UNPKG

@platform/cell.schema

Version:

URI and database schemas for the `cell.os`.

247 lines (246 loc) 10.5 kB
import { expect, fs } from '../test'; import { Links } from '.'; describe('Links', () => { describe('encoding', () => { it('encodeKey => decodeKey', () => { const test = (input, encoded) => { const res = { encoded: Links.encodeKey(input), decoded: Links.decodeKey(Links.encodeKey(input)), }; expect(res.encoded).to.eql(encoded); expect(res.decoded).to.eql(input); }; test('foo', 'foo'); test('foo|bar', 'foo|bar'); test('[foo]', '[foo]'); test('.foo', ':foo'); test('[.foo]', '[:foo]'); test('foo.png', 'foo:png'); test('foo.bar.baz', 'foo:bar:baz'); test('foo/bar', 'foo::bar'); test('foo/bar/baz', 'foo::bar::baz'); test('.foo.', ':foo:'); test('..foo...', '[::]foo[:::]'); test('...foo.', '[:::]foo:'); test('...foo.png', '[:::]foo:png'); test('...foo/bar..png', '[:::]foo::bar[::]png'); test('[..]foo[...]', '[[::]]foo[[:::]]'); }); it('toKey (encoded)', () => { const test = (prefix, input, output) => { const res1 = Links.toKey(prefix, input); const res2 = Links.create(prefix).toKey(input); expect(res1).to.eql(output); expect(res2).to.eql(output); }; test('ref', 'foo', 'ref:foo'); test('fs', 'foo', 'fs:foo'); test('fs:', 'foo', 'fs:foo'); test('fs:::', 'foo', 'fs:foo'); test(' fs ', 'foo', 'fs:foo'); test(' fs:: ', 'foo', 'fs:foo'); test('fs', 'foo.png', 'fs:foo:png'); test('fs', '/foo.png', 'fs:foo:png'); test('fs', '//foo.png', 'fs:foo:png'); test('fs', 'fs.foo.png', 'fs:fs:foo:png'); test('fs', 'cat&bird.png', 'fs:cat&bird:png'); test('fs', 'foo/bar.png', 'fs:foo::bar:png'); test('fs', 'foo/bar/zoo.png', 'fs:foo::bar::zoo:png'); test('fs', '/foo/bar.png', 'fs:foo::bar:png'); test('fs', '///foo/bar.png', 'fs:foo::bar:png'); test('fs', 'foo/bar/', 'fs:foo::bar'); test('fs', 'foo/bar.png/', 'fs:foo::bar:png'); }); it('toKey: throw if empty', () => { const test = (input) => { const fn = () => Links.toKey('prefix', input); expect(fn).to.throw(/Link key must have a value/); }; test(); test(''); test(' '); }); }); it('isKey', () => { const test = (prefix, key, expected) => { const res1 = Links.isKey(prefix, key); const res2 = Links.create(prefix).isKey(key); expect(res1).to.eql(expected); expect(res2).to.eql(expected); }; test('ref', undefined, false); test('ref', '', false); test('ref', ' ', false); test('ref', 'ref:func:wasm', true); test('fs', ' fs:func:wasm ', true); }); it('total', () => { const test = (prefix, links, expected) => { const res1 = Links.total(prefix, links); const res2 = Links.create(prefix).total(links); expect(res1).to.eql(expected); expect(res2).to.eql(expected); }; test('ref', undefined, 0); test('ref', {}, 0); test('ref', { foo: 'bar' }, 0); test('ref', { 'ref:foo:png': '...' }, 1); test('ref', { foo: 'bar', 'ref:foo:png': '...' }, 1); test('ref', { foo: 'bar', 'ref:file1:png': '...', 'ref:file2:jpg': '...', }, 2); }); describe('parseKey', () => { it('name', () => { const prefix = 'foo'; const key = Links.toKey(prefix, 'image.png'); const res = Links.parseKey(prefix, ` ${key} `); expect(res.prefix).to.eql(prefix); expect(res.key).to.eql(key); expect(res.path).to.eql('image.png'); expect(res.name).to.eql('image.png'); expect(res.dir).to.eql(''); expect(res.ext).to.eql('png'); }); it('path: dir/name', () => { const prefix = 'foo'; const key = Links.toKey(prefix, '///foo/bar/image.png'); const res = Links.parseKey(prefix, ` ${key} `); expect(res.key).to.eql(key); expect(res.path).to.eql('foo/bar/image.png'); expect(res.name).to.eql('image.png'); expect(res.dir).to.eql('foo/bar'); expect(res.ext).to.eql('png'); }); it('path variants', () => { const test = (prefix, input, path) => { const res = Links.create(prefix).parseKey(input); expect(res.key).to.eql(input.trim()); expect(res.path).to.eql(path); expect(res.name).to.eql(fs.basename(res.path)); expect(res.dir).to.eql(fs.dirname(res.path).replace(/^\./, '')); expect(res.ext).to.eql(fs.extname(res.path).replace(/^\./, '')); }; test('ref', 'ref:foo', 'foo'); test('fs', 'fs:foo:png', 'foo.png'); test('fs', 'fs:fs:foo:png', 'fs.foo.png'); test('fs', 'fs:foo::bar:png', 'foo/bar.png'); test('fs', 'fs:foo::bar::zoo:png', 'foo/bar/zoo.png'); test('fs', 'fs:[::]foo:png', '..foo.png'); test('fs', 'fs:foo[::]png', 'foo..png'); }); }); describe('parseValue', () => { it('uri', () => { const res = Links.parseValue(' cell:foo:A1 ? '); expect(res.value).to.eql('cell:foo:A1'); expect(res.uri.type).to.eql('CELL'); expect(res.uri.ns).to.eql('foo'); expect(res.uri.key).to.eql('A1'); expect(res.query).to.eql({}); }); it('query', () => { const res1 = Links.parseValue('cell:foo:A1'); expect(res1.query).to.eql({}); const res2 = Links.parseValue(' cell:foo:A1 ? '); expect(res2.query).to.eql({}); const res3 = Links.parseValue('cell:foo:A1?color=red&isEnabled=true'); const res4 = Links.parseValue(' cell:foo:A1 ? color=red&isEnabled=true '); expect(res3.query).to.eql({ color: 'red', isEnabled: true }); expect(res4.query).to.eql(res3.query); }); }); describe('parse (key:value)', () => { it('combines [parseKey] and [parseValue]', () => { const prefix = 'p'; const linkKey = 'p:bar/baz.t'; const linkValue = 'cell:foo:A1?hash=abc'; const key = Links.parseKey(prefix, linkKey); const value = Links.parseValue(linkValue); const res1 = Links.parseLink(prefix, linkKey, linkValue); const res2 = Links.create(prefix).parse(linkKey, linkValue); expect(JSON.stringify(res1)).to.eql(JSON.stringify(res2)); expect(JSON.stringify(res1)).to.eql(JSON.stringify(Object.assign(Object.assign({}, key), value))); }); }); describe('toList', () => { it('empty', () => { const test = (links) => { const res1 = Links.toList('prefix', links); const res2 = Links.create('prefix').toList(links); expect(res1).to.eql([]); expect(res2).to.eql([]); }; test(); test({}); test({ 'SOMETHING:ELSE': 'foo' }); }); it('converts to list', () => { const keys = { 'fs:main:js': 'file:foo:abc123?status=uploading', 'fs:images/foo/kitten:png': 'file:foo:def456?hash=sha256-abc', 'NO:MATCH': '<something>', }; const list = Links.create('fs').toList(keys); expect(list.length).to.eql(2); expect(list[0].key).to.eql('fs:main:js'); expect(list[0].value).to.eql('file:foo:abc123?status=uploading'); expect(list[1].key).to.eql('fs:images/foo/kitten:png'); expect(list[1].value).to.eql('file:foo:def456?hash=sha256-abc'); }); }); describe('find: byName', () => { const LINKS = { 'fs:main:js': 'file:foo:abc', 'ref:foo::bar::zoo:png': 'cell:foo:A1', 'ref:foo::bar::baz:jpg': 'cell:foo:A2', }; it('not found', () => { const test = (prefix, path) => { const res1 = Links.find(prefix, LINKS).byName(path); const res2 = Links.create(prefix) .find(LINKS) .byName(path); expect(res1).to.eql(undefined); expect(res2).to.eql(undefined); }; test('', ''); test('', undefined); test('fs', ''); test('fs', undefined); test('fs', 'main.js/'); test('ref', 'foo::bar::zoo:png'); }); it('found', () => { const test = (prefix, path, expected) => { var _a, _b; const res1 = Links.find(prefix, LINKS).byName(path); const res2 = Links.create(prefix) .find(LINKS) .byName(path); expect((_a = res1) === null || _a === void 0 ? void 0 : _a.value).to.eql(expected, path); expect((_b = res2) === null || _b === void 0 ? void 0 : _b.value).to.eql(expected, path); }; test('fs', 'main.js', 'file:foo:abc'); test('fs', '/main.js', 'file:foo:abc'); test('ref', 'foo/bar/zoo.png', 'cell:foo:A1'); test('ref', '///foo/bar/zoo.png', 'cell:foo:A1'); test('fs', '*.js', 'file:foo:abc'); test('ref', 'foo/bar*', 'cell:foo:A1'); test('ref', 'foo/bar*.jpg', 'cell:foo:A2'); }); }); describe('error', () => { it('toKey: throw if contains ":"', () => { const fn = () => Links.toKey('foo', 'foo:bar.png'); expect(fn).to.throw(/cannot contain ":" character/); }); it('encode: throw if contains ":"', () => { const fn = () => Links.encodeKey('foo:bar.png'); expect(fn).to.throw(/cannot contain ":" character/); }); }); });