creatable
Version:
Elegant HTML generation. No templating. Just Javascript.
224 lines (184 loc) • 8.41 kB
text/coffeescript
Creatable = @Creatable ? require('../creatable.js')
chai = @chai ? require('chai')
should = chai.should()
describe "Basic", ->
describe "passing null or undefined", ->
it "should return null", ->
should.not.exist Creatable.create(null)
should.not.exist Creatable.create(undefined)
describe 'passing a string or number', ->
it 'should return a TextNode with the string or number as its content', ->
Creatable.create('test').should.have.property('nodeType', 3)
Creatable.create('test').should.have.property('textContent', 'test')
describe 'passing a tagName in brackets', ->
it 'should create an element with that tagName', ->
Creatable.create(['div']).nodeName.should.equal('DIV')
describe 'passing text as the second argument', ->
it 'should create an element with the given text content', ->
el = Creatable.create(['p', 'This is a test.'])
el.nodeName.should.equal('P')
$(el).text().should.equal('This is a test.')
describe 'passing text as the third argument', ->
it 'should create an element with the given text content', ->
el = Creatable.create(['p', {}, 'This is a test.'])
el.nodeName.should.equal('P')
$(el).text().should.equal('This is a test.')
describe "Ids and Classes", ->
describe 'div#myId', ->
it 'should create a div with an id of myId', ->
el = Creatable.create(['div#myId'])
el.nodeName.should.equal('DIV')
$(el).attr('id').should.equal('myId')
describe '#myId', ->
it 'should create a div with an id of myId', ->
el = Creatable.create(['#myId'])
el.nodeName.should.equal('DIV')
$(el).attr('id').should.equal('myId')
describe 'div.myClass', ->
it 'should create a div with a class of myClass', ->
el = Creatable.create(['div.myClass'])
el.nodeName.should.equal('DIV')
$(el).hasClass('myClass').should.be.true
describe '.myClass', ->
it 'should create a div with a class of myClass', ->
el = Creatable.create(['.myClass'])
el.nodeName.should.equal('DIV')
$(el).hasClass('myClass').should.be.true
describe '.class1.class2', ->
it 'should create a div with two classes', ->
el = Creatable.create(['.class1.class2'])
el.nodeName.should.equal('DIV')
$(el).hasClass('class1').should.be.true
$(el).hasClass('class2').should.be.true
describe '#myId.myClass', ->
it 'should create a div with both an id and a class', ->
el = Creatable.create(['#myId.myClass'])
el.nodeName.should.equal('DIV')
$(el).attr('id').should.equal('myId')
$(el).hasClass('myClass').should.be.true
describe 'Attributes', ->
describe 'passing an object as the second argument', ->
it 'should create an element with attributes', ->
el = Creatable.create(['a', { href: 'http://google.com', target: '_blank' }])
$(el).attr('href').should.equal('http://google.com')
$(el).attr('target').should.equal('_blank')
describe 'using css-syntax and a class attribute', ->
it 'should create a div with both classes', ->
el = Creatable.create(['.class1', { 'class': 'class2' }])
$(el).hasClass('class1').should.be.true
$(el).hasClass('class2').should.be.true
describe 'Children', ->
describe 'passing an array of children', ->
it 'should create an element with the appropriate children', ->
el = Creatable.create(
['div', [
['a'],
['p']
]]
)
el.nodeName.should.equal('DIV')
el.childNodes.should.have.length(2)
el.childNodes[0].nodeName.should.equal('A')
el.childNodes[1].nodeName.should.equal('P')
describe 'null or undefined children', ->
it 'should be ignored', ->
el = Creatable.create(
['div', [
['a'],
null,
undefined,
['p']
]]
)
el.childNodes.should.have.length(2)
el.childNodes[0].nodeName.should.equal('A')
el.childNodes[1].nodeName.should.equal('P')
describe 'document fragment', ->
it 'should be created from an empty array', ->
el = Creatable.create([])
el.nodeType.should.equal(11)
el.childNodes.should.have.length(0)
it 'should be created from an array of children', ->
el = Creatable.create(
[[
['a'],
['p']
]]
)
el.nodeType.should.equal(11)
el.childNodes.should.have.length(2)
el.childNodes[0].nodeName.should.equal('A')
el.childNodes[1].nodeName.should.equal('P')
describe 'descendant css syntax', ->
it 'should create children', ->
el = Creatable.create(['div p a'])
el.nodeName.should.equal('DIV')
el.firstChild.nodeName.should.equal('P')
el.firstChild.firstChild.nodeName.should.equal('A')
it 'should add classes and attributes to the final descendant', ->
el = Creatable.create(['div p a.button', { href: 'http://google.com' }])
$(el.firstChild.firstChild).attr('href').should.equal('http://google.com')
describe 'Other Features', ->
describe 'unescaped HTML content', ->
it 'should be able to be added with the attribute of { html: true }', ->
el = Creatable.create(
['ul', {html:true}, '<li>A</li><li>B</li><li>C</li>']
)
el.childNodes.should.have.length(3)
el.firstChild.nodeName.should.equal('LI')
el.firstChild.textContent.should.equal('A')
describe 'checked, disabled, selected attributes', ->
it 'should convert true to the attribute name', ->
checked = Creatable.create(["input", { type: "radio", checked: true }])
disabled = Creatable.create(["input", { type: "text", disabled: true }])
selected = Creatable.create(["select", [
["option", { selected: true }]
]])
$(checked).prop('checked').should.be.true
$(disabled).attr('disabled').should.equal('disabled')
$(selected.firstChild).attr('selected').should.equal('selected')
it 'should not render the attribute when set to false', ->
checked = Creatable.create(["input", { type: "radio", checked: false }])
disabled = Creatable.create(["input", { type: "text", disabled: false }])
selected = Creatable.create(["select", [
["option", { selected: false }]
]])
checked.hasAttribute('checked').should.be.false
disabled.hasAttribute('disabled').should.be.false
selected.firstChild.hasAttribute('selected').should.be.false
describe 'Emulated document object', ->
describe 'TextNode', ->
textNode = new Creatable.TextNode('content')
it 'should have a nodeType of 3', ->
textNode.should.have.property 'nodeType', 3
it 'should have a textContent property equal to its text', ->
textNode.should.have.property 'textContent', 'content'
it 'should override toString() to render the text content', ->
textNode.toString().should.equal 'content'
describe 'Element', ->
voidElements = area: 1, base: 1, br: 1, col: 1, command: 1, embed: 1, hr: 1, img: 1, input: 1, keygen: 1, link: 1, meta: 1, param: 1, source: 1, track: 1, wbr: 1
elementNode = new Creatable.Element('p')
elementNode.appendChild(new Creatable.TextNode('content'))
it 'should have a tagName', ->
elementNode.should.have.property 'tagName', 'p'
it 'should have a childNodes property', ->
elementNode.should.have.property 'childNodes'
elementNode.childNodes.should.be.an.array
it 'should have a nodeType of 1', ->
elementNode.should.have.property 'nodeType', 1
it 'should override toString() render HTML', ->
elementNode.toString().should.equal '<p>content</p>'
it 'should not render closing tags on void elements', ->
for tagName of voidElements
el = new Creatable.Element tagName
el.toString().should.equal "<#{tagName}>"
describe 'DocumentFragment', ->
fragmentNode = new Creatable.DocumentFragment()
it 'should have a childNodes property', ->
fragmentNode.should.have.property 'childNodes'
fragmentNode.childNodes.should.be.an.array
it 'should have a nodeType of 11', ->
fragmentNode.should.have.property 'nodeType', 11
describe 'createHtml', ->
it 'should use the emulated document to render creatable markup to a string', ->
Creatable.createHtml(['a#go.small.button', 'test']).should.equal('<a id="go" class="small button">test</a>')