elliptical-extend
Version:
Linguistic Extension for Elliptical phrases
343 lines (297 loc) • 8.4 kB
JSX
/** @jsx createElement */
/* eslint-env mocha */
import _ from 'lodash'
import { createElement, compile } from 'elliptical'
import { text, compileAndTraverse } from './_util'
import { expect } from 'chai'
describe('extends', () => {
it('allows phrases that return null (for classes to be extended)', () => {
const Noop = {
describe () {
return null
}
}
const data = compileAndTraverse(<Noop />, '')
expect(data).to.have.length(0)
})
it('handles phrases that return null to be extended', () => {
const Noop = {
id: 'noop',
describe () {
return null
}
}
const Extender = {
extends: [Noop],
describe () {
return <literal text='test' />
}
}
const data = compileAndTraverse(<Noop />, '', [Extender])
expect(data).to.have.length(1)
expect(text(data[0])).to.equal('test')
})
it('matches phrases that do not have an id', () => {
const Noop = {
describe () {
return null
}
}
const Extender = {
extends: [Noop],
describe () {
return <literal text='test' />
}
}
const data = compileAndTraverse(<Noop />, '', [Extender])
expect(data).to.have.length(1)
expect(text(data[0])).to.equal('test')
})
it('handles phrases that have the same id, even if they are different instances', () => {
const NoopReal = {
id: 'noop',
describe () {
return null
}
}
const NoopFake = {
id: 'noop',
describe () {
return null
}
}
const Extender = {
extends: [NoopFake],
describe () {
return <literal text='test' />
}
}
const data = compileAndTraverse(<NoopReal />, '', [Extender])
expect(data).to.have.length(1)
expect(text(data[0])).to.equal('test')
})
it('does not match phrases if they are different and do not share id', () => {
const NoopReal = {
id: 'noop-real',
describe () {
return null
}
}
const NoopFake = {
id: 'noop-fake',
describe () {
return null
}
}
const Extender = {
extends: [NoopFake],
describe () {
return <literal text='test' />
}
}
const data = compileAndTraverse(<NoopReal />, '', [Extender])
expect(data).to.have.length(0)
})
it('handles phrases with extends', () => {
const Extended = {
id: 'extended',
describe () { return <literal text='test a' value='a' /> }
}
const Extender = {
extends: [Extended],
describe () { return <literal text='test b' value='b' /> }
}
const data = compileAndTraverse(<Extended />, '', [Extender])
expect(data).to.have.length(2)
expect(text(data[0])).to.equal('test a')
expect(data[0].result).to.equal('a')
expect(data[1].result).to.equal('b')
})
it('handles phrases extended multiple times', () => {
const Extended = {
id: 'extended',
describe () { return <literal text='test a' value='a' /> }
}
const Extender1 = {
extends: [Extended],
describe () { return <literal text='test b' value='b' /> }
}
const Extender2 = {
extends: [Extended],
describe () { return <literal text='test c' value='c' /> }
}
const data = compileAndTraverse(<Extended />, '', [Extender1, Extender2])
expect(data).to.have.length(3)
expect(text(data[0])).to.equal('test a')
expect(data[0].result).to.equal('a')
expect(text(data[1])).to.equal('test b')
expect(data[1].result).to.equal('b')
expect(text(data[2])).to.equal('test c')
expect(data[2].result).to.equal('c')
})
it('passes props to extended', () => {
const Extended = {
id: 'extended',
describe ({props}) {
expect(props.x).to.equal(1)
return <literal text='a' value='a' />
}
}
const Extender = {
extends: [Extended],
describe ({props}) {
expect(props.x).to.equal(1)
return <literal text='b' value='b' />
}
}
const data = compileAndTraverse(<Extended x={1} />, '', [Extender])
expect(data).to.have.length(2)
})
it('passes RegExp props to extended', () => {
const Extended = {
id: 'extended',
describe ({props}) {
expect(_.isRegExp(props.x)).to.be.true
expect(props.x).to.eql(/test/)
return <literal text='a' value='a' />
}
}
const Extender = {
extends: [Extended],
describe ({props}) {
expect(_.isRegExp(props.x)).to.be.true
expect(props.x).to.eql(/test/)
return <literal text='b' value='b' />
}
}
const data = compileAndTraverse(<Extended x={/test/} />, '', [Extender])
expect(data).to.have.length(2)
})
it('handles recursive phrases with extends', () => {
const Extended = {
id: 'extended',
describe ({props}) {
return (
<sequence>
<literal text='a' value='a' id='a' />
{props.allowRecurse ? <Extended allowRecurse={false} id='b' /> : null}
</sequence>
)
}
}
const Extender = {
extends: [Extended],
describe () {
return <literal text='b' value='b' />
}
}
const data = compileAndTraverse(<Extended allowRecurse />, 'ab', [Extender])
expect(data).to.have.length(1)
expect(text(data[0])).to.equal('ab')
expect(data[0].result).to.eql({a: 'a', b: 'b'})
})
it('handles phrases with extends in sequence', () => {
const Test = {
describe () {
return (
<sequence>
<literal text='test ' />
<Extended id='test' />
</sequence>
)
}
}
const Extended = {
id: 'extended',
describe () { return <literal text='a' value='a' /> }
}
const Extender = {
extends: [Extended],
describe () { return <literal text='b' value='b' /> }
}
const data = compileAndTraverse(<Test />, '', [Extender])
expect(data).to.have.length(2)
expect(text(data[0])).to.equal('test a')
expect(data[0].result.test).to.equal('a')
expect(text(data[1])).to.equal('test b')
expect(data[1].result.test).to.equal('b')
})
it('respects filterResult of extended', () => {
const Noop = {
id: 'noop',
filterResult (result) {
return result === 'test2'
},
describe () {
return null
}
}
const Extender = {
extends: [Noop],
describe () {
return <list items={[
{text: 'test1', value: 'test1'},
{text: 'test2', value: 'test2'}
]} />
}
}
const data = compileAndTraverse(<Noop />, '', [Extender])
expect(data).to.have.length(1)
expect(text(data[0])).to.equal('test2')
expect(data[0].result).to.equal('test2')
})
it('does mapResult of extended', () => {
const Extended = {
id: 'extended',
mapResult (result) {
return result + 'x'
},
describe () {
return <literal text='test1' value='test1' />
}
}
const Extender = {
extends: [Extended],
describe () {
return <literal text='test2' value='test2' />
}
}
const data = compileAndTraverse(<Extended />, '', [Extender])
expect(data).to.have.length(2)
expect(text(data[0])).to.equal('test1')
expect(data[0].result).to.equal('test1x')
expect(text(data[1])).to.equal('test2')
expect(data[1].result).to.equal('test2x')
})
it('calls mapResult of extender', () => {
const Extended = {
id: 'extended',
mapResult (result) {
return result + 'x'
},
describe () {
return <literal text='test1' value='test1' />
}
}
const Extender = {
extends: [Extended],
mapResult (result, element) {
expect(element).to.eql({
type: Extender,
props: {id: undefined},
children: []
})
return result + 'y'
},
describe () {
return <literal text='test2' value='test2' />
}
}
const data = compileAndTraverse(<Extended />, '', [Extender])
expect(data).to.have.length(2)
expect(text(data[0])).to.equal('test1')
expect(data[0].result).to.equal('test1x')
expect(text(data[1])).to.equal('test2')
expect(data[1].result).to.equal('test2yx')
})
})