From 2293b4c12a3d5facbc3c3becaed25a5b22a4db9f Mon Sep 17 00:00:00 2001 From: Adam Stankiewicz Date: Tue, 6 Nov 2018 14:52:35 +0100 Subject: [PATCH] fix: flawed logic in checking if elements are indeed html elements (#67) * Fix checkHtmlElement helper * Remove checkHtmlText --- src/__tests__/utils.js | 46 +++++++++++++++++++++++++++++++++++++++++- src/to-contain-html.js | 10 --------- src/utils.js | 28 +++++++++++++++++++++---- 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/__tests__/utils.js b/src/__tests__/utils.js index 06914aed..e25fa7c8 100644 --- a/src/__tests__/utils.js +++ b/src/__tests__/utils.js @@ -1,4 +1,5 @@ -import {deprecate} from '../utils' +import {deprecate, checkHtmlElement, HtmlElementTypeError} from '../utils' +import document from './helpers/document' test('deprecate', () => { const spy = jest.spyOn(console, 'warn').mockImplementation(() => {}) @@ -14,3 +15,46 @@ test('deprecate', () => { spy.mockRestore() }) + +describe('checkHtmlElement', () => { + it('does not throw an error for correct html element', () => { + expect(() => { + const element = document.createElement('p') + checkHtmlElement(element, () => {}, {}) + }).not.toThrow() + }) + + it('does not throw an error for correct svg element', () => { + expect(() => { + const element = document.createElementNS( + 'http://www.w3.org/2000/svg', + 'rect', + ) + checkHtmlElement(element, () => {}, {}) + }).not.toThrow() + }) + + it('does not throw for body', () => { + expect(() => { + checkHtmlElement(document.body, () => {}, {}) + }).not.toThrow() + }) + + it('throws for undefined', () => { + expect(() => { + checkHtmlElement(undefined, () => {}, {}) + }).toThrow(HtmlElementTypeError) + }) + + it('throws for document', () => { + expect(() => { + checkHtmlElement(document, () => {}, {}) + }).toThrow(HtmlElementTypeError) + }) + + it('throws for function', () => { + expect(() => { + checkHtmlElement(() => {}, () => {}, {}) + }).toThrow(HtmlElementTypeError) + }) +}) diff --git a/src/to-contain-html.js b/src/to-contain-html.js index 667c72f2..46c1a60b 100644 --- a/src/to-contain-html.js +++ b/src/to-contain-html.js @@ -1,18 +1,8 @@ import {matcherHint, printReceived} from 'jest-matcher-utils' import {checkHtmlElement} from './utils' -function checkHtmlText(element, htmlText, ...args) { - const DOMParser = element.ownerDocument.defaultView.DOMParser - const htmlElement = - typeof htmlText === 'string' - ? new DOMParser().parseFromString(htmlText, 'text/html').body.firstChild - : null - checkHtmlElement(htmlElement, ...args) -} - export function toContainHTML(container, htmlText) { checkHtmlElement(container, toContainHTML, this) - checkHtmlText(container, htmlText, toContainHTML, this) return { pass: container.outerHTML.includes(htmlText), diff --git a/src/utils.js b/src/utils.js index 3017c7f1..e54f7149 100644 --- a/src/utils.js +++ b/src/utils.js @@ -17,6 +17,13 @@ class HtmlElementTypeError extends Error { if (Error.captureStackTrace) { Error.captureStackTrace(this, matcherFn) } + let withType = '' + try { + withType = printWithType('Received', received, printReceived) + } catch (e) { + // Can throw for Document: + // https://github.com/jsdom/jsdom/issues/2304 + } this.message = [ matcherHint( `${context.isNot ? '.not' : ''}.${matcherFn.name}`, @@ -27,16 +34,28 @@ class HtmlElementTypeError extends Error { `${receivedColor( 'received', )} value must be an HTMLElement or an SVGElement.`, - printWithType('Received', received, printReceived), + withType, ].join('\n') } } +function checkHasWindow(htmlElement, ...args) { + if ( + !htmlElement || + !htmlElement.ownerDocument || + !htmlElement.ownerDocument.defaultView + ) { + throw new HtmlElementTypeError(htmlElement, ...args) + } +} + function checkHtmlElement(htmlElement, ...args) { + checkHasWindow(htmlElement, ...args) + const window = htmlElement.ownerDocument.defaultView + if ( - !htmlElement.ownerDocument && - !(htmlElement instanceof htmlElement.ownerDocument.HTMLElement) && - !(htmlElement instanceof htmlElement.ownerDocument.SVGElement) + !(htmlElement instanceof window.HTMLElement) && + !(htmlElement instanceof window.SVGElement) ) { throw new HtmlElementTypeError(htmlElement, ...args) } @@ -115,6 +134,7 @@ function normalize(text) { } export { + HtmlElementTypeError, checkHtmlElement, checkValidCSS, deprecate,