DuyTa's picture
Upload folder using huggingface_hub
bc20498 verified
'use strict';
var domino = require('../lib');
var fs = require('fs');
var html = fs.readFileSync(__dirname + '/fixture/doc.html', 'utf8');
var Window = require('../lib/Window');
exports = exports.domino = {};
function createWindow(html, address) {
var document = domino.createDocument(html);
if (address) {
document.address = 'http://example.com/';
}
return new Window(document);
}
exports.matches = function() {
// see https://developer.mozilla.org/en-US/docs/Web/API/Element.matches
var d = createWindow(html).document;
var h1 = d.getElementById('lorem');
h1.matches('h1').should.equal(true);
h1.matches('body > h1').should.equal(true); // not rooted
h1.matches('h1 > p').should.equal(false);
h1.matches('h1,h2').should.equal(true);
h1.matches('h2,h1').should.equal(true);
};
exports.closest = function() {
// see https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
var html =
'<article>\n' +
' <div id="div-01">Here is div-01\n' +
' <div id="div-02">Here is div-02\n' +
' <div id="div-03">Here is div-03</div>\n' +
' </div>\n' +
' </div>\n' +
'</article>';
var document = createWindow(html).document;
var el = document.getElementById('div-03');
var r1 = el.closest('#div-02');
r1.id.should.equal('div-02');
var r2 = el.closest('div div');
r2.id.should.equal('div-03');
var r3 = el.closest('article > div');
r3.id.should.equal('div-01');
var r4 = el.closest(':not(div)');
r4.tagName.should.equal('ARTICLE');
var r5 = el.closest('#nothere');
(r5 === null).should.be.true();
// GH #154
var disconnected = document.createElement('div');
var r6 = disconnected.closest('#nothere');
(r6 === null).should.be.true();
var fragment = document.createDocumentFragment();
fragment.appendChild(disconnected);
var r7 = disconnected.closest('#nothere');
(r7 === null).should.be.true();
var r8 = disconnected.closest(':not(div)');
// This should not return DocumentFragment! Always should return an Element.
(r8 === null).should.be.true();
};
exports.querySelectorAll = function() {
var window = createWindow(html);
var d = window.document;
var nodeList = d.querySelectorAll('p');
nodeList.should.have.property('item');
nodeList.should.have.length(2);
nodeList = d.querySelectorAll('p:not(.foo)');
nodeList.should.have.length(1);
nodeList = d.querySelectorAll('tt.foo');
nodeList.should.have.length(2);
nodeList = d.querySelectorAll('tt:not(.bar)');
nodeList.should.have.length(1);
};
exports.qsaOrder = function() {
var window = domino.createDocument('<h2></h2><h3></h3><h3></h3><h2></h2><h3></h3>');
Array.from(window.querySelectorAll('h2, h3')).map(function(el) {
return el.tagName;
})
.should.eql(['H2', 'H3', 'H3', 'H2', 'H3']);
};
exports.orphanQSA = function() {
var document = domino.createDocument('<h1>foo</h1>');
var p = document.createElement('p');
p.querySelectorAll('p').should.have.length(0);
p.querySelectorAll('p').should.have.length(0);
};
// This is https://github.com/chjj/zest/issues/22
exports.tildeQSA = function() {
var document = domino.createDocument('<div class="foo-bar foo">');
var els = document.querySelectorAll('.foo');
els.should.have.length(1);
};
exports.rootQSA = function() {
// the root element should be both first-child and last-child
var document = domino.createDocument('foo');
var html = document.documentElement;
html.matches(':first-child').should.be.true();
html.matches(':last-child').should.be.true();
html.matches(':only-child').should.be.true();
html.matches(':first-of-type').should.be.true();
html.matches(':last-of-type').should.be.true();
html.matches(':nth-child(1)').should.be.true();
html.matches(':nth-child(2)').should.be.false();
html.matches(':nth-last-child(1)').should.be.true();
html.matches(':nth-last-child(2)').should.be.false();
html.matches(':nth-of-type(1)').should.be.true();
html.matches(':nth-of-type(2)').should.be.false();
html.matches(':nth-last-of-type(1)').should.be.true();
html.matches(':nth-last-of-type(2)').should.be.false();
};
exports.escapeQSA = function() {
var document = domino.createDocument('<p>foo');
// ensure that selector parsing can handle escaped characters
document.querySelectorAll('p\\22\\27p').should.have.length(0);
document.querySelectorAll('\\50').should.have.length(1);
};
exports.gh20 = function() {
var window = createWindow('');
var frag = window.document.createDocumentFragment();
frag.querySelectorAll('p').should.have.length(0);
frag.appendChild(window.document.createElement('p'));
frag.querySelectorAll('p').should.have.length(1);
frag.appendChild(window.document.createElement('p'));
frag.querySelectorAll('p').should.have.length(2);
};
exports.gh22 = function() {
var d=domino.createDocument("<div><h1>Hello world</h1><p>Hi</p></div>");
d.querySelectorAll('div').should.have.length(1);
d.body.querySelectorAll('div').should.have.length(1);
d.body.querySelectorAll('h1').should.have.length(1);
d.body.querySelectorAll('p').should.have.length(1);
var w=createWindow("<div><h1>Hello world</h1><p>Hi</p></div>");
d=w.document;
d.querySelectorAll('div').should.have.length(1);
d.body.querySelectorAll('div').should.have.length(1);
d.body.querySelectorAll('h1').should.have.length(1);
d.body.querySelectorAll('p').should.have.length(1);
};
exports.gh31 = function() {
var document, heading1, heading2;
document = domino.createDocument("<h1>First</h1><h1>Second</h1>");
document.querySelectorAll('h1').should.have.length(2);
heading1 = document.body.querySelector('h1');
heading1.getElementsByTagName('h1').should.have.length(0);
heading1.querySelectorAll('h1').should.have.length(0);
heading2 = document.body.querySelector('h1 + h1');
heading2.querySelectorAll('h1').should.have.length(0);
};
exports.gh38 = function() {
var d = domino.createDocument('<table><tr><th>Header cell</th><td>Data cell</td></tr></table>');
var r = d.querySelector('tr');
r.should.have.property('cells');
r.cells.should.have.length(2);
};
exports.evilHandler = function() {
var window = domino.createDocument('<a id="a" onclick="alert(\'breakin&#39;-stuff\')">');
window = window; // avoid defined-but-not-used lint error
};
exports.title = function() {
var d = domino.createDocument(html);
if (d.head) { d.documentElement.removeChild(d.head); }
d.should.have.property('head', null);
d.should.have.property('title', '');
d.querySelectorAll('head > title').should.have.length(0);
// per the spec, if there is no <head>, then setting Document.title should
// be a no-op.
d.title = "Lorem!";
d.title.should.equal('');
d.querySelectorAll('head > title').should.have.length(0);
// but if there is a <head>, then setting Document.title should create the
// <title> element if necessary.
d.documentElement.insertBefore(d.createElement('head'), d.body);
(d.head === null).should.be.false();
d.title.should.equal('');
d.title = "Lorem!";
d.title.should.equal("Lorem!");
d.querySelectorAll('head > title').should.have.length(1);
// verify that setting <title> works if there's already a title
d.title = "ipsum";
d.title.should.equal("ipsum");
d.querySelectorAll('head > title').should.have.length(1); // still only 1!
};
exports.children = function() {
var d = domino.createDocument(html);
var c = d.body.children;
c.should.have.length(4);
c.should.have.property('0');
var a = Array.prototype.slice.call(c);
a.should.be.an.instanceof(Array);
a.should.have.length(4);
d.body.appendChild(d.createElement('p'));
a = Array.prototype.slice.call(c);
a.should.have.length(5);
};
exports.attributes1 = function() {
var d = domino.createDocument();
var el = d.createElement('div');
el.setAttribute('foo', 'foo');
el.setAttribute('bar', 'bar');
el.attributes.should.have.length(2);
el.attributes.item(0).value.should.equal('foo');
el.removeAttribute('foo');
el.attributes.should.have.length(1);
el.attributes.item(0).name.should.equal('bar');
el.setAttribute('baz', 'baz');
el.attributes.should.have.length(2);
el.attributes.item(1).value.should.equal('baz');
};
exports.classList = function() {
var d = domino.createDocument();
var el = d.body;
el.className = 'foo bar boo';
var cl = el.classList;
cl.should.have.length(3);
cl[0].should.equal('foo');
cl.contains('bar').should.be.ok();
cl.contains('baz').should.not.be.ok();
cl.add('baz');
cl.contains('baz').should.be.ok();
cl.should.have.length(4);
el.className.should.match(/baz/);
cl.remove('foo');
cl.should.have.length(3);
el.className.should.not.match(/foo/);
cl[0].should.not.equal('foo');
};
exports.attributes2 = function() {
var d = domino.createDocument();
var div = d.createElement('div');
div.setAttribute('onclick', 't');
div.attributes.should.have.property('onclick');
div.attributes.onclick.should.have.property('value', 't');
div.removeAttribute('onclick');
(div.attributes.onclick === undefined).should.be.true();
};
// exports.jquery1_9 = function() {
// var window = createWindow(html);
// var f = __dirname + '/fixture/jquery-1.9.1.js';
// window._run(fs.readFileSync(f, 'utf8'), f);
// window.$.should.be.ok();
// window.$('.foo').should.have.length(3);
// };
exports.jquery2_2 = function() {
var window = createWindow(html);
window.$ = require(__dirname + '/fixture/jquery-2.2.0.js')(window);
window.$.should.be.ok();
window.$('.foo').should.have.length(3);
window.$.ajaxTransport("test", function() {
return { send: function() {}, abort: function() {} };
});
window.$.ajax({ url: 'test://', dataType: "test", timeout: 1, async: true });
};
exports.jquery3 = function() {
var window = createWindow(html);
window.$ = require(__dirname + '/../node_modules/jquery/dist/jquery.js')(window);
window.$.should.be.ok();
window.$('.foo').should.have.length(3);
window.$.ajaxTransport("test", function() {
return { send: function() {}, abort: function() {} };
});
window.$.ajax({ url: 'test://', dataType: "test", timeout: 1, async: true });
};
exports.treeWalker = function() {
var window = createWindow(html);
var d = window.document;
var root = d.getElementById('tw');
var tw = d.createTreeWalker(root, window.NodeFilter.SHOW_TEXT, function(n) {
return (n.data === 'ignore') ?
window.NodeFilter.FILTER_REJECT : window.NodeFilter.FILTER_ACCEPT;
});
tw.root.should.equal(root);
tw.currentNode.should.equal(root);
tw.whatToShow.should.equal(0x4);
var actual = [];
while (tw.nextNode() !== null) {
actual.push(tw.currentNode);
}
actual.length.should.equal(4);
actual.should.eql([
root.firstChild.firstChild,
root.firstChild.lastChild.firstChild,
root.lastChild.firstChild,
root.lastChild.lastChild.firstChild
]);
};
exports.nodeIterator = function() {
var window = createWindow(html);
var d = window.document;
var root = d.getElementById('tw');
var ni = d.createNodeIterator(root, window.NodeFilter.SHOW_TEXT, function(n) {
return (n.data === 'ignore') ?
window.NodeFilter.FILTER_REJECT : window.NodeFilter.FILTER_ACCEPT;
});
ni.root.should.equal(root);
ni.referenceNode.should.equal(root);
ni.whatToShow.should.equal(0x4);
var actual = [];
for (var n = ni.nextNode(); n ; n = ni.nextNode()) {
actual.push(n);
}
actual.length.should.equal(4);
actual.should.eql([
root.firstChild.firstChild,
root.firstChild.lastChild.firstChild,
root.lastChild.firstChild,
root.lastChild.lastChild.firstChild
]);
};
exports.nodeIterator2 = function() {
/* jshint bitwise: false */
var document = domino.createDocument(
'<a>123<b>456<script>alert(1)</script></b></a>789'
);
var NodeFilter = domino.impl.NodeFilter;
var ni = document.createNodeIterator(
document.body,
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT,
function() { return NodeFilter.FILTER_ACCEPT; },
false
);
var node = ni.nextNode();
node.tagName.should.equal('BODY');
node = ni.nextNode();
node.tagName.should.equal('A');
node = ni.nextNode();
node.nodeName.should.equal('#text');
node = ni.nextNode();
node.tagName.should.equal('B');
node.insertAdjacentHTML('AfterEnd', node.innerHTML);
node.parentNode.removeChild(node);
node = ni.nextNode();
node.nodeName.should.equal('#text');
node = ni.nextNode();
node.tagName.should.equal('SCRIPT');
node.parentNode.removeChild(node);
node = ni.nextNode();
node.nodeName.should.equal('#text');
node = ni.nextNode();
(node === null).should.be.true();
document.body.innerHTML.should.equal('<a>123456</a>789');
/* jshint bitwise: true */
};
exports.innerHTML = function() {
var d = domino.createDocument();
['pre','textarea','listing'].forEach(function(elementName) {
var div = d.createElement('div');
var el = d.createElement(elementName);
el.innerHTML = "a";
div.appendChild(el);
// no extraneous newline after element tag in this case
div.innerHTML.should.equal('<'+elementName+'>a</'+elementName+'>');
el.innerHTML = "\nb";
// Note that this doesn't roundtrip:
// see https://github.com/whatwg/html/issues/944
div.innerHTML.should.equal('<'+elementName+'>\nb</'+elementName+'>');
});
};
exports.outerHTML = function() {
var tests = [
// This doesn't round trip:
// see https://github.com/whatwg/html/issues/944
//'<body><pre>\n\na\n</pre></body>',
'<body bgcolor="white"><h1 style="color: red">\nOne\n2 &amp; 3</h1></body>',
`<body data-test="&lt;&gt;&amp;&quot;\'"></body>`
];
tests.forEach(function(html) {
var d = domino.createDocument(html);
// Verify round-tripping.
d.body.outerHTML.should.equal(html);
});
};
exports.largeAttribute = function() {
var size = 400000;
// work around a performance regression in node 0.4.x - 0.6.x
if (/^v0\.[0-6]\./.test(process.version)) { size = 50000; }
var html = '<body><span data-large="';
for (var i=0; i<size; i++) {
html += '&amp;';
}
html += '"></span></body>';
// this should not crash with a stack overflow!
domino.createDocument(html);
};
exports.createTextNodeWithNonString = function() {
var document = domino.createDocument('<html></html>');
var tests = [
[false, 'false'],
[NaN, 'NaN'],
[123, '123'],
[{}, '[object Object]'],
[[], ''],
[null, 'null'],
[undefined, 'undefined'],
];
for(var i=0; i<tests.length; i++) {
var element = document.createElement('div');
var textNode = document.createTextNode(tests[i][0]);
element.appendChild(textNode);
element.innerHTML.should.equal(tests[i][1]);
}
};
exports.adoption = function() {
// See https://github.com/fgnass/domino/pull/36
var html = "<b>X<b>Y</b>Z</b>";
var doc = domino.createDocument(html);
doc.body.innerHTML.should.equal(html);
};
exports.attributeSelector = function() {
var html = '<h1>foo</h1><h2 id="x" title="y" lang="en" dir="ltr" ' +
'accessKey="z" hidden tabIndex="2">bar</h2>';
var doc = domino.createDocument(html);
var h1 = doc.querySelector('h1');
h1.matches('*[id]').should.equal(false);
h1.matches('*[title]').should.equal(false);
h1.matches('*[lang]').should.equal(false);
h1.matches('*[dir]').should.equal(false);
h1.matches('*[accessKey]').should.equal(false);
h1.matches('*[hidden]').should.equal(false);
h1.matches('*[tabIndex]').should.equal(false);
var h2 = doc.querySelector('h2');
h2.matches('*[id]').should.equal(true);
h2.matches('*[title]').should.equal(true);
h2.matches('*[lang]').should.equal(true);
h2.matches('*[dir]').should.equal(true);
h2.matches('*[accessKey]').should.equal(true);
h2.matches('*[hidden]').should.equal(true);
h2.matches('*[tabIndex]').should.equal(true);
h1.matches('*[matches]').should.equal(false);
h1.matches('*[querySelector]').should.equal(false);
h1.matches('*[isHTML]').should.equal(false);
};
exports.crHandling = function() {
var html = '<div\rid=a data-test=1\rfoo="\r"\rbar=\'\r\'\rbat=\r>\r</div\r>';
var doc = domino.createDocument(html);
var div = doc.querySelector('#a');
(div != null).should.be.true(); // jshint ignore:line
// all \r should be converted to \n
div.outerHTML.should.equal('<div id="a" data-test="1" foo="\n" bar="\n" bat="">\n</div>');
};
exports.eqAttr = function() {
var html = "<div id=a ==x><a=B></A=b></div>";
var doc = domino.createDocument(html);
var div = doc.querySelector('#a');
(div != null).should.be.true(); // jshint ignore:line
div.attributes.length.should.equal(2);
div.attributes.item(1).name.should.equal('=');
div.children.length.should.equal(1);
div.children[0].tagName.should.equal('A=B');
};
exports.tagNameCase = function() {
// See https://github.com/fgnass/domino/pull/41
var impl = domino.createDOMImplementation();
var namespace = 'http://schemas.xmlsoap.org/soap/envelope/';
var qualifiedName = 'Envelope';
var doc = impl.createDocument(namespace, qualifiedName, null);
doc.documentElement.tagName.should.equal(qualifiedName);
};
exports.fastAttributes = function() {
// test the SIMPLETAG/SIMPLEATTR path in HTMLParser
var html = "<div id=a b=\"x &quot;y\" c='a \rb'><\np></div>";
var doc = domino.createDocument(html);
var div = doc.querySelector('#a');
(div != null).should.be.true(); // jshint ignore:line
div.attributes.length.should.equal(3);
div.attributes.item(1).value.should.equal('x "y');
div.attributes.item(2).value.should.equal('a \nb');
div.children.length.should.equal(0);
};
exports.anchorElement = function() {
var html = "<a href='http://user:[email protected]:1234/foo/bar?bat#baz'>!</a>";
var doc = domino.createDocument(html);
var a = doc.querySelector('a');
(a != null).should.be.true(); // jshint ignore:line
a.href.should.equal('http://user:[email protected]:1234/foo/bar?bat#baz');
a.protocol.should.equal('http:');
a.host.should.equal('example.com:1234');
a.hostname.should.equal('example.com');
a.port.should.equal('1234');
a.pathname.should.equal('/foo/bar');
a.search.should.equal('?bat');
a.hash.should.equal('#baz');
a.username.should.equal('user');
a.password.should.equal('pass');
a.origin.should.equal('http://example.com:1234');
// now try mutating!
a.protocol = 'https:';
a.href.should.equal('https://user:[email protected]:1234/foo/bar?bat#baz');
a.hostname = 'other.net';
a.href.should.equal('https://user:[email protected]:1234/foo/bar?bat#baz');
a.port = 5678;
a.href.should.equal('https://user:[email protected]:5678/foo/bar?bat#baz');
a.pathname = '/blam/';
a.href.should.equal('https://user:[email protected]:5678/blam/?bat#baz');
a.search = '?bat&banana';
a.href.should.equal('https://user:[email protected]:5678/blam/?bat&banana#baz');
a.hash = '#oranges';
a.href.should.equal('https://user:[email protected]:5678/blam/?bat&banana#oranges');
a.username = 'joe';
a.href.should.equal('https://joe:[email protected]:5678/blam/?bat&banana#oranges');
a.password = 'smith';
a.href.should.equal('https://joe:[email protected]:5678/blam/?bat&banana#oranges');
};
exports.gh59 = function() {
var html = '<html><body><span style="display:none">foo</span></body></html>';
var doc = domino.createDocument(html);
doc.querySelectorAll('span[style]').should.have.length(1);
doc.querySelectorAll('span[style="display:none"]').should.have.length(1);
doc.querySelectorAll('span[style*="display:none"]').should.have.length(1);
};
exports.duplicateID = function() {
var doc = domino.createDocument('<root></root>');
var root = doc.documentElement;
function makeElement(name) {
var elt = doc.createElement(name);
elt.setAttribute("id", "x");
return elt;
}
var a = root.appendChild(makeElement("a"));
var b = root.appendChild(makeElement("b"));
var c = root.appendChild(makeElement("c"));
var d = root.appendChild(makeElement("d"));
doc.getElementById("x").should.equal(a);
root.removeChild(a);
doc.getElementById("x").should.equal(b);
root.removeChild(c);
root.removeChild(b);
doc.getElementById("x").should.equal(d);
root.removeChild(d);
(doc.getElementById("x") === null).should.be.true();
};
exports.normalize = function() {
var doc = domino.createDocument('<span id="x"><!---->foo</span>');
var span = doc.getElementById("x");
span.appendChild(doc.createTextNode('bar'));
span.outerHTML.should.equal('<span id="x"><!---->foobar</span>');
span.normalize();
span.outerHTML.should.equal('<span id="x"><!---->foobar</span>');
span.childNodes[1].nodeValue.should.equal('foobar');
};
exports.replaceChild = function() {
var impl = domino.createDOMImplementation();
var doc = impl.createDocument();
var root = doc.appendChild(doc.createElement('root'));
root.outerHTML.should.equal('<root></root>');
var a = root.appendChild(doc.createElement('a'));
root.outerHTML.should.equal('<root><a></a></root>');
var b = doc.createElement('b');
function capture(f) {
var events = [];
doc._setMutationHandler(function(info) {
events.push(info);
});
f();
doc._setMutationHandler(null);
return events;
}
// Replace with unrooted
capture(function() {
root.replaceChild(b, a).should.equal(a);
}).should.deepEqual([
{
type: 4, // Remove
target: root,
node: a
},
{
type: 6, // Insert
target: root,
node: b
}]);
root.outerHTML.should.equal('<root><b></b></root>');
root.replaceChild(a, b).should.equal(b);
root.outerHTML.should.equal('<root><a></a></root>');
// Move node
var c = doc.createElement('c');
root.appendChild(b);
root.appendChild(c);
capture(function() {
root.replaceChild(c, a);
}).should.deepEqual([
{
type: 4, // Remove
target: root,
node: a
},
{
type: 5, // Move
target: c
}]);
root.outerHTML.should.equal('<root><c></c><b></b></root>');
// Replace under unrooted parent
var df = doc.createDocumentFragment();
var d = df.appendChild(doc.createElement('d'));
var e = df.appendChild(doc.createElement('e'));
var f = doc.createElement('f');
df.replaceChild(f, e);
df.serialize().should.equal('<d></d><f></f>');
d = d; // avoid defined-but-not-used warning
// Replace rooted node with document fragment
root.appendChild(a);
root.replaceChild(df, b);
root.outerHTML.should.equal('<root><c></c><d></d><f></f><a></a></root>');
};
exports.contains = function() {
// see https://developer.mozilla.org/en-US/docs/Web/API/Node/contains
var document = createWindow(html).document;
var h1 = document.getElementById('lorem');
h1.contains(null).should.equal(false);
h1.contains(h1).should.equal(true);
h1.childNodes[0].contains(h1).should.equal(false);
h1.contains(h1.childNodes[0]).should.equal(true);
document.body.contains(h1).should.equal(true);
var nodeList = document.querySelectorAll('p');
h1.contains(nodeList[0]).should.equal(false);
document.body.contains(nodeList[0]).should.equal(true);
nodeList[0].contains(nodeList[1]).should.equal(false);
nodeList[1].contains(nodeList[0]).should.equal(false);
};
exports.parseImportant = function() {
var html = '<p style="font-family:sans-serif; text-decoration:none !important">foo</p>';
var doc = domino.createDocument(html);
var p = doc.querySelector('p');
p.style.fontFamily.should.equal('sans-serif');
p.style.textDecoration.should.equal('none');
};
exports.gh70 = function() {
var document = domino.createDocument('<h1 class="hello">Hello world</h1>');
var h1 = document.querySelector('h1');
var classAttr = h1.attributes.item(0);
classAttr.value.should.equal('hello');
classAttr.nodeValue.should.equal('hello');
classAttr.textContent.should.equal('hello');
classAttr.nodeValue = 'nodeValue';
classAttr.value.should.equal('nodeValue');
classAttr.nodeValue.should.equal('nodeValue');
classAttr.textContent.should.equal('nodeValue');
classAttr.textContent = 'textContent';
classAttr.value.should.equal('textContent');
classAttr.nodeValue.should.equal('textContent');
classAttr.textContent.should.equal('textContent');
classAttr.innerText.should.equal('textContent');
};
exports.innerText = function() {
var document = domino.createDocument('<div>Hello <h1>world!</h1></div>');
var div = document.querySelector('div');
div.innerText.should.equal('Hello world!'); // getter
div.innerText = 'Hi'; // setter
div.textContent.should.equal('Hi');
div.innerText.should.equal('Hi');
};
exports.gh71 = function() {
var document = domino.createDocument('<h1 style="color:red !important">Hello world</h1>');
var h1 = document.querySelector('h1');
h1.style.display = 'none';
h1.outerHTML.should.equal('<h1 style="color: red !important; display: none;">Hello world</h1>');
};
exports.gh72 = function() {
var window = createWindow('<h1>Hello, world!</h1>');
window.setTimeout.should.have.type('function');
window.clearTimeout.should.have.type('function');
window.setInterval.should.have.type('function');
window.clearInterval.should.have.type('function');
};
exports.navigatorID = function() {
var window = createWindow('<h1>Hello, world!</h1>');
window.navigator.appCodeName.should.equal("Mozilla");
window.navigator.taintEnabled().should.equal(false);
};
exports.template1 = function() {
var document = domino.createDocument("<table><tbody><template id=row><tr><td><td>");
document.body.innerHTML.should.equal('<table><tbody><template id="row"><tr><td></td><td></td></tr></template></tbody></table>');
var t = document.getElementById("row");
t.should.be.an.instanceof(domino.impl.HTMLTemplateElement);
t.childNodes.length.should.equal(0);
t.content.should.be.an.instanceof(domino.impl.DocumentFragment);
t.content.serialize().should.equal("<tr><td></td><td></td></tr>");
document.querySelectorAll("td").length.should.equal(0);
t.content.querySelectorAll("td").length.should.equal(2);
t.content.ownerDocument.should.not.equal(document);
t.content.querySelectorAll("*").map(function(el) {
el.ownerDocument.should.equal(t.content.ownerDocument);
});
};
exports.template2 = function() {
// Templates go in <head> by default.
var document = domino.createDocument("<template>x<!--hi");
document.head.childNodes.length.should.equal(1);
document.head.children[0].tagName.should.equal("TEMPLATE");
var df = document.head.children[0].content;
df.should.be.an.instanceof(domino.impl.DocumentFragment);
df.ownerDocument.should.not.equal(document);
df.childNodes.length.should.equal(2);
df.childNodes[0].ownerDocument.should.equal(df.ownerDocument);
df.childNodes[1].ownerDocument.should.equal(df.ownerDocument);
document.head.innerHTML.should.equal('<template>x<!--hi--></template>');
};
// HTMLTemplateElement.innerHTML
// see https://github.com/w3c/DOM-Parsing/issues/1
exports.template3 = function() {
var document = domino.createDocument();
var t = document.createElement("template");
t.should.be.an.instanceof(domino.impl.HTMLTemplateElement);
t.childNodes.length.should.equal(0);
t.content.should.be.an.instanceof(domino.impl.DocumentFragment);
// This is the key line:
t.innerHTML = '<div>abc</div><p>def</p>';
t.innerHTML.should.equal('<div>abc</div><p>def</p>');
t.content.ownerDocument.should.not.equal(document);
t.content.childNodes.length.should.equal(2);
t.content.querySelectorAll("*").map(function(el) {
el.ownerDocument.should.equal(t.content.ownerDocument);
});
// Non-standard (gh #73)
t.content.outerHTML.should.equal('<div>abc</div><p>def</p>');
};
exports.fosterParent1 = function() {
var document = domino.createDocument('<table><tr>x<a>foo<td>y');
// In this case the "x<a>" gets foster-parented *before* the <tr>
document.body.innerHTML.should.equal("x<a>foo</a><table><tbody><tr><td>y</td></tr></tbody></table>");
};
exports.fosterParent2 = function() {
var document = domino.createDocument('foster test');
var thead = document.createElement("thead");
// exercise the "no table in open element stack" case in foster parenting
// algorithm.
thead.innerHTML = "<tr>x<a>foo<td>y";
// Note how "x" got placed *after* the <tr> in this case.
thead.outerHTML.should.equal('<thead><tr><td>y</td></tr>x<a>foo</a></thead>');
};
exports.fosterParent3 = function() {
var document = domino.createDocument('<body><template><table><tr>x</template><table><template><tr>y');
document.body.innerHTML.should.equal("<template>x<table><tbody><tr></tr></tbody></table></template><table><template><tr></tr>y</template></table>");
var templates = document.querySelectorAll("template");
templates.length.should.equal(2);
document.querySelectorAll("tr").length.should.equal(0);
Array.prototype.forEach.call(templates, function(t) {
t.ownerDocument.should.equal(document);
t.content.ownerDocument.should.not.equal(document);
t.content.querySelectorAll("*").map(function(el) {
el.ownerDocument.should.equal(t.content.ownerDocument);
});
});
templates[0].content.ownerDocument.should.equal(
templates[1].content.ownerDocument
);
};
exports.canvasTag = function() {
var document = domino.createDocument('<canvas width=23 height=45>');
var canvas = document.querySelector('canvas');
canvas.should.be.instanceof(domino.impl.HTMLElement);
canvas.should.be.instanceof(domino.impl.HTMLCanvasElement);
canvas.should.not.be.instanceof(domino.impl.HTMLUnknownElement);
canvas.width.should.equal(23);
canvas.height.should.equal(45);
};
exports.dialogTag = function() {
// <p> should be closed before <dialog>
var document = domino.createDocument('<div><p>x<dialog open returnvalue="foo">y');
document.body.innerHTML.should.equal('<div><p>x</p><dialog open="" returnvalue="foo">y</dialog></div>');
var dialog = document.querySelector('dialog');
dialog.should.be.instanceof(domino.impl.HTMLElement);
dialog.should.be.instanceof(domino.impl.HTMLDialogElement);
dialog.should.not.be.instanceof(domino.impl.HTMLUnknownElement);
dialog.open.should.equal(true);
dialog.returnValue.should.equal("foo");
};
exports.mainTag = function() {
// <p> should be closed before <main>
var document = domino.createDocument('<div><p>x<main>y');
document.body.innerHTML.should.equal('<div><p>x</p><main>y</main></div>');
var main = document.querySelector('main');
main.should.be.instanceof(domino.impl.HTMLElement);
main.should.not.be.instanceof(domino.impl.HTMLUnknownElement);
};
exports.menuItemTag = function() {
// <menuitem> should be special
var document = domino.createDocument('<menuitem type="checkbox" checked default>');
document.body.innerHTML.should.equal('<menuitem type="checkbox" checked="" default=""></menuitem>');
var menuitem = document.querySelector('menuitem');
menuitem.should.be.instanceof(domino.impl.HTMLElement);
menuitem.should.be.instanceof(domino.impl.HTMLMenuItemElement);
menuitem.should.not.be.instanceof(domino.impl.HTMLUnknownElement);
menuitem.type.should.equal("checkbox");
menuitem.checked.should.equal(true);
menuitem.disabled.should.equal(false);
menuitem.default.should.equal(true);
};
exports.rubyTags = function() {
var document = domino.createDocument(
'<p><ruby id=a>base<rt>annotation</ruby>' +
'<ruby id=b><rb>上<rb>手<rt>じよう<rt>ず<rtc><rt>jou<rt>zu'
);
document.body.innerHTML.should.equal(
'<p><ruby id="a">base<rt>annotation</rt></ruby>' +
'<ruby id="b"><rb>上</rb><rb>手</rb><rt>じよう</rt><rt>ず</rt><rtc><rt>jou</rt><rt>zu</rt></rtc></ruby></p>'
);
Array.prototype.forEach.call(
document.querySelectorAll('ruby,rb,rp,rt,rtc'), function(el) {
el.should.be.instanceof(domino.impl.HTMLElement);
el.should.not.be.instanceof(domino.impl.HTMLUnknownElement);
});
};
exports.sourceTag = function() {
var document = domino.createDocument('<base href=http://example.com><video controls><source src="foo.webm" type="video/webm">Sorry, no HTML5 video.');
document.body.innerHTML.should.equal('<video controls=""><source src="foo.webm" type="video/webm">Sorry, no HTML5 video.</video>');
var source = document.querySelector('source');
source.should.be.instanceof(domino.impl.HTMLElement);
source.should.be.instanceof(domino.impl.HTMLSourceElement);
source.should.not.be.instanceof(domino.impl.HTMLUnknownElement);
source.src.should.equal("http://example.com/foo.webm");
source.type.should.equal("video/webm");
};
exports.trackTag = function() {
var document = domino.createDocument('<base href=http://example.com><video poster="foo.jpg"><source src="foo.webm" type="video/webm"><track kind="captions" src="en-captions.vtt" srclang="en">');
document.body.innerHTML.should.equal('<video poster="foo.jpg"><source src="foo.webm" type="video/webm"><track kind="captions" src="en-captions.vtt" srclang="en"></video>');
var track = document.querySelector('track');
track.should.be.instanceof(domino.impl.HTMLElement);
track.should.be.instanceof(domino.impl.HTMLTrackElement);
track.should.not.be.instanceof(domino.impl.HTMLUnknownElement);
track.kind.should.equal("captions");
track.src.should.equal("http://example.com/en-captions.vtt");
track.srclang.should.equal("en");
};
exports.elementInterface = function() {
[
"acronym", "basefont", "big", "center", "nobr", "noembed", "noframes",
"plaintext", "rb", "rtc", "strike", "tt"
].forEach(function(tag) {
var document = domino.createDocument('<'+tag+'>');
var elt = document.querySelector(tag);
elt.should.be.instanceof(domino.impl.HTMLElement);
elt.should.not.be.instanceof(domino.impl.HTMLUnknownElement);
});
[
"listing", "xmp", "pre"
].forEach(function(tag) {
var document = domino.createDocument('<'+tag+'>');
var elt = document.querySelector(tag);
elt.should.be.instanceof(domino.impl.HTMLElement);
elt.should.be.instanceof(domino.impl.HTMLPreElement);
elt.should.not.be.instanceof(domino.impl.HTMLUnknownElement);
});
};
exports.gh79 = function() {
// CSS identifiers can only contain the characters [a-zA-Z0-9] and
// ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the
// underscore (_). But they *can* have escaped characters.
var doc = '<div id="cite_note-13.3F_It_Can\'t_Be!-3"></div>';
var document = domino.createDocument(doc);
document.body.innerHTML.should.equal(doc);
(function() {
document.querySelector("#cite_note-13.3F_It_Can't_Be!-3");
}).should.throw({ name: 'SyntaxError' });
var div = document.querySelectorAll("#cite_note-13\\.3F_It_Can\\'t_Be\\!-3");
div.length.should.equal(1);
};
exports.small_list = function() {
var doc = '<ul><li><small class=foo>x</li><li>y<ul><li>b</li><li>c</small></li></ul></li></ul>';
var document = domino.createDocument(doc);
var smalls = document.querySelectorAll('small');
smalls.length.should.equal(4);
for (var i=0; i<smalls.length; i++) {
smalls[i].classList.contains('foo').should.be.true();
}
};
exports.menuitem = function() {
var doc = '<menuitem id=a label=" b "><menuitem id=c> d <b> e ';
var document = domino.createDocument(doc);
document.body.innerHTML.should.equal('<menuitem id="a" label=" b "></menuitem><menuitem id="c"> d <b> e </b></menuitem>');
var itema = document.getElementById('a');
(itema != null).should.be.true(); // jshint ignore:line
itema.should.be.an.instanceof(domino.impl.HTMLMenuItemElement);
itema.label.should.equal(' b ');
itema.label = ' x ';
itema.label.should.equal(' x ');
itema.hasAttribute('label').should.be.true();
itema.getAttribute('label').should.equal(' x ');
itema.outerHTML.should.equal('<menuitem id="a" label=" x "></menuitem>');
var itemb = document.getElementById('c');
(itemb != null).should.be.true(); // jshint ignore:line
itemb.should.be.an.instanceof(domino.impl.HTMLMenuItemElement);
itemb.label.should.equal('d e');
itemb.label = ' y ';
itemb.label.should.equal(' y ');
itemb.hasAttribute('label').should.be.true();
itemb.getAttribute('label').should.equal(' y ');
itemb.outerHTML.should.equal('<menuitem id="c" label=" y "> d <b> e </b></menuitem>');
};
exports.createSvgElements = function() {
var document = domino.createDocument();
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
document.body.appendChild(svg);
svg.should.be.instanceOf(domino.impl.SVGSVGElement);
document.body.innerHTML.should.equal("<svg></svg>");
};
exports.gh95 = function() {
var document = domino.createDocument(
'<body><a href="foo\'s">bar</a></body>'
);
(function() {
document.querySelectorAll("a[href=foo's]");
}).should.throw({ name: 'SyntaxError' });
document.querySelectorAll("a[href=foo\\'s]").length.should.equal(1);
};
exports.propertyWritability = function () { // gh #89
var window = createWindow('');
var document = domino.createDocument();
var assertWritable = function(object, property) {
var replacement = function () { };
object[property] = replacement;
object[property].should.equal(replacement, property + " should be writable");
};
assertWritable(window, 'HTMLElement');
assertWritable(document, 'importNode');
assertWritable(document, 'createElement');
assertWritable(document, 'createElementNS');
};
exports.gh90 = function() {
var doc = '<input type="checkbox">';
var document = domino.createDocument(doc);
document.body.innerHTML.should.equal(doc);
var input = document.querySelector('input');
input.checked.should.equal(false);
input.checked = true;
input.checked.should.equal(true);
input.outerHTML.should.equal('<input type="checkbox" checked="">');
input.checked = false;
input.checked.should.equal(false);
input.outerHTML.should.equal(doc);
// Now test again, using hasAttribute/hasAttributeNS directly.
input.hasAttribute('checked').should.equal(false);
input.hasAttributeNS(null, 'checked').should.equal(false);
input.hasAttributeNS('foo', 'checked').should.equal(false);
input.setAttribute('checked', 'bar');
input.setAttributeNS('foo', 'checked', 'bat');
input.hasAttribute('checked').should.equal(true);
input.hasAttributeNS(null, 'checked').should.equal(true);
input.hasAttributeNS('foo', 'checked').should.equal(true);
input.removeAttribute('checked');
input.removeAttributeNS('foo', 'checked');
input.hasAttribute('checked').should.equal(false);
input.hasAttributeNS(null, 'checked').should.equal(false);
input.hasAttributeNS('foo', 'checked').should.equal(false);
};
exports.gh98 = function() {
var doc = '<a href="/"></a>';
var document = domino.createDocument(doc);
var a = document.querySelector('a');
(a.style.getPropertyValue('background') === '').should.be.true();
};
exports.gh99 = function() {
// test '#foo' optimization in querySelectorAll
var window = createWindow(
'<!DOCTYPE html><html><body></body></html>'
);
var doc = window.document;
var match = doc.querySelectorAll('#coordinates');
match.length.should.equal(0);
if (Array.from) {
Array.from(match).length.should.equal(0);
}
(match[0] === undefined).should.be.true();
// continue test, now w/ multiple elements sharing same id.
doc.body.innerHTML = '<p id=a>x</p><p id=a>y</p>';
match = doc.querySelectorAll('#a');
match.length.should.equal(2);
if (Array.from) {
Array.from(match).length.should.equal(2);
}
match[0].textContent.should.equal('x');
match[1].textContent.should.equal('y');
};
exports.gh112 = function() {
// attributes named 'xmlns' are fine. (gh #112)
var window = createWindow(
'<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><b></b></html>'
);
var document = window.document;
document.documentElement.setAttribute('xmlns', 'test');
var b = document.querySelector('b');
b.innerHTML = '<test></test>';
var test = document.querySelector('test');
// Note that this seems contrary to what is implied by
// https://lists.w3.org/Archives/Public/www-dom/2011JulSep/0153.html
// but matches what modern browsers do.
b.namespaceURI.should.equal('http://www.w3.org/1999/xhtml');
test.namespaceURI.should.equal('http://www.w3.org/1999/xhtml');
};
exports.gh107 = function() {
var document = domino.createDocument();
document.scrollingElement.should.equal(document.documentElement);
};
exports.gh109 = function() {
var document = domino.createDocument();
var div = document.createElement('div');
div.classList.add('one', 'two');
div.classList.length.should.equal(2);
div.classList.contains('one').should.be.true();
div.classList.contains('two').should.be.true();
div.classList.remove('one', 'two');
div.classList.length.should.equal(0);
div.classList.contains('one').should.be.false();
div.classList.contains('two').should.be.false();
};
exports.gh111 = function() {
var document = domino.createDocument();
var div = document.createElement('div');
div.classList.toggle('a');
div.classList.toggle('b', true);
div.classList.length.should.equal(2);
div.classList.value.should.equal('a b');
div.classList.toggle('a');
div.classList.toggle('b', true);
div.classList.length.should.equal(1);
div.classList.value.should.equal('b');
div.classList.toggle('b', false);
div.classList.length.should.equal(0);
div.classList.value.should.equal('');
div.classList.value = ' foo\rbat \n baz a\nb\f\t';
div.classList.value.should.equal(' foo\rbat \n baz a\nb\f\t');
div.classList.length.should.equal(5);
div.classList.contains('').should.be.false();
div.classList.contains(' ').should.be.false();
div.classList.contains('\n').should.be.false();
div.classList.contains('\f').should.be.false();
div.classList[0].should.equal('foo');
div.classList[1].should.equal('bat');
div.classList.item(2).should.equal('baz');
div.classList.contains('a').should.be.true();
div.classList.contains('b').should.be.true();
div.classList.replace('bat', 'ball');
div.classList.value.should.equal('foo ball baz a b');
div.classList.length.should.equal(5);
div.classList.contains('ball').should.be.true();
div.classList[1].should.equal('ball');
};
exports.gh126 = function() {
var document = domino.createDocument();
var div = document.createElement('div');
div.classList.length.should.equal(0);
div.classList.add();
div.classList.length.should.equal(0);
div.classList.add(undefined);
div.classList.add(null);
div.classList.length.should.equal(2);
div.classList.remove();
div.classList.length.should.equal(2);
div.classList.contains(undefined).should.be.true();
div.classList.contains('undefined').should.be.true();
div.classList.contains(null).should.be.true();
div.classList.contains('null').should.be.true();
div.classList.remove(undefined, null);
div.classList.length.should.equal(0);
div.classList.contains(undefined).should.be.false();
div.classList.contains('undefined').should.be.false();
div.classList.contains(null).should.be.false();
div.classList.contains('null').should.be.false();
};
exports.arrayfrom = function() {
// If your version of node supports Array.from, it should support
// Array.from(node.attributes) ... even though we don't use proxies.
if (typeof(Array.from) !== 'function') { return; }
var d = domino.createDocument('');
var e = d.createElement('span');
e.setAttribute('a','1');
e.setAttribute('b','2');
var a = Array.from(e.attributes);
a.should.have.length(2);
a[0].should.have.property('name','a');
a[0].should.have.property('value','1');
a[1].should.have.property('name','b');
a[1].should.have.property('value','2');
};
exports.gh119 = function() {
var document = domino.createDocument('<div></div>');
var div = document.querySelector('div');
div.style.flex = '1 1 0px';
div.outerHTML.should.equal('<div style="flex: 1 1 0px;"></div>');
document = domino.createDocument('<div></div>');
div = document.querySelector('div');
div.style.flexFlow = 'row wrap';
div.outerHTML.should.equal('<div style="flex-flow: row wrap;"></div>');
document = domino.createDocument('<div></div>');
div = document.querySelector('div');
div.style.flexBasis = '0px';
div.style.flexGrow = 1;
div.style.flexShrink = 1;
div.style.flexDirection = 'column';
div.style.flexWrap = 'wrap';
div.outerHTML.should.equal('<div style="flex-basis: 0px; flex-grow: 1; flex-shrink: 1; flex-direction: column; flex-wrap: wrap;"></div>');
};
exports.setPropertyClipBox = function() {
var document = domino.createDocument('<div></div>');
var div = document.querySelector('div');
div.style['clip-path'] = 'margin-box';
div.outerHTML.should.equal('<div style="clip-path: margin-box;"></div>');
};
exports.setPropertyNull = function() {
var document = domino.createDocument('<div style="color:red;"></div>');
var div = document.querySelector('div');
div.style.setProperty('--bg-color', null);
div.outerHTML.should.equal('<div style="color:red;"></div>');
var document = domino.createDocument('<div style="color:green;"></div>');
var div = document.querySelector('div');
div.style.color = null;
div.outerHTML.should.equal('<div style=""></div>');
};
exports.gh121 = function() {
var document = domino.createDocument('<div></div>');
var div = document.querySelector('div');
div.className = 'ab a';
div.matches('.a').should.be.true();
div.matches('[class~=a]').should.be.true();
div.className = 'a ab';
div.matches('.a').should.be.true();
div.matches('[class~=a]').should.be.true();
};
exports.gh127 = function() {
var document = domino.createDocument('<a href="#foo"></a><a href="http://#foo"></a>');
var aEls = document.querySelectorAll('a');
aEls.length.should.equal(2);
for (var i=0; i < aEls.length; i++) {
aEls[i].hash.should.equal('#foo');
}
};
exports.gh128 = function() {
var document = domino.createDocument('<a target="xInSeNsItIvEx"></a><a target="xYx"></a>');
var expected = document.querySelectorAll('a')[0];
[
{ sel: '[target*="insensitive" i]' },
{ sel: "[target='XinsensitiveX'i]" },
{ sel: '[target=XINSENSITIVEX i]' },
{ sel: '[target=XINSENSITIVEXi]', expectFail: true },
{ sel: '[target^=XI i]' },
{ sel: '[target^=XIi]', expectFail: true },
{ sel: '[target^=XI]', expectFail: true },
{ sel: '[target$=EX i]' },
{ sel: '[target$="ex"i]' },
{ sel: '[target~="xinsensitivex"i]' },
{ sel: '[target|="xinsensitivex" i]' },
].forEach(function(oneCase) {
var a = document.querySelectorAll('*'+oneCase.sel);
if (oneCase.expectFail) {
a.length.should.equal(0);
} else {
a.length.should.equal(1);
a[0].should.be.exactly(expected);
}
});
};
exports.gh129 = function() {
var window = createWindow();
var document = window.document;
var div = document.body.appendChild(document.createElement('div'));
div.innerHTML = '<p></p><span></span>';
var span = div.firstChild.nextSibling;
div.textContent = '';
(span.parentNode === null).should.equal(true);
};
exports.gh135 = function() {
var document = domino.createDocument('<a target="foobar"></a>');
var a = document.querySelectorAll('*[target$="aaaaaaa"]');
a.length.should.equal(0);
};
exports.gh136 = function() {
var document = domino.createDocument('<option> \f\tabc\n');
var o = document.querySelector('option');
o.value.should.equal('abc');
o.text.should.equal('abc');
o.textContent.should.equal(' \f\tabc\n');
o.value = ' def ';
o.value.should.equal(' def ');
o.text.should.equal('abc');
o.text = ' ghi ';
o.text.should.equal('ghi');
o.textContent.should.equal(' ghi ');
o.outerHTML.should.equal("<option value=\" def \"> ghi </option>");
};
// Examples from
// https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
exports.outerHTML1 = function() {
var document = domino.createDocument(
'<div id="d"><p>Content</p><p>Further Elaborated</p></div>'
);
var d = document.getElementById('d');
d.outerHTML.should.equal(
'<div id="d"><p>Content</p><p>Further Elaborated</p></div>'
);
};
exports.outerHTML2 = function() {
var document = domino.createDocument(
'<div id="container"><div id="d">This is a div.</div></div>'
);
var container = document.getElementById('container');
var d = document.getElementById('d');
container.firstChild.nodeName.should.equal('DIV');
d.outerHTML = "<p>This paragraph replaced the original div.</p>";
container.firstChild.nodeName.should.equal('P');
(d.parentNode === null).should.be.true();
};
exports.outerHTML3 = function() {
var document = domino.createDocument();
var div = document.createElement("div");
div.outerHTML = "<div class=\"test\">test</div>";
// "Many browsers will also throw an exception"
div.outerHTML.should.equal('<div></div>');
};
exports.outerHTML4 = function() {
var document = domino.createDocument("<p>hello there</p>");
var p = document.getElementsByTagName("p")[0];
p.nodeName.should.equal("P");
p.outerHTML = "<div>This div replaced a paragraph.</div>";
p.nodeName.should.equal("P");
(p.parentNode === null).should.be.true();
};
// Test case taken from
// https://developer.mozilla.org/en-US/docs/Web/API/Text/wholeText
exports.wholeText = function() {
var document = domino.createDocument(
'<p>Thru-hiking is great! <strong>No insipid election coverage!</strong>' +
' However, <a href="http://en.wikipedia.org/wiki/Absentee_ballot">casting' +
' a ballot</a> is tricky.</p>'
);
var para = document.querySelector('p');
para.removeChild(para.childNodes[1]);
para.firstChild.wholeText.should.equal("Thru-hiking is great! However, ");
};
exports.documentClone = function() {
var document = domino.createDocument('throw away');
var html = document.implementation.createHTMLDocument('my title');
html.body.innerHTML = '<p>Inside <b>body';
var copy = html.cloneNode(true); // deep copy!
(html === copy).should.be.false();
html.nodeType.should.equal(copy.nodeType);
html.nodeName.should.equal(copy.nodeName);
html.title.should.equal(copy.title);
html.body.outerHTML.should.equal(copy.body.outerHTML);
copy.head.ownerDocument.should.equal(copy);
copy.body.ownerDocument.should.equal(copy);
};
exports.insertForeignElement = function() {
// Sanitization test case from DOMPurify
// Verifies that prefixes are handled correctly during the
// "insert a foreign element" step in HTML parsing.
// https://html.spec.whatwg.org/multipage/parsing.html#insert-a-foreign-element
var document = domino.createDocument(
'<svg xmlns="http://www.w3.org/2000/svg">'+
'<xsl:stylesheet id="stylesheet" version="1.0" ' +
'xmlns:xsl="http://www.w3.org/1999/XSL/Transform">' +
'<xsl:template match="/">' +
'<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:alert(125)">'
);
var el = document.querySelector('*[match]');
el.namespaceURI.should.equal('http://www.w3.org/2000/svg');
el.localName.should.equal('xsl:template'); // Not 'template' !
el.outerHTML.should.equal(
'<xsl:template match="/">' +
'<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:alert(125)">'+
'</iframe></xsl:template>'
);
};
exports.bodyNL = function() {
var document = domino.createDocument(
'<body></body>\n'
);
// This may be surprising, but it's what the spec requires.
document.body.textContent.should.equal('\n');
};
exports.testIncompleteTag = function() {
var document = domino.createDocument('<p>hello<');
document.body.outerHTML.should.equal('<body><p>hello&lt;</p></body>');
};
exports.incrementalHTMLParser1 = function() {
// Verify correct operation of incremental parser, fed chunks which split
// up tokens.
var incrParser = domino.createIncrementalHTMLParser();
var neverPause = function() { return false; };
incrParser.write('<p>hello<');
incrParser.process(neverPause);
incrParser.write('b>foo&am');
incrParser.process(neverPause);
incrParser.write('p;<');
incrParser.process(neverPause);
incrParser.write('/p>');
incrParser.process(neverPause);
incrParser.end();
// omitting the pauseFunc is equivalent to passing neverPause
incrParser.process().should.equal(/*no more to do*/false);
incrParser.document().outerHTML.should.equal(
'<html><head></head><body><p>hello<b>foo&amp;</b></p></body></html>'
);
};
exports.incrementalHTMLParser2 = function() {
// Verify correct operation of incremental parser when we only manage to
// scan one token at each step.
var justOneStep = function() {
var counter = 1;
return function() { return (counter--) <= 0; };
};
var incrParser = domino.createIncrementalHTMLParser();
incrParser.write('<p>hello<');
incrParser.write('b>foo&am');
incrParser.write('p;<');
incrParser.write('/p>');
incrParser.end();
[
'<html><head></head><body><p></p></body></html>',
'<html><head></head><body><p>hello</p></body></html>',
'<html><head></head><body><p>hello<b></b></p></body></html>',
'<html><head></head><body><p>hello<b>foo</b></p></body></html>',
'<html><head></head><body><p>hello<b>foo</b></p></body></html>',
'<html><head></head><body><p>hello<b>foo</b></p></body></html>',
'<html><head></head><body><p>hello<b>foo</b></p></body></html>',
'<html><head></head><body><p>hello<b>foo</b></p></body></html>',
'<html><head></head><body><p>hello<b>foo&amp;</b></p></body></html>',
].forEach(function(step) {
incrParser.process(justOneStep()).should.equal(/*more to do!*/true);
incrParser.document().outerHTML.should.equal(step);
});
incrParser.process(justOneStep()).should.equal(/*no more to do*/false);
incrParser.document().outerHTML.should.equal(
'<html><head></head><body><p>hello<b>foo&amp;</b></p></body></html>'
);
};
exports.shouldNotEmptyStyle = function() {
var document = domino.createDocument('<div></div>');
var div = document.querySelector('div');
div.style.flex = ' ';
div.outerHTML.should.equal('<div></div>');
};
exports.supportModernStyle = function() {
var document = domino.createDocument('<h1 style="color:red !important">Hello world</h1>');
var h1 = document.querySelector('h1');
h1.style.inset = '0px';
h1.outerHTML.should.equal('<h1 style="color: red !important; inset: 0px;">Hello world</h1>');
};
exports.supportsNonceAttribute = function() {
var document = domino.createDocument('<style>* {color: red}</style>');
var h1 = document.querySelector('style');
h1.nonce = 'randomhaash';
h1.outerHTML.should.equal('<style nonce="randomhaash">* {color: red}</style>');
};
exports.supportsHtmlElementsInNoScriptTag = function() {
const document = domino.createDocument('<body><noscript>For information <em>click</em> here.</noscript></body>');
const noscript = document.querySelector('noscript');
noscript.outerHTML.should.equal('<noscript>For information <em>click</em> here.</noscript>');
};