neft
Version:
JavaScript. Everywhere.
358 lines (304 loc) • 10.8 kB
text/coffeescript
'use strict'
fs = require 'fs'
os = require 'os'
{assert, utils, unit, Document} = Neft
{describe, it} = unit
{createView, renderParse, uid} = require './utils'
describe 'src/document neft:script', ->
it 'is not rendered', ->
view = createView '''
<neft:script></neft:script>
'''
view = view.clone()
renderParse view
assert.is view.node.stringify(), ''
it 'context is shared between rendered views', ->
view = createView '''
<neft:script><![CDATA[
this.a = Math.random();
]]></neft:script>
'''
view = view.clone()
renderParse view
proto = view.context.__proto__
assert.isFloat view.context.a
view.revert()
renderParse view
assert.is view.context.__proto__, proto
view.revert()
view2 = view.clone()
renderParse view2
assert.is view2.context.__proto__, proto
describe '<script>', ->
it 'works like <neft:script>', ->
view = createView '''
<script>
this.a = Math.random();
</script>
'''
view = view.clone()
renderParse view
assert.isFloat view.context.a
it 'is not rendered', ->
view = createView '''
<script></script>
'''
view = view.clone()
renderParse view
assert.is view.node.stringify(), ''
it 'does not work if has attributes', ->
view = createView '''
<script src=""><![CDATA[
this.a = 1;
]]></script>
'''
view = view.clone()
renderParse view
assert.isNot view.node.stringify(), ''
assert.is view.context?.a, undefined
describe 'this.onCreate()', ->
it 'is called on a view clone', ->
view = createView '''
<neft:attr name="x" value="1" />
<neft:script><![CDATA[
this.onCreate(function(){
this.b = 2;
});
this.a = 1;
]]></neft:script>
'''
view = view.clone()
renderParse view
{context} = view
assert.is context.b, 2
assert.is context.a, 1
view.revert()
renderParse view
assert.is view.context, context
view2 = view.clone()
renderParse view2
assert.isNot view2.context, context
assert.is view2.context.b, 2
assert.is view2.context.a, 1
it 'is called with its prototype', ->
view = createView '''
<neft:script><![CDATA[
this.onCreate(function(){
this.proto = this;
this.protoA = this.a;
});
this.a = 1;
]]></neft:script>
'''
view = view.clone()
renderParse view
assert.is view.context.proto, view.context
assert.is view.context.protoA, 1
it 'is called with props in context', ->
view = createView '''
<neft:script><![CDATA[
this.onCreate(function(){
this.a = this.props.a;
});
]]></neft:script>
<neft:attr name="a" value="1" />
'''
view = view.clone()
renderParse view
assert.is view.context.a, 1
it 'is called with ids in context', ->
view = createView '''
<neft:script><![CDATA[
this.onCreate(function(){
this.a = this.ids.x.attrs.a;
});
]]></neft:script>
<b id="x" a="1" />
'''
view = view.clone()
renderParse view
assert.is view.context.a, 1
it 'is called with root in context', ->
view = createView '''
<neft:script><![CDATA[
this.onRender(function(){
this.a = this.root.a;
});
]]></neft:script>
'''
view = view.clone()
renderParse view, storage: a: 1
assert.is view.context.a, 1
it 'is called with file node in context', ->
view = createView '''
<neft:script><![CDATA[
this.onCreate(function(){
this.aNode = this.node;
});
]]></neft:script>
'''
view = view.clone()
renderParse view
assert.is view.context.aNode, view.node
describe.onServer '[filename]', ->
it 'supports .coffee files', ->
view = Document.fromHTML uid(), '''
<neft:script filename="a.coffee"><![CDATA[
@a = 1
]]></neft:script>
'''
Document.parse view
view = view.clone()
renderParse view
assert.is view.context.a, 1
it 'predefined context properties are not enumerable', ->
view = createView '''
<neft:script><![CDATA[
var protoKeys = [];
for (var key in this) {
protoKeys.push(key);
}
this.onCreate(function(){
var keys = [].concat(protoKeys);
this.keys = keys;
for (var key in this) {
keys.push(key);
}
});
]]></neft:script>
'''
view = view.clone()
renderParse view
assert.isEqual view.context.keys, ['keys']
it 'further tags are properly called', ->
view = createView '''
<neft:script><![CDATA[
this.onCreate(function(){
this.aa = 1;
});
this.a = 1;
]]></neft:script>
<neft:script><![CDATA[
this.onCreate(function(){
this.bb = 1;
this.bbaa = this.aa;
});
this.b = 1;
]]></neft:script>
'''
view = view.clone()
renderParse view
{context} = view
assert.is context.a, 1
assert.is context.aa, 1
assert.is context.b, 1
assert.is context.bb, 1
assert.is context.bbaa, 1
it 'can contains XML text', ->
source = createView """
<neft:script><![CDATA[
this.a = '<&&</neft:script>';
]]></neft:script>
${this.a}
"""
view = source.clone()
renderParse view
assert.is view.node.stringify(), '<&&</neft:script>'
it '<script> can contains XML text with no CDATA', ->
source = createView """
<script>
this.a = '<&&</neft:script>';
</script>
${this.a}
"""
view = source.clone()
renderParse view
assert.is view.node.stringify(), '<&&</neft:script>'
it.onServer 'accepts `src` attribute', ->
filename = "tmp#{uid()}.js"
path = "#{os.tmpdir()}/#{filename}"
file = 'module.exports = function(){ this.a = 1; }'
fs.writeFileSync path, file, 'utf-8'
source = Document.fromHTML uid(), """
<neft:script src="#{path}" />
<neft:blank>${this.a}</neft:blank>
"""
Document.parse source
view = source.clone()
renderParse view
assert.is view.node.stringify(), '1'
it.onServer 'accepts relative `src` attribute', ->
scriptFilename = "tmp#{uid()}.js"
scriptPath = "#{os.tmpdir()}/#{scriptFilename}"
file = 'module.exports = function(){ this.a = 1; }'
fs.writeFileSync scriptPath, file, 'utf-8'
viewFilename = "tmp#{uid()}"
viewPath = "#{os.tmpdir()}/#{viewFilename}"
fs.writeFileSync viewPath, viewStr = """
<neft:script src="./#{scriptFilename}" />
<neft:blank>${this.a}</neft:blank>
"""
source = Document.fromHTML viewPath, viewStr
Document.parse source
view = source.clone()
renderParse view
assert.is view.node.stringify(), '1'
it 'properly calls events', ->
view = createView """
<neft:script><![CDATA[
this.onCreate(function(){
this.events = [];
});
this.onBeforeRender(function(){
this.events.push('onBeforeRender');
});
this.onRender(function(){
this.events.push('onRender');
});
this.onBeforeRevert(function(){
this.events.push('onBeforeRevert');
});
this.onRevert(function(){
this.events.push('onRevert');
});
]]></neft:script>
"""
view = view.clone()
{events} = view.context
assert.isEqual events, []
view.render()
assert.isEqual events, ['onBeforeRender', 'onRender']
view.revert()
assert.isEqual events, [
'onBeforeRender', 'onRender', 'onBeforeRevert', 'onRevert'
]
it 'does not call events for foreign context', ->
view = createView """
<neft:script><![CDATA[
this.onCreate(function(){
this.events = [];
});
this.onBeforeRender(function(){
this.events.push('onBeforeRender');
});
this.onRender(function(){
this.events.push('onRender');
});
this.onBeforeRevert(function(){
this.events.push('onBeforeRevert');
});
this.onRevert(function(){
this.events.push('onRevert');
});
]]></neft:script>
<ul neft:each="[1,2]">${props.item}</ul>
"""
view = view.clone()
{events} = view.context
assert.isEqual events, []
view.render()
assert.isEqual events, ['onBeforeRender', 'onRender']
view.revert()
assert.isEqual events, [
'onBeforeRender', 'onRender', 'onBeforeRevert', 'onRevert'
]