neft
Version:
JavaScript. Everywhere.
592 lines (445 loc) • 19.9 kB
text/coffeescript
'use strict'
{unit, assert, utils, Document, Renderer, styles} = Neft
{createView} = require '../document/utils'
{describe, it} = unit
{Element} = Document
testViews = []
render = (opts) ->
doc = createView opts.html
{path} = doc
Style = styles
styles: opts.styles or {}
queries: opts.queries or {}
windowStyle: opts.windowStyle or {objects: {}}
for key, subfile of Document._files
if key.indexOf(path) is 0
testViews.push subfile
Style.extendDocumentByStyles subfile
clone = doc.render()
clone.destroy()
doc.render()
describe 'src/styles', ->
describe "neft:style", ->
it "can be a Renderer.Item instance", ->
# item = Renderer.Rectangle.New()
# node = new Element.Tag
# node.attrs['neft:style'] = item
# doc = render
# node: node
# assert.is doc.styles.length, 1
# assert.isDefined style = doc.styles[0]
# assert.is style.item, item
it "accepts 'renderer:' prefix", ->
doc = render
html: """<b neft:style="renderer:Rectangle" />"""
assert.is doc.styles.length, 1
assert.instanceOf (style = doc.styles[0]).item, Renderer.Rectangle
it "accepts 'styles:file' syntax", ->
doc = render
html: """<b neft:style="styles:file" />"""
styles:
file:
_main:
getComponent: ->
item: Renderer.Rectangle.New()
assert.is doc.styles.length, 1
assert.instanceOf (item = doc.styles[0].item), Renderer.Rectangle
it "accepts 'styles:file:style' syntax", ->
doc = render
html: """<b neft:style="styles:file:style" />"""
styles:
file:
style:
getComponent: ->
item: Renderer.Rectangle.New()
assert.is doc.styles.length, 1
assert.instanceOf (item = doc.styles[0].item), Renderer.Rectangle
it "accepts 'styles:file:style:subid' syntax", ->
doc = render
html: """<b neft:style="styles:file:style">
<div neft:style="renderer:Item">
<i neft:style="styles:file:style:subid" />
</div>
</b>"""
styles:
file:
style:
getComponent: ->
item: Renderer.Rectangle.New()
objects:
subid: Renderer.Text.New()
bNode = doc.node.query 'b'
iNode = doc.node.query 'i'
assert.is doc.styles.length, 1
assert.instanceOf bNode.style, Renderer.Rectangle
assert.instanceOf iNode.style, Renderer.Text
it "accepts 'styles:view:style:subid' syntax", ->
doc = render
html: """<b neft:style="styles:view:style:subid" />"""
windowStyle:
objects:
subid: Renderer.Text.New()
assert.is doc.styles.length, 1
assert.instanceOf (item = (style = doc.styles[0]).item), Renderer.Text
it "created style is accessible in node", ->
doc = render
html: """<b neft:style="renderer:Item" />"""
assert.is (node = doc.styles[0].node).name, 'b'
assert.instanceOf node.style, Renderer.Item
it "node is accessible in created style document", ->
doc = render
html: """<b neft:style="renderer:Item" />"""
bNode = doc.node.query 'b'
assert.is bNode.style.document.node, bNode
it "must be specify to create a style", ->
doc = render
html: """<b />"""
node = doc.node.query 'b'
assert.is doc.styles.length, 0
assert.isNotDefined node.style
describe "Renderer.Text::text", ->
it "is always equal of stringified node children", ->
doc = render
html: """<b neft:style="renderer:Text">ab<i>c</i></b>"""
node = doc.node.query 'b'
item = doc.styles[0].item
assert.is item.text, node.stringifyChildren()
node.children[0].text = '123'
assert.is item.text, node.stringifyChildren()
it "is always equal of stringified visible node children", ->
doc = render
html: """<b neft:style="renderer:Text">ab<i visible="false">c</i></b>"""
bNode = doc.node.query 'b'
iNode = doc.node.query 'i'
item = doc.styles[0].item
assert.is item.text, bNode.stringifyChildren()
iNode.attrs.set 'visible', true
assert.is item.text, bNode.stringifyChildren()
describe "Renderer.Item::$.text", ->
it "is always equal stringified node children", ->
doc = render
html: """<b neft:style="styles:file">ab<i>c</i></b>"""
styles:
file:
_main:
getComponent: ->
item = Renderer.Item.New()
item.$.text = 'debug'
item: item
node = doc.node.query 'b'
item = doc.styles[0].item
assert.is item.$.text, node.stringifyChildren()
node.children[0].text = '123'
assert.is item.$.text, node.stringifyChildren()
it "is more important than ::text property", ->
doc = render
html: """<b neft:style="styles:file">ab<i>c</i></b>"""
styles:
file:
_main:
getComponent: ->
item = Renderer.Text.New()
item.$.text = 'debug'
item: item
node = doc.node.query 'b'
item = doc.styles[0].item
assert.is item.text, ''
assert.is item.$.text, node.stringifyChildren()
node.children[0].text = '123'
assert.is item.text, ''
assert.is item.$.text, node.stringifyChildren()
describe "Element.Text", ->
it "is rendered as Renderer.Text", ->
doc = render
html: """<b>abc</b>"""
assert.is doc.styles.length, 1
assert.instanceOf node = (style = doc.styles[0]).node, Element.Text
assert.is node.text, 'abc'
assert.instanceOf item = style.item, Renderer.Text
it "text is properly synchronized", ->
doc = render
html: """<b>abc</b>"""
node = doc.node.query '#text'
item = doc.styles[0].item
assert.is item.text, node.text
node.text = '123'
assert.is item.text, node.text
it "is not created if has a text parent", ->
doc = render
html: """<b neft:style="styles:file">ab</b>"""
styles:
file:
_main:
getComponent: ->
item = Renderer.Text.New()
item: item
node = doc.node.query 'b'
textNode = node.query '#text'
item = doc.styles[0].item
assert.instanceOf item, Renderer.Text
assert.isNotDefined textNode.style
describe "a[href]", ->
it "sets style linkUri", ->
doc = render
html: """<a href="/abc" neft:style="renderer:Item"></a>"""
node = doc.node.query 'a'
assert.is doc.styles.length, 1
assert.instanceOf style = node.style, Renderer.Item
assert.is style.linkUri, node.attrs.href
it "sets child node style linkUri", ->
doc = render
html: """<a href="/abc"><b neft:style="renderer:Item" /></a>"""
aNode = doc.node.query 'a'
bNode = doc.node.query 'b'
assert.is doc.styles.length, 1
assert.instanceOf style = bNode.style, Renderer.Item
assert.is style.linkUri, aNode.attrs.href
it "doesn't set child node style linkUri if the parent node is styled", ->
doc = render
html: """<a href="/abc" neft:style="renderer:Item">
<b neft:style="renderer:Item" />
</a>"""
aNode = doc.node.query 'a'
bNode = doc.node.query 'b'
assert.is bNode.style.linkUri, ''
it "updates style linkUri on attr change", ->
doc = render
html: """<a href="/abc" neft:style="renderer:Item"></a>"""
node = doc.node.query 'a'
node.attrs.set 'href', '/123'
assert.is node.style.linkUri, node.attrs.href
it "updates style linkUri on parent change", ->
doc = render
html: """<a href="/abc"><div /></a><b neft:style="renderer:Item" />"""
aNode = doc.node.query 'a'
divNode = doc.node.query 'div'
bNode = doc.node.query 'b'
assert.is bNode.style.linkUri, ''
bNode.parent = divNode
assert.is bNode.style.linkUri, aNode.attrs.href
bNode.parent = null
assert.is bNode.style.linkUri, ''
it "updates child style linkUri on attr change", ->
doc = render
html: """<a href="/abc"><div><b neft:style="renderer:Item" /></div></a>"""
aNode = doc.node.query 'a'
bNode = doc.node.query 'b'
aNode.attrs.set 'href', '/123'
assert.is bNode.style.linkUri, aNode.attrs.href
it "updates neft:each styles", ->
test = ->
for child in ulNode.children
assert.is child.query('#text').style?.linkUri, child.query('a').attrs.href
return
doc = render
html: """<ul neft:each="[1,2]">
<a href="/${props.item}">${props.item}</a>
</ul>"""
ulNode = doc.node.query 'ul'
test()
ulNode.attrs.set 'neft:each', [5,6,7]
test()
describe "'style:' attributes", ->
it "are set on a style item", ->
doc = render
html: """<b neft:style="renderer:Item" style:x="50" />"""
{node, item} = doc.styles[0]
assert.instanceOf item, Renderer.Item
assert.is item.x, node.attrs['style:x']
it "on change are set on a style item", ->
doc = render
html: """<b neft:style="renderer:Item" style:x="50" />"""
{node, item} = doc.styles[0]
node.attrs.set 'style:x', 70
assert.is item.x, node.attrs['style:x']
it "'null' value is not set for non-object properties", ->
doc = render
html: """<b neft:style="renderer:Item" style:x="null" />"""
{node, item} = doc.styles[0]
assert.is item.x, 0
node.attrs.set 'style:x', 4
node.attrs.set 'style:x', null
assert.is item.x, 4
describe "'class' attribute", ->
it "sets item classes", ->
doc = render
html: """<b neft:style="renderer:Item" class="a b c" />"""
{node, item} = doc.styles[0]
assert.isEqual item.classes.toArray(), node.attrs.class.split(' ')
it "synchronizes item classes on add and remove", ->
doc = render
html: """<b neft:style="renderer:Item" class="a b c" />"""
{node, item} = doc.styles[0]
node.attrs.set 'class', 'g a c'
assert.isEqual item.classes.toArray(), node.attrs.class.split(' ')
describe "Style item visible", ->
it "is 'true' by default", ->
doc = render
html: """<b neft:style="renderer:Item" />"""
assert.is doc.styles[0].item.visible, true
it "is 'false' if the style node is invisible", ->
doc = render
html: """<b neft:style="renderer:Item" visible="false" />"""
assert.is doc.styles[0].item.visible, false
it "is 'false' if the style node comes invisible", ->
doc = render
html: """<b neft:style="renderer:Item" />"""
node = doc.node.query 'b'
node.visible = false
assert.is doc.styles[0].item.visible, false
it "is 'true' if the style node comes visible", ->
doc = render
html: """<b neft:style="renderer:Item" visible="false" />"""
node = doc.node.query 'b'
node.visible = true
assert.is doc.styles[0].item.visible, true
it "is 'false' if the not-styled node parent is invisible", ->
doc = render
html: """<div visible="false">
<div><b neft:style="renderer:Item" /></div>
</div>"""
assert.is doc.styles[0].item.visible, false
it "is 'false' if the not-styled node parent comes invisible", ->
doc = render
html: """<div>
<div><b neft:style="renderer:Item" /></div>
</div>"""
node = doc.node.query 'div'
node.visible = false
assert.is doc.styles[0].item.visible, false
it "is 'true' if the styled node parent is invisible", ->
doc = render
html: """<div neft:style="renderer:Rectangle" visible="false">
<div><b neft:style="renderer:Item" /></div>
</div>"""
bNode = doc.node.query 'b'
assert.is bNode.style.visible, true
it "is 'true' if the styled node parent comes invisible", ->
doc = render
html: """<div neft:style="renderer:Rectangle">
<div><b neft:style="renderer:Item" /></div>
</div>"""
divNode = doc.node.query 'div'
bNode = doc.node.query 'b'
divNode.visible = false
assert.is bNode.style.visible, true
describe "Style item parent", ->
it "refers to the first styled parent style", ->
doc = render
html: """<div neft:style="renderer:Item">
<b neft:style="renderer:Item" />
</div>"""
divNode = doc.node.query 'div'
bNode = doc.node.query 'b'
assert.is bNode.style.parent, divNode.style
it "refers to the first styled parent style after the parent change", ->
doc = render
html: """<div neft:style="renderer:Item">
<i />
</div>
<b neft:style="renderer:Item" />"""
divNode = doc.node.query 'div'
iNode = doc.node.query 'i'
bNode = doc.node.query 'b'
bNode.parent = iNode
assert.is bNode.style.parent, divNode.style
it "is properly synchronized on 'neft:use'", ->
doc = render
html: """<neft:fragment neft:name="a">
<b neft:style="renderer:Item" />
<i neft:style="renderer:Item" />
</neft:fragment>
<div neft:style="renderer:Item">
<neft:use neft:fragment="a" />
</div>"""
divNode = doc.node.query 'div'
bNode = doc.node.query 'b'
iNode = doc.node.query 'i'
assert.is bNode.style.parent, divNode.style
assert.is iNode.style.parent, divNode.style
it "doesn't change if the item has a parent", ->
doc = render
html: """<div neft:style="renderer:Item"></div>
<b neft:style="styles:file:style" />"""
styles:
file:
style:
getComponent: ->
parent = Renderer.Item.New()
item = Renderer.Item.New()
item.parent = parent
item: item
divNode = doc.node.query 'div'
bNode = doc.node.query 'b'
bNode.parent = divNode
assert.isDefined bNode.style.parent
assert.isNot bNode.style.parent, divNode.style
describe "Style item index", ->
describe "is valid on", ->
it "index change", ->
doc = render
html: """<div neft:style="renderer:Item">
<em neft:style="renderer:Item" />
<b neft:style="renderer:Item" />
<i neft:style="renderer:Item" />
</div>"""
divNode = doc.node.query 'div'
emNode = doc.node.query 'em'
bNode = doc.node.query 'b'
iNode = doc.node.query 'i'
iNode.index = 1
assert.is iNode.style.previousSibling, emNode.style
assert.is iNode.style.nextSibling, bNode.style
it "parent change", ->
doc = render
html: """<div neft:style="renderer:Item">
<em />
<b neft:style="renderer:Item" />
</div>
<i neft:style="renderer:Item" />"""
divNode = doc.node.query 'div'
emNode = doc.node.query 'em'
bNode = doc.node.query 'b'
iNode = doc.node.query 'i'
iNode.parent = emNode
assert.is iNode.style.nextSibling, bNode.style
it "is valid in neft:each", ->
test = ->
childItem = divNode.style.children.firstChild
for item in divNode.attrs['neft:each']
assert.is childItem.text, item+''
childItem = childItem.nextSibling
return
doc = render
html: """<div neft:style="renderer:Item" neft:each="[1,2,3]">
<b>${props.item}</b>
</div>"""
divNode = doc.node.query 'div'
test()
divNode.attrs.set 'neft:each', [5,6,7,8]
test()
return
it "is valid for fixed item parent", ->
doc = render
html: """<b neft:style="styles:file:style">
<em neft:style="renderer:Item" />
<i neft:style="styles:file:style:subid" />
</b>"""
styles:
file:
style:
getComponent: ->
item = Renderer.Rectangle.New()
subid = Renderer.Text.New()
subid.parent = item
item: item
objects:
subid: subid
bNode = doc.node.query 'b'
emNode = doc.node.query 'em'
iNode = doc.node.query 'i'
assert.is emNode.style.nextSibling, iNode.style
it '', ->
for view in testViews
utils.clear view.styles
return