diff --git a/lib/index.js b/lib/index.js index 04bf728a..8a01de6a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -308,6 +308,17 @@ module.exports = { } }); + // Recognize as a special subtype of DOMComment so it can be targeted by assertions: + expect.exportType({ + name: 'DOMIgnoreComment', + base: 'DOMComment', + identify: function(obj) { + return ( + this.baseType.identify(obj) && /^\s*ignore\s*$/.test(obj.nodeValue) + ); + } + }); + expect.exportType({ name: 'DOMTextNode', base: 'DOMNode', @@ -719,6 +730,13 @@ module.exports = { } ); + expect.exportAssertion( + ' to [exhaustively] satisfy ', + function(expect, subject, value) { + return expect(subject.nodeValue, 'to equal', value.nodeValue); + } + ); + // Avoid rendering a huge object diff when a text node is matched against a different node type: expect.exportAssertion( ' to [exhaustively] satisfy ', @@ -727,6 +745,13 @@ module.exports = { } ); + // Always passes: + expect.exportAssertion( + // Name each subject type to increase the specificity of the assertion + ' to [exhaustively] satisfy ', + function(expect, subject, value) {} + ); + // Necessary because this case would otherwise be handled by the above catch-all for : expect.exportAssertion( ' to [exhaustively] satisfy ', @@ -743,10 +768,7 @@ module.exports = { ); function convertDOMNodeToSatisfySpec(node, isHtml) { - if (node.nodeType === 8 && node.nodeValue.trim() === 'ignore') { - // Ignore subtree - return expect.it('to be an', 'DOMNode'); - } else if (node.nodeType === 10) { + if (node.nodeType === 10) { // HTMLDocType return { name: node.nodeName }; } else if (node.nodeType === 1) { @@ -778,6 +800,9 @@ module.exports = { } else if (node.nodeType === 3) { // DOMTextNode return node.nodeValue; + } else if (node.nodeType === 8) { + // DOMComment + return node; } else { throw new Error( 'to satisfy: Node type ' + diff --git a/test/index.spec.js b/test/index.spec.js index 6e50d14a..d5384956 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -63,6 +63,10 @@ function parseHtml(str) { .window.document.body.firstChild; } +function parseHtmlDocument(str) { + return new jsdom.JSDOM(str).window.document; +} + function parseHtmlFragment(str) { str = '' + str + ''; var htmlDocument = new jsdom.JSDOM(str).window.document; @@ -76,6 +80,10 @@ function parseHtmlFragment(str) { return documentFragment; } +function parseHtmlNode(str) { + return parseHtmlFragment(str).childNodes[0]; +} + function parseXml(str) { if (typeof DOMParser !== 'undefined') { // eslint-disable-next-line no-undef @@ -1468,7 +1476,7 @@ describe('unexpected-dom', function() { ); }); - describe('and it contain an ignore comment', function() { + describe('and it contains an ignore comment', function() { it('ignores the corresponding subtree', () => { expect( [ @@ -2032,6 +2040,15 @@ describe('unexpected-dom', function() { expect(body.firstChild, 'to satisfy', { children: ['hey'] }); }); + it('should succeed with a node child', function() { + var node = document.createElement('div'); + node.innerHTML = '
hey
'; + body.innerHTML = '
hey
'; + expect(body.firstChild, 'to satisfy', { + children: [node.firstChild] + }); + }); + it('should fail with a diff', function() { body.innerHTML = '
hey
'; expect( @@ -2049,6 +2066,56 @@ describe('unexpected-dom', function() { '' ); }); + + describe('when using ignore', function() { + it('should succeed', function() { + var node = document.createElement('div'); + node.innerHTML = ''; + var commentNode = node.firstChild; + body.innerHTML = + '
ignoreimportant
'; + expect(body.firstChild, 'to satisfy', { + children: [ + commentNode, + { + children: 'important' + } + ] + }); + }); + }); + }); + + describe('when matching against ', function() { + var ignoreComment = parseHtmlNode(''); + + it('should match a text node', function() { + expect(parseHtmlNode('foo'), 'to satisfy', ignoreComment); + }); + + it('should match an element', function() { + expect(parseHtmlNode('
foo
'), 'to satisfy', ignoreComment); + }); + + it('should match a comment', function() { + expect(parseHtmlNode(''), 'to satisfy', ignoreComment); + }); + + it('should match a doctype', function() { + expect( + parseHtmlDocument('').firstChild, + 'to satisfy', + ignoreComment + ); + }); + + it('should match a document', function() { + expect( + 'abc', + 'when parsed as xml to satisfy', + ignoreComment + ); + }); }); it('should fail with a diff', function() { @@ -2625,6 +2692,31 @@ describe('unexpected-dom', function() { }); }); + describe('to satisfy', function() { + describe('when comparing an array of children', function() { + it('should succeed with a text child', function() { + expect( + [ + '', + '', + ' World', + '' + ].join('\n'), + 'when parsed as XML', + 'queried for first', + 'hello', + 'to satisfy', + { + attributes: { + type: 'greeting' + }, + children: ['World'] + } + ); + }); + }); + }); + describe('when the DOMParser global is available', function() { var originalDOMParser, DOMParserSpy, parseFromStringSpy;