| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- import {expect} from 'chai';
- import {PathTrie} from './path-trie.js';
- import {format} from '@e22m4u/js-format';
- import {pathToRegexp} from 'path-to-regexp';
- const VALUE = 'myValue1';
- const ANOTHER_VALUE = 'myValue2';
- describe('PathTrie', function () {
- describe('add', function () {
- it('requires the first parameter to be a String', function () {
- const trie = new PathTrie();
- const throwable = v => () => trie.add(v, VALUE);
- const error = v =>
- format(
- 'The first argument of PathTrie.add must be a String, ' +
- 'but %s was given.',
- v,
- );
- expect(throwable(10)).to.throw(error('10'));
- expect(throwable(0)).to.throw(error('0'));
- expect(throwable(true)).to.throw(error('true'));
- expect(throwable(false)).to.throw(error('false'));
- expect(throwable(null)).to.throw(error('null'));
- expect(throwable({})).to.throw(error('Object'));
- expect(throwable([])).to.throw(error('Array'));
- expect(throwable(undefined)).to.throw(error('undefined'));
- throwable('str')();
- throwable('')();
- });
- it('requires the second parameter', function () {
- const throwable = v => () => {
- const trie = new PathTrie();
- trie.add('foo', v);
- };
- const error = v =>
- format(
- 'The second argument of PathTrie.add is required, but %s was given.',
- v,
- );
- expect(throwable(undefined)).to.throw(error('undefined'));
- expect(throwable(null)).to.throw(error('null'));
- throwable('str')();
- throwable('')();
- throwable(10)();
- throwable(0)();
- throwable(true)();
- throwable(false)();
- throwable({})();
- throwable([])();
- });
- it('adds the given value with the path "" to the root node', function () {
- const trie = new PathTrie();
- expect(trie['_root']).to.be.eql({
- token: '',
- regexp: undefined,
- names: [],
- value: undefined,
- children: {},
- });
- trie.add('', VALUE);
- expect(trie['_root']).to.be.eql({
- token: '',
- regexp: undefined,
- names: [],
- value: VALUE,
- children: {},
- });
- });
- it('adds the given value with the path "/" to the root node', function () {
- const trie = new PathTrie();
- expect(trie['_root']).to.be.eql({
- token: '',
- regexp: undefined,
- names: [],
- value: undefined,
- children: {},
- });
- trie.add('/', VALUE);
- expect(trie['_root']).to.be.eql({
- token: '',
- regexp: undefined,
- names: [],
- value: VALUE,
- children: {},
- });
- });
- it('throws an error for the duplicate path "" with a different value', function () {
- const trie = new PathTrie();
- trie.add('', VALUE);
- const throwable = () => trie.add('', ANOTHER_VALUE);
- expect(throwable).to.throw(
- 'The duplicate path "" has a different value.',
- );
- });
- it('throws an error for the duplicate path "/" with a different value', function () {
- const trie = new PathTrie();
- trie.add('/', VALUE);
- const throwable = () => trie.add('/', ANOTHER_VALUE);
- expect(throwable).to.throw(
- 'The duplicate path "" has a different value.',
- );
- });
- it('considers paths "" and "/" are the same', function () {
- const trie = new PathTrie();
- trie.add('', VALUE);
- const throwable = () => trie.add('/', ANOTHER_VALUE);
- expect(throwable).to.throw(
- 'The duplicate path "" has a different value.',
- );
- });
- it('adds multiple nodes by the path which has multiple tokens', function () {
- const trie = new PathTrie();
- trie.add('foo/bar/baz', VALUE);
- expect(trie['_root']).to.be.eql({
- token: '',
- regexp: undefined,
- names: [],
- value: undefined,
- children: {
- foo: {
- token: 'foo',
- regexp: undefined,
- names: [],
- value: undefined,
- children: {
- bar: {
- token: 'bar',
- regexp: undefined,
- names: [],
- value: undefined,
- children: {
- baz: {
- token: 'baz',
- regexp: undefined,
- names: [],
- value: VALUE,
- children: {},
- },
- },
- },
- },
- },
- },
- });
- });
- it('resolves path parameters in the first node', function () {
- const trie = new PathTrie();
- trie.add(':date-:time', VALUE);
- expect(trie['_root']).to.be.eql({
- token: '',
- regexp: undefined,
- names: [],
- value: undefined,
- children: {
- ':date-:time': {
- token: ':date-:time',
- regexp: pathToRegexp(':date-:time').regexp,
- names: ['date', 'time'],
- value: VALUE,
- children: {},
- },
- },
- });
- });
- it('resolves path parameters in the middle node', function () {
- const trie = new PathTrie();
- trie.add('/foo/:id/bar', VALUE);
- expect(trie['_root']).to.be.eql({
- token: '',
- regexp: undefined,
- names: [],
- value: undefined,
- children: {
- foo: {
- token: 'foo',
- regexp: undefined,
- names: [],
- value: undefined,
- children: {
- ':id': {
- token: ':id',
- regexp: pathToRegexp(':id').regexp,
- names: ['id'],
- value: undefined,
- children: {
- bar: {
- token: 'bar',
- regexp: undefined,
- names: [],
- value: VALUE,
- children: {},
- },
- },
- },
- },
- },
- },
- });
- });
- it('throws an error for unsupported modifiers', function () {
- const modifiers = ['?', '*', '+', '{', '}'];
- const trie = new PathTrie();
- const throwable = v => () => trie.add(v, VALUE);
- const error = v =>
- format('The symbol %v is not supported in path "/foo/:id%s".', v, v);
- modifiers.forEach(m => {
- expect(throwable(`/foo/:id${m}`)).to.throw(error(m));
- });
- });
- it('throws an error if no parameter name has specified', function () {
- const trie = new PathTrie();
- const throwable = () => trie.add('/:', VALUE);
- expect(throwable).to.throw(
- 'The symbol ":" should be used to define path parameters, ' +
- 'but no parameters were found in the path "/:".',
- );
- });
- it('does not overrides value when set another one to the middle', function () {
- const trie = new PathTrie();
- trie.add('/foo/bar/baz', VALUE);
- trie.add('/foo/bar', ANOTHER_VALUE);
- expect(trie['_root']).to.be.eql({
- token: '',
- regexp: undefined,
- names: [],
- value: undefined,
- children: {
- foo: {
- token: 'foo',
- regexp: undefined,
- names: [],
- value: undefined,
- children: {
- bar: {
- token: 'bar',
- regexp: undefined,
- names: [],
- value: ANOTHER_VALUE,
- children: {
- baz: {
- token: 'baz',
- regexp: undefined,
- names: [],
- value: VALUE,
- children: {},
- },
- },
- },
- },
- },
- },
- });
- });
- });
- describe('match', function () {
- it('requires the first parameter to be a String', function () {
- const trie = new PathTrie();
- const throwable = v => () => trie.match(v);
- const error = v =>
- format(
- 'The first argument of PathTrie.match must be ' +
- 'a String, but %s was given.',
- v,
- );
- expect(throwable(10)).to.throw(error('10'));
- expect(throwable(0)).to.throw(error('0'));
- expect(throwable(true)).to.throw(error('true'));
- expect(throwable(false)).to.throw(error('false'));
- expect(throwable(null)).to.throw(error('null'));
- expect(throwable({})).to.throw(error('Object'));
- expect(throwable([])).to.throw(error('Array'));
- expect(throwable(undefined)).to.throw(error('undefined'));
- throwable('str')();
- throwable('')();
- });
- it('matches paths "" and "/" or returns undefined', function () {
- const trie = new PathTrie();
- trie.add('', VALUE);
- const res1 = trie.match('');
- const res2 = trie.match('/');
- const res3 = trie.match('/test');
- expect(res1).to.be.eql({value: VALUE, params: {}});
- expect(res2).to.be.eql({value: VALUE, params: {}});
- expect(res3).to.be.undefined;
- });
- it('returns undefined if not matched', function () {
- const trie = new PathTrie();
- trie.add('foo', VALUE);
- const res = trie.match('bar');
- expect(res).to.be.undefined;
- });
- it('matches the single token', function () {
- const trie = new PathTrie();
- trie.add('foo', VALUE);
- const res = trie.match('foo');
- expect(res).to.be.eql({value: VALUE, params: {}});
- });
- it('does not respects the prefix "/"', function () {
- const trie = new PathTrie();
- trie.add('/foo', VALUE);
- const res1 = trie.match('/foo');
- const res2 = trie.match('foo');
- expect(res1).to.be.eql({value: VALUE, params: {}});
- expect(res2).to.be.eql({value: VALUE, params: {}});
- });
- it('does not respects the postfix "/"', function () {
- const trie = new PathTrie();
- trie.add('/foo', VALUE);
- const res1 = trie.match('foo/');
- const res2 = trie.match('foo');
- expect(res1).to.be.eql({value: VALUE, params: {}});
- expect(res2).to.be.eql({value: VALUE, params: {}});
- });
- it('matches parameters of the first token', function () {
- const trie = new PathTrie();
- trie.add(':foo-:bar', VALUE);
- const res = trie.match('baz-qux');
- expect(res).to.be.eql({
- value: VALUE,
- params: {
- foo: 'baz',
- bar: 'qux',
- },
- });
- });
- it('matches parameters of the first token in the case of multiple tokens', function () {
- const trie = new PathTrie();
- trie.add(':foo-:bar/test', VALUE);
- const res = trie.match('baz-qux/test');
- expect(res).to.be.eql({
- value: VALUE,
- params: {
- foo: 'baz',
- bar: 'qux',
- },
- });
- });
- it('matches parameters of the second token', function () {
- const trie = new PathTrie();
- trie.add('/test/:foo-:bar', VALUE);
- const res = trie.match('/test/baz-qux');
- expect(res).to.be.eql({
- value: VALUE,
- params: {
- foo: 'baz',
- bar: 'qux',
- },
- });
- });
- it('does not match a path which has more tokens than needed', function () {
- const trie = new PathTrie();
- trie.add('/foo', VALUE);
- const res = trie.match('/foo/bar');
- expect(res).to.be.undefined;
- });
- it('does not match a path which has less tokens than needed', function () {
- const trie = new PathTrie();
- trie.add('/foo/bar', VALUE);
- const res = trie.match('/foo');
- expect(res).to.be.undefined;
- });
- });
- });
|