autosuggestion
Version:
  Generates suggestions for text completion.  
234 lines • 12.4 kB
JavaScript
import { Dictionary } from './dictionary';
import { Node } from './node';
import { Suggestion } from './suggestion';
import { LookupNode } from './lookup';
import { simplify } from './test_util';
describe('Trie', function () {
describe('.add(...)', function () {
it.skip('normalizes the input and inserts the pattern', function () { });
it('adds two single-word patterns, where the first is a substring of the second', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var expectations = [' ', 'a', 'r', 't', 'f', 'u', 'l'];
trie.add(['art']);
trie.add(['artful']);
expect(simplify(trie)).toEqual(expectations);
expect(trie.next.word['a'].next.char['r'].next.char['t'].end).toBeTruthy();
expect(trie.next.word['a'].next.char['r'].next.char['t'].next.char['f'].next.char['u'].next.char['l'].end).toBeTruthy();
});
it('adds two single-word patterns, where the second is a substring of the first', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var expectations = [' ', 'a', 'r', 't', 'f', 'u', 'l'];
trie.add(['artful']);
trie.add(['art']);
expect(simplify(trie)).toEqual(expectations);
expect(trie.next.word['a'].next.char['r'].next.char['t'].end).toBeTruthy();
expect(trie.next.word['a'].next.char['r'].next.char['t'].next.char['f'].next.char['u'].next.char['l'].end).toBeTruthy();
});
it('adds multiple patterns which overlap on the first word', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('A');
trie.add(['big', 'bug']);
trie.add(['bib']);
var expectations = [' ', 'b', 'i', [['g', ' ', 'b', 'u', 'g'], ['b']]];
expect(simplify(trie)).toEqual(expectations);
});
});
describe('._add(...)', function () {
it('adds a single pattern of a single word', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var pattern = ['acab'];
var expectations = ['a', 'c', 'a', 'b'];
trie['_add'](trie, pattern);
expect(simplify(trie)).toEqual(expectations);
});
it('adds a single pattern of multiple words', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var pattern = ['acab', 'or', 'acai'];
var expectations = ['a', 'c', 'a', 'b', ' ', 'o', 'r', ' ', 'a', 'c', 'a', 'i'];
trie['_add'](trie, pattern);
expect(simplify(trie)).toEqual(expectations);
});
it('adds a single pattern of a single lookup', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var frog = dictionary.define('frog');
var turtle = dictionary.define('turtle');
var pattern = [{ critters: ['frog', 'turtle'] }];
var expectations = [{ critters: [frog, turtle] }];
trie['_add'](trie, pattern);
expect(simplify(trie)).toEqual(expectations);
});
it('adds a single pattern of multiple lookups', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var frog = dictionary.define('frog');
var turtle = dictionary.define('turtle');
var emerald = dictionary.define('emerald');
var topaz = dictionary.define('topaz');
var pattern = [{ critters: ['frog', 'turtle'] }, { stones: ['emerald', 'topaz'] }];
var expectations = [{ critters: [frog, turtle] }, { stones: [emerald, topaz] }];
trie['_add'](trie, pattern);
expect(simplify(trie)).toEqual(expectations);
});
it('adds multiple patterns of a single word', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var patterns = [['acab'], ['acai']];
var expectations = ['a', 'c', 'a', [['b'], ['i']]];
trie['_add'](trie, patterns[0]);
trie['_add'](trie, patterns[1]);
expect(simplify(trie)).toEqual(expectations);
});
it('adds multiple patterns of multiple words', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var patterns = [['ab', 'cd'], ['about', 'u']];
var expectations = ['a', 'b', [['o', 'u', 't', ' ', 'u'], [' ', 'c', 'd']]];
trie['_add'](trie, patterns[0]);
trie['_add'](trie, patterns[1]);
expect(simplify(trie)).toEqual(expectations);
});
it('adds multiple patterns of a single lookup', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var pizza = dictionary.define('pizza');
var mold = dictionary.define('mold');
var patterns = [[{ food: ['pizza'] }], [{ slime: ['mold'] }]];
var expectations = [[[{ food: [pizza] }], [{ slime: [mold] }]]];
trie['_add'](trie, patterns[0]);
trie['_add'](trie, patterns[1]);
expect(simplify(trie)).toEqual(expectations);
});
it('adds multiple patterns of multiple lookups', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var pizza = dictionary.define('pizza');
var blue = dictionary.define('blue');
var mold = dictionary.define('mold');
var leisure = dictionary.define('leisure');
var patterns = [[{ food: ['pizza'] }, { colors: ['blue'] }], [{ slime: ['mold'] }, { enjoyment: ['leisure'] }]];
var expectations = [[[{ food: [pizza] }, { colors: [blue] }], [{ slime: [mold] }, { enjoyment: [leisure] }]]];
trie['_add'](trie, patterns[0]);
trie['_add'](trie, patterns[1]);
expect(simplify(trie)).toEqual(expectations);
});
});
describe('_addFirstCharOfNextWord', function () {
it('adds the first character of a word to node.next.word and returns the char node', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var word = ['bat'];
var expectation = { node: new Node('b'), pattern: ['at'] };
var result = trie['_addFirstCharOfNextWord'](trie, word);
expect(result).toEqual(expectation);
expect(result.node.end).toBeFalsy();
});
it('adds the first character of a single char word to node.next.word and returns the char node', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var word = ['b'];
var expectation = { node: new Node('b'), pattern: [] };
expectation.node.end = true;
var result = trie['_addFirstCharOfNextWord'](trie, word);
expect(result).toEqual(expectation);
expect(result.node.end).toBeTruthy();
});
it('returns the char node if the first character of a word already exists in node.next.word', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var _a = trie['_addFirstCharOfNextWord'](trie, ['bop']), exists = _a.node, pattern = _a.pattern;
trie['_addChars'](exists, pattern[0]); // just use this as a shortcut.
var word = ['bat'];
var expectation = { node: exists, pattern: ['at'] };
var result = trie['_addFirstCharOfNextWord'](trie, word);
expect(result).toEqual(expectation);
expect(result.node.end).toBeFalsy();
expect(simplify(trie)).toEqual([' ', 'b', 'o', 'p']);
});
});
describe('_addChars(...)', function () {
it('adds a word to the provided node', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var word = 'mold';
var expectation = new Node('d');
expectation.end = true;
expect(trie['_addChars'](trie, word)).toEqual(expectation);
expect(simplify(trie)).toEqual(['m', 'o', 'l', 'd']);
});
it('adds multiple words, forming a diverging path', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var words = ['fungi', 'funguy'];
var expectation = ['f', 'u', 'n', 'g', [['i'], ['u', 'y']]];
trie['_addChars'](trie, words[0]);
trie['_addChars'](trie, words[1]);
expect(simplify(trie)).toEqual(expectation);
expect(trie.next.char['f'].next.char['u'].next.char['n'].next.char['g'].next.char['i'].end).toBeTruthy();
expect(trie.next.char['f'].next.char['u'].next.char['n'].next.char['g'].next.char['u'].next.char['y'].end).toBeTruthy();
});
it('adds multiple words, where one word is a substr of the other', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var words = ['fun', 'fungi'];
var expectation = ['f', 'u', 'n', 'g', 'i'];
trie['_addChars'](trie, words[0]);
trie['_addChars'](trie, words[1]);
expect(simplify(trie)).toEqual(expectation);
expect(trie.next.char['f'].next.char['u'].next.char['n'].end).toBeTruthy();
});
});
describe('_addLookup(...)', function () {
it('adds a single lookup with a single context to a node', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var mammalTrie = dictionary.define('mammals');
var lookup = { animals: 'mammals' };
var expectation = new LookupNode('animals', [mammalTrie]);
expectation.end = true;
expect(trie['_addLookup'](trie, lookup)).toEqual([expectation]);
expect(Object.keys(trie.next.lookup)).toEqual(['animals']);
expect(Object.values(trie.next.lookup)).toEqual([expectation]);
});
it('adds a single lookup with multiple contexts to a node', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test');
var mammalsTrie = dictionary.define('mammals');
var bugsTrie = dictionary.define('bugs');
var lookup = { animals: ['mammals', 'bugs'] };
var expectation = new LookupNode('animals', [mammalsTrie, bugsTrie]);
expectation.end = true;
expect(trie['_addLookup'](trie, lookup)).toEqual([expectation]);
expect(Object.keys(trie.next.lookup)).toEqual(['animals']);
expect(Object.values(trie.next.lookup)).toEqual([expectation]);
});
});
describe('suggest(...)', function () {
it.todo('works.');
it('adds two single-word patterns, where one is a substring of the other', function () {
var dictionary = new Dictionary();
var trie = dictionary.define('test', [['artful'], ['art']]);
var expectations = [
new Suggestion(['art']),
new Suggestion(['artful']),
];
expect(trie.suggest('a')).toEqual(expectations);
});
it('returns multiple suggestions, given a full word match that is a subset of another match in a sub-context', function () {
var dictionary = new Dictionary();
var a = dictionary.define('A', [['a'], ['an']]);
var b = dictionary.define('B', [['b'], ['bb']]);
var c = dictionary.define('C', [[{ A: 'A' }, { B: 'B' }]]);
var expectation = [
new Suggestion(['a', { B: [b] }]),
new Suggestion(['an', { B: [b] }]),
];
expect(c.suggest('a')).toEqual(expectation);
});
});
});
//# sourceMappingURL=trie.test.js.map