diff --git a/packages/react-dom/src/client/__tests__/dangerouslySetInnerHTML-test.js b/packages/react-dom/src/client/__tests__/dangerouslySetInnerHTML-test.js new file mode 100644 index 0000000000000..519507c8ef191 --- /dev/null +++ b/packages/react-dom/src/client/__tests__/dangerouslySetInnerHTML-test.js @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails react-core + */ + +'use strict'; + +const React = require('react'); +const ReactDOM = require('react-dom'); + +describe('dangerouslySetInnerHTML', () => { + describe('when the node has innerHTML property', () => { + it('sets innerHTML on it', () => { + const container = document.createElement('div'); + const node = ReactDOM.render( +
Hello'}} />, + container, + ); + expect(node.innerHTML).toBe('

Hello

'); + }); + }); + + describe('when the node does not have an innerHTML property', () => { + let innerHTMLDescriptor; + + // In some versions of IE (TODO: which ones?) SVG nodes don't have + // innerHTML. To simulate this, we will take it off the Element prototype + // and put it onto the HTMLDivElement prototype. We expect that the logic + // checks for existence of innerHTML on SVG, and if one doesn't exist, falls + // back to using appendChild and removeChild. + + beforeEach(() => { + innerHTMLDescriptor = Object.getOwnPropertyDescriptor( + Element.prototype, + 'innerHTML', + ); + delete Element.prototype.innerHTML; + Object.defineProperty( + HTMLDivElement.prototype, + 'innerHTML', + innerHTMLDescriptor, + ); + }); + + afterEach(() => { + delete HTMLDivElement.prototype.innerHTML; + Object.defineProperty( + Element.prototype, + 'innerHTML', + innerHTMLDescriptor, + ); + }); + + it('sets innerHTML on it', () => { + const html = ''; + const container = document.createElementNS( + 'http://www.w3.org/2000/svg', + 'svg', + ); + ReactDOM.render( + , + container, + ); + const circle = container.firstChild.firstChild; + expect(circle.tagName).toBe('circle'); + }); + + it('clears previous children', () => { + const firstHtml = ''; + const secondHtml = ''; + + const container = document.createElementNS( + 'http://www.w3.org/2000/svg', + 'svg', + ); + ReactDOM.render( + , + container, + ); + const rect = container.firstChild.firstChild; + expect(rect.tagName).toBe('rect'); + ReactDOM.render( + , + container, + ); + const circle = container.firstChild.firstChild; + expect(circle.tagName).toBe('circle'); + }); + }); +}); diff --git a/packages/react-dom/src/client/__tests__/setInnerHTML-test.js b/packages/react-dom/src/client/__tests__/setInnerHTML-test.js deleted file mode 100644 index 13133a58f1108..0000000000000 --- a/packages/react-dom/src/client/__tests__/setInnerHTML-test.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @emails react-core - */ - -'use strict'; - -// TODO: can we express this test with only public API? -var setInnerHTML = require('../setInnerHTML').default; -var Namespaces = require('../../shared/DOMNamespaces').Namespaces; - -describe('setInnerHTML', () => { - describe('when the node has innerHTML property', () => { - it('sets innerHTML on it', () => { - var node = document.createElement('div'); - var html = '

hello

'; - setInnerHTML(node, html); - expect(node.innerHTML).toBe(html); - }); - }); - - describe('when the node does not have an innerHTML property', () => { - var node; - var nodeProxy; - beforeEach(() => { - // Create a mock node that looks like an SVG in IE (without innerHTML) - node = document.createElementNS(Namespaces.svg, 'svg'); - - nodeProxy = new Proxy(node, { - has: (target, prop) => { - return prop === 'innerHTML' ? false : prop in target; - }, - }); - - spyOn(node, 'appendChild').and.callThrough(); - spyOn(node, 'removeChild').and.callThrough(); - }); - - it('sets innerHTML on it', () => { - var html = ''; - setInnerHTML(nodeProxy, html); - - expect(node.appendChild.calls.argsFor(0)[0].outerHTML).toBe( - '', - ); - expect(node.appendChild.calls.argsFor(1)[0].outerHTML).toBe( - '', - ); - }); - - it('clears previous children', () => { - var firstHtml = ''; - var secondHtml = ''; - setInnerHTML(nodeProxy, firstHtml); - - setInnerHTML(nodeProxy, secondHtml); - - expect(node.removeChild.calls.argsFor(0)[0].outerHTML).toBe( - '', - ); - expect(node.innerHTML).toBe(''); - }); - }); -});