neft
Version:
JavaScript. Everywhere.
394 lines (317 loc) • 11.8 kB
text/coffeescript
'use strict'
{assert, Dict, List, unit} = Neft
{describe, it} = unit
{createView, renderParse} = require './utils'
describe 'src/document string interpolation', ->
describe '`props`', ->
it 'lookup neft:fragment', ->
source = createView '''
<neft:fragment neft:name="a" x="2">${props.x}</neft:fragment>
<neft:use neft:fragment="a" />
'''
view = source.clone()
renderParse view
assert.is view.node.stringify(), '2'
it 'is accessible by context', ->
source = createView '''
<neft:fragment neft:name="a" x="2">
${this.props.x}
</neft:fragment>
<neft:use neft:fragment="a" />
'''
view = source.clone()
renderParse view
assert.is view.node.stringify(), '2'
it 'lookup neft:use', ->
source = createView '''
<neft:fragment neft:name="a" x="1">${props.x}</neft:fragment>
<neft:use neft:fragment="a" x="2" />
'''
view = source.clone()
renderParse view
assert.is view.node.stringify(), '2'
it 'always keeps proper sources order', ->
source = createView '''
<neft:fragment neft:name="a" x="1">
<neft:fragment neft:name="b" x="1">
${props.x}
</neft:fragment>
<neft:use neft:fragment="b" x="4" />
</neft:fragment>
<neft:use neft:fragment="a" x="3" />
'''
view = source.clone()
renderParse view
useA = view.node.children[0]
fragmentA = useA.children[0]
useB = fragmentA.children[0]
fragmentB = useB.children[0]
assert.is view.node.stringify(), '4'
fragmentA.attrs.set 'x', -1
useA.attrs.set 'x', -1
fragmentB.attrs.set 'x', -1
assert.is view.node.stringify(), '4'
fragmentA.attrs.set 'x', 1
useA.attrs.set 'x', 3
fragmentB.attrs.set 'x', 1
useB.attrs.set 'x', undefined
assert.is view.node.stringify(), '1'
useA.attrs.set 'x', undefined
assert.is view.node.stringify(), '1'
fragmentB.attrs.set 'x', 2
assert.is view.node.stringify(), '2'
fragmentA.attrs.set 'x', 3
assert.is view.node.stringify(), '2'
fragmentA.attrs.set 'x', undefined
assert.is view.node.stringify(), '2'
describe '`ids`', ->
it 'refers to nodes', ->
source = createView '''
<a id="first" label="12" visible="false" />
${ids.first.attrs.label}
'''
view = source.clone()
renderParse view
assert.is view.node.stringify(), '12'
view.node.children[0].attrs.set 'label', 23
assert.is view.node.stringify(), '23'
it 'is accessible by context', ->
source = createView '''
<a id="first" label="12" visible="false" />
${this.ids.first.attrs.label}
'''
view = source.clone()
renderParse view
assert.is view.node.stringify(), '12'
view.node.children[0].attrs.set 'label', 23
assert.is view.node.stringify(), '23'
it 'file `ids` are accessed in fragments', ->
source = createView '''
<a id="first" label="12" visible="false" />
<neft:fragment neft:name="a">
${ids.first.attrs.label}
</neft:fragment>
<neft:use neft:fragment="a" />
'''
view = source.clone()
renderParse view
assert.is view.node.stringify(), '12'
view.node.children[0].attrs.set 'label', 23
assert.is view.node.stringify(), '23'
describe '`root`', ->
it 'is accessed in rendered file', ->
source = createView '''
${root.a}
'''
view = source.clone()
renderParse view,
storage: a: '1'
assert.is view.node.stringify(), '1'
view.revert()
renderParse view,
storage: a: '2'
assert.is view.node.stringify(), '2'
it 'is accesible by context', ->
source = createView '''
${this.root.a}
'''
view = source.clone()
renderParse view,
storage: a: '1'
assert.is view.node.stringify(), '1'
view.revert()
renderParse view,
storage: a: '2'
assert.is view.node.stringify(), '2'
it 'lookup neft:use', ->
source = createView '''
<neft:fragment neft:name="a">${root.a}</neft:fragment>
<neft:use neft:fragment="a" />
'''
view = source.clone()
renderParse view,
storage: a: '1'
assert.is view.node.stringify(), '1'
view.revert()
renderParse view,
storage: a: '2'
assert.is view.node.stringify(), '2'
it 'lookup neft:each', ->
source = createView '''
<neft:blank neft:each="[1]">
${root.a}
</neft:blank>
'''
view = source.clone()
renderParse view,
storage: a: '1'
assert.is view.node.stringify(), '1'
view.revert()
renderParse view,
storage: a: '2'
assert.is view.node.stringify(), '2'
describe '`state`', ->
it 'is accessed in rendered file', ->
source = createView '''
<script>
this.onRender(function(){
this.state.set('a', 1);
});
</script>
${state.a}
'''
view = source.clone()
renderParse view
assert.is view.node.stringify(), '1'
it 'is accesible by context', ->
source = createView '''
<script>
this.onRender(function(){
this.state.set('a', 1);
});
</script>
${this.state.a}
'''
view = source.clone()
renderParse view
assert.is view.node.stringify(), '1'
it 'is cleared on revert', ->
source = createView '''
<script>
this.onRender(function(){
this.state.set('a', (this.state.a || 0) + 1);
});
</script>
${state.a}
'''
view = source.clone()
renderParse view
assert.is view.node.stringify(), '1'
view.revert()
renderParse view
assert.is view.node.stringify(), '1'
it 'is not accessible in not rendered document', ->
source = createView '''
<script>
this.onCreate(function(){
this.a = !!this.state;
});
</script>
${this.a}
'''
view = source.clone()
renderParse view
assert.is view.node.stringify(), 'false'
it 'handler is called on signal', ->
source = createView '''
<span x="1" onAttrsChange="${root.onAttrsChange(2)}" />
'''
view = source.clone()
calls = 0
renderParse view,
storage:
onAttrsChange: (val) ->
calls += 1
assert.is val, 2
view.node.children[0].attrs.set 'x', 2
assert.is calls, 1
it 'returned handler is called on signal with context and parameters', ->
source = createView '''
<span x="1" onAttrsChange="${root.onAttrsChange}" />
'''
view = source.clone()
calls = 0
renderParse view,
storage:
onAttrsChange: (prop, oldVal) ->
calls += 1
assert.is this, view.node.children[0]
assert.is prop, 'x'
assert.is oldVal, 1
view.node.children[0].attrs.set 'x', 2
assert.is calls, 1
it 'attribute handler is called with proper context and parameters', ->
source = createView '''
<neft:attr name="y" value="3" />
<span
x="1"
id="a1"
onAttrsChange="${root.test(ids.a1.attrs.x, props.y)}"
/>
'''
view = source.clone()
calls = 0
renderParse view,
storage:
test: (x, y) ->
calls += 1
assert.is x, 2
assert.is y, 3
view.node.query('span').attrs.set 'x', 2
assert.is calls, 1
it 'attribute handler is not called if the document is not rendered', ->
source = createView '''
<neft:attr name="y" value="3" />
<span x="1" id="a1" onAttrsChange="${root.onAttrsChange()}" />
'''
view = source.clone()
calls = 0
renderParse view,
storage:
onAttrsChange: (x, y) ->
calls += 1
view.node.query('span').attrs.set 'x', 4
assert.is calls, 1
view.revert()
view.node.query('span').attrs.set 'x', 2
assert.is calls, 1
describe 'support realtime changes', ->
it 'on `props`', ->
source = createView '''
<neft:fragment neft:name="a">${props.x}</neft:fragment>
<neft:use neft:fragment="a" x="2" y="1" />
'''
view = source.clone()
elem = view.node.children[0]
renderParse view
elem.attrs.set 'x', 1
assert.is view.node.stringify(), '1'
it 'on `root`', ->
source = createView '${root.x}'
view = source.clone()
storage = new Dict x: 1
renderParse view,
storage: storage
assert.is view.node.stringify(), '1'
storage.set 'x', 2
assert.is view.node.stringify(), '2'
it 'on `root` property', ->
source = createView '${root.dict.x}'
view = source.clone()
storage = dict: new Dict x: 1
renderParse view,
storage: storage
assert.is view.node.stringify(), '1'
storage.dict.set 'x', 2
assert.is view.node.stringify(), '2'
it 'on `root` neft:use', ->
source = createView '''
<neft:fragment neft:name="a">${root.a}</neft:fragment>
<neft:use neft:fragment="a" />
'''
view = source.clone()
renderParse view,
storage: storage = new Dict a: '1'
storage.set 'a', 2
assert.is view.node.stringify(), '2'
it 'on `root` neft:each', ->
source = createView '''
<neft:blank neft:each="[1]">
${root.a}
</neft:blank>
'''
view = source.clone()
renderParse view,
storage: storage = new Dict a: '1'
storage.set 'a', 2
assert.is view.node.stringify(), '2'