UNPKG

elliptical

Version:

Interactive natural-language interfaces

539 lines (495 loc) 12.8 kB
/** @jsx createElement */ /* eslint-env mocha */ import createElement from '../src/element' import unique from '../src/unique' import {compileAndTraverse} from './_util' import { expect } from 'chai' describe('repeat', () => { describe('separator', () => { it('does not accept input that does not match the child', () => { const grammar = ( <repeat separator={<literal text='man' />}> <literal text='super' /> </repeat> ) const options = compileAndTraverse(grammar, 'wrong') expect(options).to.eql([]) }) it('accepts the child on its own', () => { const grammar = ( <repeat separator={<literal text='man' />}> <literal text='super' /> </repeat> ) const options = compileAndTraverse(grammar, 'superm') expect(options).to.eql([{ text: null, words: [ {text: 'super', input: true}, {text: 'm', input: true}, {text: 'an', input: false}, {text: 'super', input: false} ], result: [undefined, undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('accepts the child twice, with the separator in the middle', () => { const grammar = ( <repeat separator={<literal text='man' />}> <literal text='super' /> </repeat> ) const options = compileAndTraverse(grammar, 'supermans') expect(options).to.eql([{ text: null, words: [ {text: 'super', input: true}, {text: 'man', input: true}, {text: 's', input: true}, {text: 'uper', input: false} ], result: [undefined, undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('accepts the child twice and suggests when complete, with the separator in the middle', () => { const grammar = ( <repeat separator={<literal text='man' />}> <literal text='super' /> </repeat> ) const options = compileAndTraverse(grammar, 'supermansuper') expect(options).to.eql([{ text: '', words: [ {text: 'super', input: true}, {text: 'man', input: true}, {text: 'super', input: true} ], result: [undefined, undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }, { text: null, words: [ {text: 'super', input: true}, {text: 'man', input: true}, {text: 'super', input: true}, {text: 'man', input: false}, {text: 'super', input: false} ], result: [undefined, undefined, undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('allows for content to have children', () => { const grammar = ( <repeat separator={<literal text=' ' />}> <choice> <literal text='a' /> <literal text='b' /> </choice> </repeat> ) const options = compileAndTraverse(grammar, 'a ') expect(options).to.eql([{ text: null, words: [ {text: 'a', input: true}, {text: ' ', input: true}, {text: 'a', input: false} ], result: [undefined, undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }, { text: null, words: [ {text: 'a', input: true}, {text: ' ', input: true}, {text: 'b', input: false} ], result: [undefined, undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) }) it('allows for content to have children', () => { const grammar = ( <repeat> <choice> <literal text='a' /> <literal text='b' /> </choice> </repeat> ) const options = compileAndTraverse(grammar, '') expect(options).to.eql([{ text: null, words: [{text: 'a', input: false}], result: [undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }, { text: null, words: [{text: 'b', input: false}], result: [undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('does not accept input that does not match the child', () => { const grammar = ( <repeat> <literal text='super' /> </repeat> ) const options = compileAndTraverse(grammar, 'wrong') expect(options).to.eql([]) }) it('accepts the child on its own', () => { const grammar = ( <repeat> <literal text='super' value='a' /> </repeat> ) const options = compileAndTraverse(grammar, 'sup') expect(options).to.eql([{ text: null, words: [{text: 'sup', input: true}, {text: 'er', input: false}], result: ['a'], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('accepts the child twice', () => { const grammar = ( <repeat> <literal text='super' value='a' /> </repeat> ) const options = compileAndTraverse(grammar, 'supers') expect(options).to.eql([{ text: null, words: [ {text: 'super', input: true}, {text: 's', input: true}, {text: 'uper', input: false} ], result: ['a', 'a'], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('accepts the child thrice', () => { const grammar = ( <repeat> <literal text='super' value='a' /> </repeat> ) const options = compileAndTraverse(grammar, 'supersuper') expect(options).to.eql([{ text: '', words: [ {text: 'super', input: true}, {text: 'super', input: true} ], result: ['a', 'a'], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }, { text: null, words: [ {text: 'super', input: true}, {text: 'super', input: true}, {text: 'super', input: false} ], result: ['a', 'a', 'a'], score: 1, categories: [], arguments: [], qualifiers: [], annotations:[], data: [] }]) }) it('does not accept fewer than min iterations', () => { const grammar = ( <repeat min={2}> <literal text='a' value='a' /> </repeat> ) const options = compileAndTraverse(grammar, 'a') expect(options).to.eql([{ text: null, words: [ {text: 'a', input: true}, {text: 'a', input: false} ], result: ['a', 'a'], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('does not accept more than max iterations', () => { const grammar = ( <repeat max={1} > <literal text='a' value='a' /> </repeat> ) const options = compileAndTraverse(grammar, 'a') expect(options).to.eql([{ text: '', words: [ {text: 'a', input: true} ], result: ['a'], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('unique rejects non-unique repeated elements', () => { const grammar = ( <repeat unique> <choice> <literal text='a' value='1' /> <literal text='b' value='1' /> </choice> </repeat> ) const options = compileAndTraverse(grammar, 'ab') expect(options).to.eql([]) }) it('unique rejects non-unique repeated elements (using symbol)', () => { const grammar = ( <repeat unique> <choice> <literal text='a' value={{val: 1, [unique]: 'test'}} /> <literal text='b' value={{val: 2, [unique]: 'test'}} /> </choice> </repeat> ) const options = compileAndTraverse(grammar, 'ab') expect(options).to.eql([]) }) it('unique accepts non-unique repeated elements (using symbol)', () => { const grammar = ( <repeat unique> <choice> <literal text='a' value={{val: 2, [unique]: '1'}} /> <literal text='b' value={{val: 2, [unique]: 'test'}} /> </choice> </repeat> ) const options = compileAndTraverse(grammar, 'ab') expect(options).to.eql([{ text: '', words: [ {text: 'a', input: true}, {text: 'b', input: true} ], result: [{val: 2}, {val: 2}], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('unique rejects non-unique repeated elements (deep)', () => { const grammar = ( <repeat unique> <choice> <literal text='a' value={{a: 1}} /> <literal text='b' value={{a: 1}} /> </choice> </repeat> ) const options = compileAndTraverse(grammar, 'ab') expect(options).to.eql([]) }) it('unique accepts unique repeated elements', () => { const grammar = ( <repeat unique> <choice> <literal text='a' value='a' /> <literal text='b' value='b' /> </choice> </repeat> ) const options = compileAndTraverse(grammar, 'ab') expect(options).to.eql([{ text: '', words: [ {text: 'a', input: true}, {text: 'b', input: true} ], result: ['a', 'b'], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('unique accepts unique repeated elements (deep)', () => { const grammar = ( <repeat unique> <choice> <literal text='a' value={{a: 1}} /> <literal text='b' value={{a: 2}} /> </choice> </repeat> ) const options = compileAndTraverse(grammar, 'ab') expect(options).to.eql([{ text: '', words: [ {text: 'a', input: true}, {text: 'b', input: true} ], result: [{a: 1}, {a: 2}], score: 1, categories: [], arguments: [], qualifiers: [], annotations:[], data: [] }]) }) it('allows for choices inside of repeats to be limited', () => { const grammar = ( <repeat> <choice limit={1}> <literal text='aa' /> <literal text='ab' /> <literal text='ac' /> </choice> </repeat> ) const options = compileAndTraverse(grammar, 'aba') expect(options).to.eql([{ text: null, words: [ {text: 'ab', input: true}, {text: 'a', input: true}, {text: 'a', input: false} ], result: [undefined, undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('allows for choices inside of repeat separators to be limited', () => { const grammar = ( <repeat separator={ <choice limit={1}> <literal text='aa' /> <literal text='ab' /> <literal text='ac' /> </choice> }> <literal text='x' /> </repeat> ) const options = compileAndTraverse(grammar, 'xa') expect(options).to.eql([{ text: null, words: [ {text: 'x', input: true}, {text: 'a', input: true}, {text: 'a', input: false}, {text: 'x', input: false} ], result: [undefined, undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [] }]) }) it('works with data', () => { const grammar = <repeat data={1}><literal text='x ' data={2} /></repeat> const options = compileAndTraverse(grammar, 'x x') expect(options).to.eql([{ text: null, words: [ {text: 'x ', input: true}, {text: 'x', input: true}, {text: ' ', input: false}, ], result: [undefined, undefined], score: 1, qualifiers: [], categories: [], arguments: [], annotations:[], data: [1, 2, 2] }]) }) })