UNPKG

neft

Version:

Universal Platform

599 lines (495 loc) 22.3 kB
'use strict' {unit, utils, assert, Document} = Neft {Element} = Document {describe, it, beforeEach, whenChange} = unit describe 'src/document Element', -> HTML = '<b><em>abc</em></b>' + '<u></u>' + '<p title="textTitle" class="a bb c2" data-custom="customValue"></p>' doc = null b = em = div = p = null describe 'parsed html', -> it 'is an Element', -> doc = Element.fromHTML HTML assert.instanceOf doc, Element b = doc.children[0] em = b.children[0] div = doc.children[1] p = doc.children[2] it 'has proper amount of children', -> assert.is doc.children.length, 3 assert.is b.children.length, 1 assert.is em.children.length, 1 assert.is div.children.length, 0 assert.is p.children.length, 0 it 'has proper elements names', -> assert.is doc.name, 'blank' assert.is b.name, 'b' assert.is em.name, 'em' assert.is div.name, 'u' it 'stringify to html', -> html = doc.stringify() assert.is html, HTML it 'hidden props are omitted in the stringified process', -> elem = Element.fromHTML '<span n-if="a" n-each="a"></span>' html = elem.stringify() assert.is html, '<span></span>' it 'stringify children to html', -> elem = Element.fromHTML '<span><b></b></span>' htmlOuter = elem.children[0].stringify() htmlInner = elem.children[0].stringifyChildren() assert.is htmlOuter, '<span><b></b></span>' assert.is htmlInner, '<b></b>' it 'change parents properly', -> em.parent = div p.parent = undefined assert.is em.parent, div assert.is b.children.length, 0 assert.is div.children.length, 1 assert.is div.children[0], em assert.is doc.stringify(), '<b></b><u><em>abc</em></u>' try em.parent = em catch err assert.isDefined err em.parent = b p.parent = doc describe 'text property', -> it 'is filled properly', -> assert.is b.text, undefined assert.is em.text, undefined assert.is em.children[0].text, 'abc' it 'can be changed', -> em.children[0].text = '123' assert.is em.children[0].text, '123' assert.is b.children[0], em assert.is b.stringify(), '<b><em>123</em></b>' em.children[0].text = '123' it 'can be cloned deep', -> clone = b.cloneDeep() assert.instanceOf clone, Element assert.isNot clone, b assert.instanceOf clone.children[0], Element assert.isNot clone.children[0], em assert.is clone.children[0].name, 'em' describe 'props', -> it 'are filled properly', -> assert.isEqual doc.props.item(0), [undefined, undefined] assert.isEqual div.props.item(0), [undefined, undefined] assert.isEqual p.props.item(0), ['title', 'textTitle'] assert.isEqual p.props.item(1), ['class', 'a bb c2'] assert.isEqual p.props.item(2), ['data-custom', 'customValue'] assert.is p.props['title'], 'textTitle' it 'can be changed', -> elem = p.clone() assert.is elem.props['title'], 'textTitle' # change elem.props.set 'title', 'changed value' assert.is elem.props['title'], 'changed value' it 'can store references to the objects', -> elem = p.clone() title = elem.props['title'] obj = a: 1 # change elem.props.set 'title', obj assert.is elem.props['title'], obj assert.is elem.stringify(), '<p title="[object Object]" class="a bb c2" data-custom="customValue"></p>' elem.props.set 'title', title describe 'index property', -> it 'returns child index in the parent', -> assert.is div.index, 1 it 'change child index in the parent', -> elem = Element.fromHTML '<a></a><b></b>' [elemA, elemB] = elem.children elemB.index = 0 assert.isEqual elem.children, [elemB, elemA], maxDeep: 1 it 'replace() works properly', -> elem = Element.fromHTML '<b><em></em></b><u></u><p></p>' [elemB, elemDiv, elemP] = elem.children [elemEm] = b.children elem.replace elemB, elemP assert.is elem.children.length, 2 assert.is elem.children[0], elemP assert.is elem.stringify(), '<p></p><u></u>' elem.replace elemP, elemB elemP.parent = elem assert.is elem.children.length, 3 assert.is elem.children[0], elemB assert.is elem.children[1], elemDiv assert.is elem.children[2], elemP assert.is elem.stringify(), '<b><em></em></b><u></u><p></p>' describe 'queryAll() works with selector', -> doc2 = Element.fromHTML "<div><b class='first second'><u color='blue' attr='1'>text1<u></u></u></b></div><div attr='2'><blank><em>text2</em></blank><em></em></div>" doc2div1 = doc2.children[0] doc2b = doc2div1.children[0] doc2u = doc2b.children[0] doc2u2 = doc2u.children[1] doc2div2 = doc2.children[1] doc2em1 = doc2div2.children[0].children[0] doc2em2 = doc2div2.children[1] it 'E', -> assert.isEqual doc2.queryAll('div'), [doc2div1, doc2div2], maxDeep: 1 assert.isEqual doc2.queryAll('u'), [doc2u, doc2u2], maxDeep: 1 it 'E F', -> assert.isEqual doc2.queryAll('div u'), [doc2u, doc2u2], maxDeep: 1 assert.isEqual doc2.queryAll('b u'), [doc2u, doc2u2], maxDeep: 1 assert.isEqual doc2.queryAll('b div'), [] it 'E > F', -> assert.isEqual doc2.queryAll('div > u'), [] assert.isEqual doc2.queryAll('div > b'), [doc2b], maxDeep: 1 assert.isEqual doc2.queryAll('b > u'), [doc2u], maxDeep: 1 it '[foo]', -> assert.isEqual doc2.queryAll('[attr]'), [doc2u, doc2div2], maxDeep: 1 assert.isEqual doc2.queryAll('[color]'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[width]'), [] it '[foo=bar]', -> assert.isEqual doc2.queryAll('[attr=2]'), [doc2div2], maxDeep: 1 assert.isEqual doc2.queryAll('[attr="2"]'), [doc2div2], maxDeep: 1 assert.isEqual doc2.queryAll('[attr=\'2\']'), [doc2div2], maxDeep: 1 assert.isEqual doc2.queryAll('[attr=3]'), [] it '[foo^=bar]', -> assert.isEqual doc2.queryAll('[color^=bl]'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[color^="b"]'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[color^=\'blue\']'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[color^=lue]'), [] it '[foo$=bar]', -> assert.isEqual doc2.queryAll('[color$=ue]'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[color$="e"]'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[color$=\'blue\']'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[color$=blu]'), [] it '[foo*=bar]', -> assert.isEqual doc2.queryAll('[color*=bl]'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[color*="lu"]'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[color*=\'blue\']'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[color*=bl][color*=lu]'), [doc2u], maxDeep: 1 assert.isEqual doc2.queryAll('[color*=lue1]'), [] it '.foo', -> assert.isEqual doc2.queryAll('.first'), [doc2b], maxDeep: 1 assert.isEqual doc2.queryAll('.first.second'), [doc2b], maxDeep: 1 assert.isEqual doc2.queryAll('.first.second.third'), [] it 'E.foo', -> assert.isEqual doc2.queryAll('b.first'), [doc2b], maxDeep: 1 assert.isEqual doc2.queryAll('b.first.second'), [doc2b], maxDeep: 1 assert.isEqual doc2.queryAll('b.first.second.third'), [] it '*', -> assert.isEqual doc2.queryAll('*'), [doc2div1, doc2b, doc2u, doc2u2, doc2div2, doc2em1, doc2em2], maxDeep: 1 it '*[foo]', -> assert.isEqual doc2.queryAll('*[color]'), [doc2u], maxDeep: 1 it 'E > * > F[foo]', -> assert.isEqual doc2.queryAll('div > * > u[color]'), [doc2u], maxDeep: 1 it 'E > * > F[foo], F[foo]', -> assert.isEqual doc2.queryAll('div > * > u[color], div[attr]'), [doc2u, doc2div2], maxDeep: 1 assert.isEqual doc2.queryAll('div > * > u[color],div[attr]'), [doc2u, doc2div2], maxDeep: 1 it '#text', -> assert.isEqual doc2.queryAll('#text'), [doc2u.children[0], doc2em1.children[0]], maxDeep: 1 it 'E #text', -> assert.isEqual doc2.queryAll('em #text'), [doc2em1.children[0]], maxDeep: 1 it 'omits blank', -> assert.isEqual doc2.queryAll('div > em'), [doc2em1, doc2em2], maxDeep: 1 describe 'query() works with selector', -> doc2 = Element.fromHTML "<div><b><u color='blue' attr='1'></u></b></div><div attr='2'><blank><em></em></blank></div>" doc2div1 = doc2.children[0] doc2b = doc2div1.children[0] doc2u = doc2b.children[0] doc2div2 = doc2.children[1] doc2em = doc2div2.children[0].children[0] it 'E', -> assert.is doc2.query('div'), doc2div1 assert.is doc2.query('u'), doc2u it '[foo]', -> assert.is doc2.query('[attr]'), doc2u assert.is doc2.query('[color]'), doc2u assert.is doc2.query('[width]'), null it 'omits blank', -> assert.is doc2.query('div > em'), doc2em describe 'queryParents() works with selector', -> doc2 = Element.fromHTML "<div><b><u color='blue' attr='1'></u></b></div><div attr='2'><blank><em></em></blank></div>" doc2div1 = doc2.children[0] doc2b = doc2div1.children[0] doc2u = doc2b.children[0] doc2div2 = doc2.children[1] doc2em = doc2div2.children[0].children[0] it 'E', -> assert.is doc2u.queryParents('div'), doc2div1 assert.is doc2b.queryParents('div'), doc2div1 it 'E > F', -> assert.is doc2u.queryParents('div > b'), doc2div1 assert.is doc2u.queryParents('div > b >'), doc2div1 describe 'watch()', -> it 'is a function', -> assert.instanceOf doc.watch, Function describe 'works with selector', -> tags = doc2 = doc2div1 = doc2b = doc2u = doc2u2 = doc2div2 = doc2em1 = doc2em2 = null beforeEach -> tags = [] doc2 = Element.fromHTML """ <div><b><u color='blue' attr='1'><u></u></u></b></div> <div attr='2'><blank><em>text1</em></blank><em></em></div> """ doc2div1 = doc2.children[0] doc2b = doc2div1.children[0] doc2u = doc2b.children[0] doc2u2 = doc2b.children[0].children[0] doc2div2 = doc2.children[1] doc2em1 = doc2div2.children[0].children[0] doc2em2 = doc2div2.children[1] it 'E', (done) -> doc2b.parent = null watcher = doc2.watch 'b' watcher.onAdd (tag) -> tags.push tag doc2b.parent = doc2div1 whenChange tags, -> assert.isEqual tags, [doc2b], maxDeep: 1 done() it 'E F', (done) -> doc2u.parent = null watcher = doc2.watch 'b u' watcher.onAdd (tag) -> tags.push tag doc2u.parent = doc2b whenChange tags, -> assert.isEqual tags, [doc2u, doc2u2], maxDeep: 1 done() it 'E > F', (done) -> doc2u.parent = null watcher = doc2div1.watch '> u' watcher.onAdd (tag) -> tags.push tag doc2u.parent = doc2div1 whenChange tags, -> assert.isEqual tags, [doc2u], maxDeep: 1 done() it '[foo]', (done) -> watcher = doc2div1.watch '[attr2]' watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag doc2u.props.set 'attr2', '2' whenChange tags, -> assert.isEqual tags, [doc2u], maxDeep: 1 doc2u.props.set 'attr2', undefined whenChange tags, -> assert.isEqual tags, [] done() it '[foo=bar]', (done) -> watcher = doc2div1.watch '[attr=2]' watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag doc2u.props.set 'attr', '2' whenChange tags, -> assert.isEqual tags, [doc2u], maxDeep: 1 doc2u.props.set 'attr', '1' whenChange tags, -> assert.isEqual tags, [] done() it '[foo^=bar]', (done) -> watcher = doc2div1.watch '[color^=re]' watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag doc2u.props.set 'color', 'red' whenChange tags, -> assert.isEqual tags, [doc2u], maxDeep: 1 doc2u.props.set 'color', 'blue' whenChange tags, -> assert.isEqual tags, [] done() it '[foo$=bar]', (done) -> watcher = doc2div1.watch '[color$=ed]' watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag doc2u.props.set 'color', 'red' whenChange tags, -> assert.isEqual tags, [doc2u], maxDeep: 1 doc2u.props.set 'color', 'blue' whenChange tags, -> assert.isEqual tags, [] done() it '[foo*=bar]', (done) -> watcher = doc2div1.watch '[color*=rang]' watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag doc2u.props.set 'color', 'orange' whenChange tags, -> assert.isEqual tags, [doc2u], maxDeep: 1 doc2u.props.set 'color', 'blue' whenChange tags, -> assert.isEqual tags, [] done() it '*', (done) -> doc2u.parent = null watcher = doc2div1.watch '*' for node in watcher.nodes tags.push node watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag doc2u.parent = doc2div1 whenChange tags, -> assert.isEqual tags, [doc2b, doc2u, doc2u2], maxDeep: 1 doc2u.parent = null whenChange tags, -> assert.isEqual tags, [doc2b], maxDeep: 1 done() it '*[foo]', (done) -> watcher = doc2div1.watch '*[attr2]' watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag doc2u.props.set 'attr2', '2' whenChange tags, -> assert.isEqual tags, [doc2u], maxDeep: 1 doc2u.props.set 'attr2', undefined whenChange tags, -> assert.isEqual tags, [] done() it 'E > * > F[foo]', (done) -> doc2u.parent = null watcher = doc2.watch 'div > * > u[color]' watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag doc2u.parent = doc2b whenChange tags, -> assert.isEqual tags, [doc2u], maxDeep: 1 doc2u.parent = null whenChange tags, -> assert.isEqual tags, [] done() it 'E > * > F[foo], F[foo]', (done) -> doc2div1.parent = null doc2div2.parent = null watcher = doc2.watch 'div > * > u[color], div[attr]' watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag doc2div1.parent = doc2 doc2div2.parent = doc2 whenChange tags, -> assert.isEqual tags, [doc2u, doc2div2], maxDeep: 1 doc2div1.parent = null doc2div2.parent = null whenChange tags, -> assert.isEqual tags, [] done() it '&[foo]', (done) -> doc2u.parent = null watcher = doc2u.watch '&[color]' watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag doc2u.parent = doc2b whenChange tags, -> assert.isEqual tags, [doc2u], maxDeep: 1 doc2u.props.set 'color', undefined whenChange tags, -> assert.isEqual tags, [] done() it '#text', (done) -> watcher = doc2.watch '#text' watcher.onAdd (tag) -> tags.push tag watcher.onRemove (tag) -> utils.remove tags, tag whenChange tags, -> assert.isEqual tags, [doc2em1.children[0]], maxDeep: 1 newText = new Element.Text newText.parent = doc2em2 whenChange tags, -> assert.isEqual tags, [doc2em1.children[0], newText], maxDeep: 1 done() it 'supports disconnect() in onRemove()', (done) -> tags = [] removedTags = [] doc2 = Element.fromHTML """ <div><b /><b /></div> """ div = doc2.children[0] [b1, b2] = div.children watcher1 = div.watch 'b' watcher2 = div.watch 'b' disconnected = false watcher2.onAdd (tag) -> tags.push tag watcher1.onRemove (tag) -> unless disconnected disconnected = true watcher1.disconnect() watcher2.disconnect() watcher2.onRemove (tag) -> removedTags.push tag whenChange tags, -> b1.parent = null whenChange removedTags, -> assert.isEqual removedTags, [b1, b2], maxDeep: 1 done() it 'visible property is editable', -> assert.ok p.visible p.visible = false assert.notOk p.visible p.visible = true describe 'Observer', -> it 'observing attr changes works properly', -> value = args = null elem = Element.fromHTML('<b a="1"></b>').cloneDeep() tag = elem.children[0] tag.onPropsChange (name, oldVal) -> value = @props[name] args = [@, arguments...] tag.props.set 'a', 2 assert.isEqual args, [tag, 'a', '1'], maxDeep: 1 assert.is value, 2 it 'observing visibility changes works properly', -> value = args = null elem = Element.fromHTML('<b></b>').cloneDeep() tag = elem.children[0] tag.onVisibleChange -> value = @visible args = [@, arguments...] tag.visible = false assert.isEqual args, [tag, true, undefined], maxDeep: 1 assert.is value, false it 'observing text changes works properly', -> text = args = null elem = Element.fromHTML('<b>a</b>').cloneDeep() tag = elem.children[0].children[0] tag.onTextChange -> text = @text args = [@, arguments...] tag.text = 'b' assert.isEqual args, [tag, 'a', undefined], maxDeep: 1 assert.is text, 'b' it 'observing parent changes works properly', -> value = args = null elem = Element.fromHTML('<a></a><b></b>').cloneDeep() tag1 = elem.children[0] tag2 = elem.children[1] tag2.onParentChange -> value = @parent args = [@, arguments...] tag2.parent = tag1 assert.isEqual args, [tag2, elem, undefined], maxDeep: 1 assert.is value, tag1 it 'disconnect() works as expected', -> ok = true elem = Element.fromHTML('<b></b>').cloneDeep() tag = elem.children[0] listener = -> ok = false tag.onVisibleChange listener tag.onVisibleChange.disconnect listener tag.visible = false assert.ok ok