378 lines
12 KiB
JavaScript
378 lines
12 KiB
JavaScript
|
|
||
|
var assert = require('assert');
|
||
|
var serialize = require('../');
|
||
|
|
||
|
describe('node-serialize', function () {
|
||
|
var node;
|
||
|
|
||
|
afterEach(function () {
|
||
|
if (node) {
|
||
|
// clean up...
|
||
|
if (node.parentNode) {
|
||
|
node.parentNode.removeChild(node);
|
||
|
}
|
||
|
node = null;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
it('should return an empty string on invalid input', function () {
|
||
|
assert.strictEqual('', serialize(null));
|
||
|
});
|
||
|
|
||
|
it('should serialize a SPAN element', function () {
|
||
|
node = document.createElement('span');
|
||
|
assert.equal('<span></span>', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize a BR element', function () {
|
||
|
node = document.createElement('br');
|
||
|
assert.equal('<br>', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize a text node', function () {
|
||
|
node = document.createTextNode('test');
|
||
|
assert.equal('test', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize a text node with special HTML characters', function () {
|
||
|
node = document.createTextNode('<>\'"&');
|
||
|
assert.equal('<>\'"&', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize a DIV element with child nodes', function () {
|
||
|
node = document.createElement('div');
|
||
|
node.appendChild(document.createTextNode('hello '));
|
||
|
var b = document.createElement('b');
|
||
|
b.appendChild(document.createTextNode('world'));
|
||
|
node.appendChild(b);
|
||
|
node.appendChild(document.createTextNode('!'));
|
||
|
node.appendChild(document.createElement('br'));
|
||
|
assert.equal('<div>hello <b>world</b>!<br></div>', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize a DIV element with attributes', function () {
|
||
|
node = document.createElement('div');
|
||
|
node.setAttribute('foo', 'bar');
|
||
|
node.setAttribute('escape', '<>&"\'');
|
||
|
assert.equal('<div foo="bar" escape="<>&"'"></div>', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize an Attribute node', function () {
|
||
|
var div = document.createElement('div');
|
||
|
div.setAttribute('foo', 'bar');
|
||
|
node = div.attributes[0];
|
||
|
assert.equal('foo="bar"', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize a Comment node', function () {
|
||
|
node = document.createComment('test');
|
||
|
assert.equal('<!--test-->', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize a Document node', function () {
|
||
|
node = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null);
|
||
|
assert.equal('<html></html>', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize a Doctype node', function () {
|
||
|
node = document.implementation.createDocumentType(
|
||
|
'html',
|
||
|
'-//W3C//DTD XHTML 1.0 Strict//EN',
|
||
|
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
|
||
|
);
|
||
|
|
||
|
// Some older browsers require the DOCTYPE to be within a Document,
|
||
|
// otherwise the "serialize" custom event is considered "cancelled".
|
||
|
// See: https://travis-ci.org/webmodules/dom-serialize/builds/47307749
|
||
|
var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', node);
|
||
|
|
||
|
assert.equal('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">', serialize(node));
|
||
|
assert.equal('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html></html>', serialize(doc));
|
||
|
});
|
||
|
|
||
|
it('should serialize a Doctype node with systemId', function () {
|
||
|
node = document.implementation.createDocumentType(
|
||
|
'root-element',
|
||
|
'',
|
||
|
'http://www.w3.org/1999/xhtml'
|
||
|
);
|
||
|
document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'root-element', node);
|
||
|
|
||
|
assert.equal('<!DOCTYPE root-element SYSTEM "http://www.w3.org/1999/xhtml">', serialize(node));
|
||
|
});
|
||
|
|
||
|
|
||
|
it('should serialize an HTML5 Doctype node', function () {
|
||
|
node = document.implementation.createDocumentType(
|
||
|
'html',
|
||
|
'',
|
||
|
''
|
||
|
);
|
||
|
document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'node', node);
|
||
|
|
||
|
assert.equal('<!DOCTYPE html>', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize a DocumentFragment node', function () {
|
||
|
node = document.createDocumentFragment();
|
||
|
node.appendChild(document.createElement('b'));
|
||
|
node.appendChild(document.createElement('i'));
|
||
|
node.lastChild.appendChild(document.createTextNode('foo'));
|
||
|
assert.equal('<b></b><i>foo</i>', serialize(node));
|
||
|
});
|
||
|
|
||
|
it('should serialize an Array of nodes', function () {
|
||
|
var array = [];
|
||
|
array.push(document.createTextNode('foo'));
|
||
|
array.push(document.createElement('div'));
|
||
|
array[1].appendChild(document.createTextNode('bar'));
|
||
|
assert.equal('foo<div>bar</div>', serialize(array));
|
||
|
});
|
||
|
|
||
|
describe('serializeText()', function () {
|
||
|
|
||
|
it('should serialize an Attribute node', function () {
|
||
|
var d = document.createElement('div');
|
||
|
d.setAttribute('foo', '<>"&');
|
||
|
assert.equal('foo="<>"&"', serialize.serializeAttribute(d.attributes[0]));
|
||
|
});
|
||
|
|
||
|
it('should allow an "options" object to be passed in', function () {
|
||
|
var d = document.createElement('div');
|
||
|
d.setAttribute('foo', '<>"&');
|
||
|
assert.equal('foo="<>"&"', serialize.serializeAttribute(d.attributes[0], { named: false }));
|
||
|
});
|
||
|
|
||
|
});
|
||
|
|
||
|
describe('serializeText()', function () {
|
||
|
|
||
|
it('should serialize a TextNode instance', function () {
|
||
|
node = document.createTextNode('<b>&');
|
||
|
assert.equal('<b>&', serialize.serializeText(node));
|
||
|
});
|
||
|
|
||
|
it('should allow an "options" object to be passed in', function () {
|
||
|
node = document.createTextNode('<b>&');
|
||
|
assert.equal('<b>&', serialize.serializeText(node, { named: false }));
|
||
|
});
|
||
|
|
||
|
});
|
||
|
|
||
|
describe('"serialize" event', function () {
|
||
|
|
||
|
it('should emit a "serialize" event on a DIV node', function () {
|
||
|
node = document.createElement('div');
|
||
|
var count = 0;
|
||
|
node.addEventListener('serialize', function (e) {
|
||
|
count++;
|
||
|
e.detail.serialize = 'MEOW';
|
||
|
});
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('MEOW', serialize(node));
|
||
|
assert.equal(1, count);
|
||
|
});
|
||
|
|
||
|
it('should emit a "serialize" event on a Text node', function () {
|
||
|
node = document.createTextNode('whaaaaa!!!!!!');
|
||
|
var count = 0;
|
||
|
node.addEventListener('serialize', function (e) {
|
||
|
count++;
|
||
|
e.detail.serialize = 'MEOW';
|
||
|
});
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('MEOW', serialize(node));
|
||
|
assert.equal(1, count);
|
||
|
});
|
||
|
|
||
|
it('should output an empty string when event is cancelled', function () {
|
||
|
node = document.createElement('div');
|
||
|
node.appendChild(document.createTextNode('!'));
|
||
|
var count = 0;
|
||
|
node.firstChild.addEventListener('serialize', function (e) {
|
||
|
count++;
|
||
|
e.preventDefault();
|
||
|
});
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('<div></div>', serialize(node));
|
||
|
assert.equal(1, count);
|
||
|
});
|
||
|
|
||
|
it('should render a Number when set as `e.detail.serialize`', function () {
|
||
|
node = document.createTextNode('whaaaaa!!!!!!');
|
||
|
var count = 0;
|
||
|
node.addEventListener('serialize', function (e) {
|
||
|
count++;
|
||
|
e.detail.serialize = 123;
|
||
|
});
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('123', serialize(node));
|
||
|
assert.equal(1, count);
|
||
|
});
|
||
|
|
||
|
it('should render a Node when set as `e.detail.serialize`', function () {
|
||
|
node = document.createTextNode('whaaaaa!!!!!!');
|
||
|
var count = 0;
|
||
|
node.addEventListener('serialize', function (e) {
|
||
|
count++;
|
||
|
if (count === 1) {
|
||
|
e.detail.serialize = document.createTextNode('foo');
|
||
|
}
|
||
|
});
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('foo', serialize(node));
|
||
|
assert.equal(2, count);
|
||
|
});
|
||
|
|
||
|
it('should render a Node when set as `e.detail.serialize` and event is cancelled', function () {
|
||
|
node = document.createTextNode('whaaaaa!!!!!!');
|
||
|
var count = 0;
|
||
|
node.addEventListener('serialize', function (e) {
|
||
|
count++;
|
||
|
if (count === 1) {
|
||
|
e.preventDefault();
|
||
|
e.detail.serialize = document.createTextNode('foo');
|
||
|
}
|
||
|
});
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('foo', serialize(node));
|
||
|
assert.equal(2, count);
|
||
|
});
|
||
|
|
||
|
it('should have `context` set on the event', function () {
|
||
|
node = document.createTextNode('');
|
||
|
var count = 0;
|
||
|
node.addEventListener('serialize', function (e) {
|
||
|
count++;
|
||
|
e.detail.serialize = e.detail.context;
|
||
|
});
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('foo', serialize(node, 'foo'));
|
||
|
assert.equal(1, count);
|
||
|
assert.equal('bar', serialize(node, 'bar'));
|
||
|
assert.equal(2, count);
|
||
|
assert.equal('baz', serialize(node, 'baz'));
|
||
|
assert.equal(3, count);
|
||
|
});
|
||
|
|
||
|
it('should bubble', function () {
|
||
|
node = document.createElement('div');
|
||
|
node.appendChild(document.createTextNode('foo'));
|
||
|
node.appendChild(document.createTextNode(' '));
|
||
|
node.appendChild(document.createTextNode('bar'));
|
||
|
|
||
|
// `node` must be inside the DOM for the "serialize" event to bubble
|
||
|
document.body.appendChild(node);
|
||
|
|
||
|
var count = 0;
|
||
|
node.addEventListener('serialize', function (e) {
|
||
|
count++;
|
||
|
assert.equal('foo', e.detail.context);
|
||
|
if (e.serializeTarget === node)
|
||
|
return;
|
||
|
else if (e.serializeTarget.nodeValue === 'foo')
|
||
|
e.detail.serialize = '…';
|
||
|
else
|
||
|
e.preventDefault();
|
||
|
}, false);
|
||
|
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('<div>…</div>', serialize(node, 'foo'));
|
||
|
assert.equal(4, count);
|
||
|
});
|
||
|
|
||
|
it('should support one-time callback function on Elements', function () {
|
||
|
node = document.createElement('div');
|
||
|
var count = 0;
|
||
|
|
||
|
function callback (e) {
|
||
|
count++;
|
||
|
e.detail.serialize = count;
|
||
|
}
|
||
|
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('1', serialize(node, callback));
|
||
|
assert.equal(1, count);
|
||
|
assert.equal('<div></div>', serialize(node));
|
||
|
assert.equal(1, count);
|
||
|
});
|
||
|
|
||
|
it('should support one-time callback function on NodeLists', function () {
|
||
|
node = document.createElement('div');
|
||
|
node.appendChild(document.createElement('strong'));
|
||
|
node.appendChild(document.createTextNode('foo'));
|
||
|
node.appendChild(document.createElement('em'));
|
||
|
node.appendChild(document.createTextNode('bar'));
|
||
|
|
||
|
var count = 0;
|
||
|
|
||
|
function callback (e) {
|
||
|
count++;
|
||
|
e.detail.serialize = count;
|
||
|
}
|
||
|
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('1234', serialize(node.childNodes, callback));
|
||
|
assert.equal(4, count);
|
||
|
assert.equal('<strong></strong>foo<em></em>bar', serialize(node.childNodes));
|
||
|
assert.equal(4, count);
|
||
|
});
|
||
|
|
||
|
it('should support one-time callback function on Nodes set in `e.detail.serialize`', function () {
|
||
|
node = document.createElement('div');
|
||
|
node.appendChild(document.createTextNode('foo'));
|
||
|
|
||
|
// `node` must be inside the DOM for the "serialize" event to bubble
|
||
|
document.body.appendChild(node);
|
||
|
|
||
|
var count = 0;
|
||
|
|
||
|
function callback (e) {
|
||
|
count++;
|
||
|
|
||
|
if (2 === count) {
|
||
|
assert.equal('foo', e.serializeTarget.nodeValue);
|
||
|
var text = document.createTextNode('bar');
|
||
|
e.detail.serialize = text;
|
||
|
} else if (3 === count) {
|
||
|
assert.equal('bar', e.serializeTarget.nodeValue);
|
||
|
var text = document.createTextNode('baz');
|
||
|
e.detail.serialize = text;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('<div>baz</div>', serialize(node, callback));
|
||
|
assert.equal(4, count);
|
||
|
});
|
||
|
|
||
|
it('should support one-time callback function on complex Nodes set in `e.detail.serialize`', function () {
|
||
|
node = document.createElement('div');
|
||
|
node.appendChild(document.createTextNode('foo'));
|
||
|
|
||
|
// `node` must be inside the DOM for the "serialize" event to bubble
|
||
|
document.body.appendChild(node);
|
||
|
|
||
|
var count = 0;
|
||
|
|
||
|
function callback (e) {
|
||
|
count++;
|
||
|
if (e.serializeTarget.nodeValue === 'foo') {
|
||
|
var el = document.createElement('p');
|
||
|
el.appendChild(document.createTextNode('x '));
|
||
|
el.appendChild(document.createElement('i'));
|
||
|
el.lastChild.appendChild(document.createTextNode('bar'));
|
||
|
|
||
|
e.detail.serialize = el;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
assert.equal(0, count);
|
||
|
assert.equal('<div><p>x <i>bar</i></p></div>', serialize(node, callback));
|
||
|
assert.equal(6, count);
|
||
|
});
|
||
|
|
||
|
});
|
||
|
|
||
|
});
|