From fa10f5f6f0e9722de6e7ee8a943620c872a0f790 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 12 Sep 2018 17:43:01 +0100 Subject: [PATCH] Unify Fire test cases with normal ones --- .../__tests__/DOMPropertyOperations-test.js | 21 +- .../src/__tests__/ReactDOMInput-test.js | 246 +++- .../ReactDOMServerIntegrationCheckbox-test.js | 6 +- .../ReactDOMServerIntegrationInput-test.js | 6 +- .../src/__tests__/ReactFire-test.internal.js | 1195 ----------------- .../ChangeEventPlugin-test.internal.js | 11 +- scripts/jest/setupFire.js | 2 +- 7 files changed, 228 insertions(+), 1259 deletions(-) delete mode 100644 packages/react-dom/src/__tests__/ReactFire-test.internal.js diff --git a/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js b/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js index 3f6e0ff8a8e5b..16821b1b3f314 100644 --- a/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js +++ b/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js @@ -9,6 +9,9 @@ 'use strict'; +// Set by `yarn test-fire`. +const {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags'); + describe('DOMPropertyOperations', () => { let React; let ReactDOM; @@ -80,7 +83,11 @@ describe('DOMPropertyOperations', () => { it('should not remove empty attributes for special input properties', () => { const container = document.createElement('div'); ReactDOM.render( {}} />, container); - expect(container.firstChild.getAttribute('value')).toBe(''); + if (disableInputAttributeSyncing) { + expect(container.firstChild.hasAttribute('value')).toBe(false); + } else { + expect(container.firstChild.getAttribute('value')).toBe(''); + } expect(container.firstChild.value).toBe(''); }); @@ -165,7 +172,11 @@ describe('DOMPropertyOperations', () => { , container, ); - expect(container.firstChild.getAttribute('value')).toBe('foo'); + if (disableInputAttributeSyncing) { + expect(container.firstChild.hasAttribute('value')).toBe(false); + } else { + expect(container.firstChild.getAttribute('value')).toBe('foo'); + } expect(container.firstChild.value).toBe('foo'); expect(() => ReactDOM.render( @@ -175,7 +186,11 @@ describe('DOMPropertyOperations', () => { ).toWarnDev( 'A component is changing a controlled input of type text to be uncontrolled', ); - expect(container.firstChild.getAttribute('value')).toBe('foo'); + if (disableInputAttributeSyncing) { + expect(container.firstChild.hasAttribute('value')).toBe(false); + } else { + expect(container.firstChild.getAttribute('value')).toBe('foo'); + } expect(container.firstChild.value).toBe('foo'); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMInput-test.js b/packages/react-dom/src/__tests__/ReactDOMInput-test.js index 05764401cd95a..e9f917bd067c7 100644 --- a/packages/react-dom/src/__tests__/ReactDOMInput-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMInput-test.js @@ -9,6 +9,9 @@ 'use strict'; +// Set by `yarn test-fire`. +const {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags'); + function emptyFunction() {} describe('ReactDOMInput', () => { @@ -230,11 +233,14 @@ describe('ReactDOMInput', () => { const node = ReactDOM.render(stub, container); setUntrackedValue.call(node, '2.0'); - dispatchEventOnNode(node, 'input'); - expect(node.getAttribute('value')).toBe('2'); expect(node.value).toBe('2'); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.getAttribute('value')).toBe('2'); + } }); it('does change the string "2" to "2.0" with no change handler', () => { @@ -242,11 +248,14 @@ describe('ReactDOMInput', () => { const node = ReactDOM.render(stub, container); setUntrackedValue.call(node, '2.0'); - dispatchEventOnNode(node, 'input'); - expect(node.getAttribute('value')).toBe('2'); expect(node.value).toBe('2'); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.getAttribute('value')).toBe('2'); + } }); it('changes the number 2 to "2.0" using a change handler', () => { @@ -268,11 +277,14 @@ describe('ReactDOMInput', () => { const node = ReactDOM.findDOMNode(stub); setUntrackedValue.call(node, '2.0'); - dispatchEventOnNode(node, 'input'); - expect(node.getAttribute('value')).toBe('2.0'); expect(node.value).toBe('2.0'); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.getAttribute('value')).toBe('2.0'); + } }); }); @@ -419,11 +431,17 @@ describe('ReactDOMInput', () => { ); expect(node.value).toBe('0'); + expect(node.defaultValue).toBe('0'); ReactDOM.render(, container); - expect(node.value).toBe('0'); - expect(node.defaultValue).toBe('1'); + if (disableInputAttributeSyncing) { + expect(node.value).toBe('1'); + expect(node.defaultValue).toBe('1'); + } else { + expect(node.value).toBe('0'); + expect(node.defaultValue).toBe('1'); + } }); it('should update `defaultValue` for uncontrolled date/time input', () => { @@ -433,11 +451,17 @@ describe('ReactDOMInput', () => { ); expect(node.value).toBe('1980-01-01'); + expect(node.defaultValue).toBe('1980-01-01'); ReactDOM.render(, container); - expect(node.value).toBe('1980-01-01'); - expect(node.defaultValue).toBe('2000-01-01'); + if (disableInputAttributeSyncing) { + expect(node.value).toBe('2000-01-01'); + expect(node.defaultValue).toBe('2000-01-01'); + } else { + expect(node.value).toBe('1980-01-01'); + expect(node.defaultValue).toBe('2000-01-01'); + } ReactDOM.render(, container); }); @@ -650,12 +674,17 @@ describe('ReactDOMInput', () => { const node = ReactDOM.render(stub, container); setUntrackedValue.call(node, '0.0'); - dispatchEventOnNode(node, 'input'); - dispatchEventOnNode(node, 'blur'); - expect(node.value).toBe('0.0'); - expect(node.getAttribute('value')).toBe('0.0'); + if (disableInputAttributeSyncing) { + expect(node.value).toBe('0.0'); + expect(node.hasAttribute('value')).toBe(false); + } else { + dispatchEventOnNode(node, 'blur'); + + expect(node.value).toBe('0.0'); + expect(node.getAttribute('value')).toBe('0.0'); + } }); it('should properly transition from an empty value to 0', function() { @@ -669,9 +698,13 @@ describe('ReactDOMInput', () => { ); const node = container.firstChild; - expect(node.value).toBe('0'); - expect(node.defaultValue).toBe('0'); + + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.defaultValue).toBe('0'); + } }); it('should properly transition from 0 to an empty value', function() { @@ -703,7 +736,11 @@ describe('ReactDOMInput', () => { const node = container.firstChild; expect(node.value).toBe('0.0'); - expect(node.defaultValue).toBe('0.0'); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.defaultValue).toBe('0.0'); + } }); it('should properly transition a number input from "" to 0', function() { @@ -719,7 +756,11 @@ describe('ReactDOMInput', () => { const node = container.firstChild; expect(node.value).toBe('0'); - expect(node.defaultValue).toBe('0'); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.defaultValue).toBe('0'); + } }); it('should properly transition a number input from "" to "0"', function() { @@ -735,7 +776,11 @@ describe('ReactDOMInput', () => { const node = container.firstChild; expect(node.value).toBe('0'); - expect(node.defaultValue).toBe('0'); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.defaultValue).toBe('0'); + } }); it('should have the correct target value', () => { @@ -960,21 +1005,34 @@ describe('ReactDOMInput', () => { const cNode = stub.refs.c; expect(aNode.checked).toBe(true); - expect(aNode.hasAttribute('checked')).toBe(true); expect(bNode.checked).toBe(false); - expect(bNode.hasAttribute('checked')).toBe(false); // c is in a separate form and shouldn't be affected at all here expect(cNode.checked).toBe(true); - expect(cNode.hasAttribute('checked')).toBe(true); + + if (disableInputAttributeSyncing) { + expect(aNode.hasAttribute('checked')).toBe(false); + expect(bNode.hasAttribute('checked')).toBe(false); + expect(cNode.hasAttribute('checked')).toBe(true); + } else { + expect(aNode.hasAttribute('checked')).toBe(true); + expect(bNode.hasAttribute('checked')).toBe(false); + expect(cNode.hasAttribute('checked')).toBe(true); + } setUntrackedChecked.call(bNode, true); expect(aNode.checked).toBe(false); expect(cNode.checked).toBe(true); // The original 'checked' attribute should be unchanged - expect(aNode.hasAttribute('checked')).toBe(true); - expect(bNode.hasAttribute('checked')).toBe(false); - expect(cNode.hasAttribute('checked')).toBe(true); + if (disableInputAttributeSyncing) { + expect(aNode.hasAttribute('checked')).toBe(false); + expect(bNode.hasAttribute('checked')).toBe(false); + expect(cNode.hasAttribute('checked')).toBe(true); + } else { + expect(aNode.hasAttribute('checked')).toBe(true); + expect(bNode.hasAttribute('checked')).toBe(false); + expect(cNode.hasAttribute('checked')).toBe(true); + } // Now let's run the actual ReactDOMInput change event handler dispatchEventOnNode(bNode, 'click'); @@ -1520,15 +1578,26 @@ describe('ReactDOMInput', () => { />, container, ); - expect(log).toEqual([ - 'set attribute type', - 'set attribute min', - 'set attribute max', - 'set attribute step', - 'set property value', - 'set attribute value', - 'set attribute checked', - ]); + + if (disableInputAttributeSyncing) { + expect(log).toEqual([ + 'set attribute type', + 'set attribute min', + 'set attribute max', + 'set attribute step', + 'set property value', + ]); + } else { + expect(log).toEqual([ + 'set attribute type', + 'set attribute min', + 'set attribute max', + 'set attribute step', + 'set property value', + 'set attribute value', + 'set attribute checked', + ]); + } }); it('sets value properly with type coming later in props', () => { @@ -1583,12 +1652,20 @@ describe('ReactDOMInput', () => { }); ReactDOM.render(, container); - expect(log).toEqual([ - 'node.setAttribute("type", "date")', - 'node.value = "1980-01-01"', - 'node.setAttribute("value", "1980-01-01")', - 'node.setAttribute("checked", "")', - ]); + + if (disableInputAttributeSyncing) { + expect(log).toEqual([ + 'node.setAttribute("type", "date")', + 'node.setAttribute("value", "1980-01-01")', + ]); + } else { + expect(log).toEqual([ + 'node.setAttribute("type", "date")', + 'node.value = "1980-01-01"', + 'node.setAttribute("value", "1980-01-01")', + 'node.setAttribute("checked", "")', + ]); + } }); describe('assigning the value attribute on controlled inputs', function() { @@ -1617,7 +1694,11 @@ describe('ReactDOMInput', () => { setUntrackedValue.call(node, '2'); dispatchEventOnNode(node, 'input'); - expect(node.getAttribute('value')).toBe('2'); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.getAttribute('value')).toBe('2'); + } }); it('does not set the value attribute on number inputs if focused', () => { @@ -1633,7 +1714,11 @@ describe('ReactDOMInput', () => { setUntrackedValue.call(node, '2'); dispatchEventOnNode(node, 'input'); - expect(node.getAttribute('value')).toBe('1'); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.getAttribute('value')).toBe('1'); + } }); it('sets the value attribute on number inputs on blur', () => { @@ -1645,10 +1730,8 @@ describe('ReactDOMInput', () => { const node = ReactDOM.findDOMNode(stub); node.focus(); - setUntrackedValue.call(node, '2'); dispatchEventOnNode(node, 'input'); - // TODO: it is unclear why blur must be triggered twice, // manual testing in the fixtures shows that the active element // is no longer the input, however blur() + a blur event seem to @@ -1656,7 +1739,13 @@ describe('ReactDOMInput', () => { node.blur(); dispatchEventOnNode(node, 'blur'); - expect(node.getAttribute('value')).toBe('2'); + if (disableInputAttributeSyncing) { + expect(node.value).toBe('2'); + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.value).toBe('2'); + expect(node.getAttribute('value')).toBe('2'); + } }); it('an uncontrolled number input will not update the value attribute on blur', () => { @@ -1665,8 +1754,14 @@ describe('ReactDOMInput', () => { container, ); + node.focus(); setUntrackedValue.call(node, 4); - + dispatchEventOnNode(node, 'input'); + // TODO: it is unclear why blur must be triggered twice, + // manual testing in the fixtures shows that the active element + // is no longer the input, however blur() + a blur event seem to + // be the only way to remove focus in JSDOM + node.blur(); dispatchEventOnNode(node, 'blur'); expect(node.getAttribute('value')).toBe('1'); @@ -1678,8 +1773,14 @@ describe('ReactDOMInput', () => { container, ); + node.focus(); setUntrackedValue.call(node, 4); - + dispatchEventOnNode(node, 'input'); + // TODO: it is unclear why blur must be triggered twice, + // manual testing in the fixtures shows that the active element + // is no longer the input, however blur() + a blur event seem to + // be the only way to remove focus in JSDOM + node.blur(); dispatchEventOnNode(node, 'blur'); expect(node.getAttribute('value')).toBe('1'); @@ -1719,7 +1820,11 @@ describe('ReactDOMInput', () => { 'Input elements should not switch from controlled to ' + 'uncontrolled (or vice versa).', ); - expect(input.getAttribute('value')).toBe('first'); + if (disableInputAttributeSyncing) { + expect(input.getAttribute('value')).toBe(null); + } else { + expect(input.getAttribute('value')).toBe('first'); + } }); it('preserves the value property', () => { @@ -1767,7 +1872,11 @@ describe('ReactDOMInput', () => { 'Input elements should not switch from controlled ' + 'to uncontrolled (or vice versa).', ]); - expect(input.getAttribute('value')).toBe('first'); + if (disableInputAttributeSyncing) { + expect(input.hasAttribute('value')).toBe(false); + } else { + expect(input.getAttribute('value')).toBe('first'); + } }); it('preserves the value property', () => { @@ -1793,7 +1902,11 @@ describe('ReactDOMInput', () => { const node = container.firstChild; expect(node.value).toBe(''); - expect(node.getAttribute('value')).toBe(''); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.getAttribute('value')).toBe(''); + } }); it('treats updated Symbol value as an empty string', function() { @@ -1807,7 +1920,11 @@ describe('ReactDOMInput', () => { const node = container.firstChild; expect(node.value).toBe(''); - expect(node.getAttribute('value')).toBe(''); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.getAttribute('value')).toBe(''); + } }); it('treats initial Symbol defaultValue as an empty string', function() { @@ -1824,7 +1941,11 @@ describe('ReactDOMInput', () => { ReactDOM.render(, container); const node = container.firstChild; - expect(node.value).toBe('foo'); + if (disableInputAttributeSyncing) { + expect(node.value).toBe(''); + } else { + expect(node.value).toBe('foo'); + } expect(node.getAttribute('value')).toBe(''); // TODO: we should warn here. }); @@ -1841,7 +1962,11 @@ describe('ReactDOMInput', () => { const node = container.firstChild; expect(node.value).toBe(''); - expect(node.getAttribute('value')).toBe(''); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.getAttribute('value')).toBe(''); + } }); it('treats updated function value as an empty string', function() { @@ -1855,7 +1980,11 @@ describe('ReactDOMInput', () => { const node = container.firstChild; expect(node.value).toBe(''); - expect(node.getAttribute('value')).toBe(''); + if (disableInputAttributeSyncing) { + expect(node.hasAttribute('value')).toBe(false); + } else { + expect(node.getAttribute('value')).toBe(''); + } }); it('treats initial function defaultValue as an empty string', function() { @@ -1872,8 +2001,13 @@ describe('ReactDOMInput', () => { ReactDOM.render( {}} />, container); const node = container.firstChild; - expect(node.value).toBe('foo'); - expect(node.getAttribute('value')).toBe(''); + if (disableInputAttributeSyncing) { + expect(node.value).toBe(''); + expect(node.getAttribute('value')).toBe(''); + } else { + expect(node.value).toBe('foo'); + expect(node.getAttribute('value')).toBe(''); + } // TODO: we should warn here. }); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationCheckbox-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationCheckbox-test.js index 61c08c1295814..03e7c4b984480 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationCheckbox-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationCheckbox-test.js @@ -10,6 +10,8 @@ 'use strict'; const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); +// Set by `yarn test-fire`. +const {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags'); let React; let ReactDOM; @@ -31,7 +33,9 @@ function initModules() { const {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules); -describe('ReactDOMServerIntegrationCheckbox', () => { +// TODO: Run this in React Fire mode after we figure out the SSR behavior. +const desc = disableInputAttributeSyncing ? xdescribe : describe; +desc('ReactDOMServerIntegrationCheckbox', () => { beforeEach(() => { resetModules(); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationInput-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationInput-test.js index f979535993fc3..d637755d02c0b 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationInput-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationInput-test.js @@ -10,6 +10,8 @@ 'use strict'; const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); +// Set by `yarn test-fire`. +const {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags'); let React; let ReactDOM; @@ -31,7 +33,9 @@ function initModules() { const {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules); -describe('ReactDOMServerIntegrationInput', () => { +// TODO: Run this in React Fire mode after we figure out the SSR behavior. +const desc = disableInputAttributeSyncing ? xdescribe : describe; +desc('ReactDOMServerIntegrationInput', () => { beforeEach(() => { resetModules(); }); diff --git a/packages/react-dom/src/__tests__/ReactFire-test.internal.js b/packages/react-dom/src/__tests__/ReactFire-test.internal.js deleted file mode 100644 index 65c7b5b05d431..0000000000000 --- a/packages/react-dom/src/__tests__/ReactFire-test.internal.js +++ /dev/null @@ -1,1195 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * 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'; - -function emptyFunction() {} - -describe('ReactFire', () => { - let React; - let ReactDOM; - let ReactDOMServer; - let ReactFeatureFlags; - let container; - - function dispatchEventOnNode(node, type) { - node.dispatchEvent(new Event(type, {bubbles: true, cancelable: true})); - } - - beforeEach(() => { - jest.resetModules(); - - ReactFeatureFlags = require('shared/ReactFeatureFlags'); - ReactFeatureFlags.disableInputAttributeSyncing = true; - - React = require('react'); - ReactDOM = require('react-dom'); - ReactDOMServer = require('react-dom/server'); - - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - }); - - describe('DOMPropertyOperations', () => { - it('should not remove empty attributes for special input properties', () => { - ReactDOM.render( {}} />, container); - expect(container.firstChild.hasAttribute('value')).toBe(false); - expect(container.firstChild.value).toBe(''); - }); - - it('should not remove attributes for special properties', () => { - ReactDOM.render( - , - container, - ); - expect(container.firstChild.hasAttribute('value')).toBe(false); - expect(container.firstChild.value).toBe('foo'); - expect(() => - ReactDOM.render( - , - container, - ), - ).toWarnDev( - 'A component is changing a controlled input of type text to be uncontrolled', - ); - expect(container.firstChild.hasAttribute('value')).toBe(false); - expect(container.firstChild.value).toBe('foo'); - }); - }); - - describe('ReactDOMInput', () => { - let setUntrackedValue; - let setUntrackedChecked; - beforeEach(() => { - setUntrackedValue = Object.getOwnPropertyDescriptor( - HTMLInputElement.prototype, - 'value', - ).set; - setUntrackedChecked = Object.getOwnPropertyDescriptor( - HTMLInputElement.prototype, - 'checked', - ).set; - }); - - it('should control a value in reentrant events', () => { - class ControlledInputs extends React.Component { - state = {value: 'lion'}; - a = null; - b = null; - switchedFocus = false; - change(newValue) { - this.setState({value: newValue}); - // Calling focus here will blur the text box which causes a native - // change event. Ideally we shouldn't have to fire this ourselves. - // Don't remove unless you've verified the fix in #8240 is still covered. - dispatchEventOnNode(this.a, 'input'); - this.b.focus(); - } - blur(currentValue) { - this.switchedFocus = true; - // currentValue should be 'giraffe' here because we should not have - // restored it on the target yet. - this.setState({value: currentValue}); - } - render() { - return ( -
- (this.a = n)} - value={this.state.value} - onChange={e => this.change(e.target.value)} - onBlur={e => this.blur(e.target.value)} - /> - (this.b = n)} /> -
- ); - } - } - - const instance = ReactDOM.render(, container); - - // Focus the field so we can later blur it. - // Don't remove unless you've verified the fix in #8240 is still covered. - instance.a.focus(); - setUntrackedValue.call(instance.a, 'giraffe'); - // This must use the native event dispatching. If we simulate, we will - // bypass the lazy event attachment system so we won't actually test this. - dispatchEventOnNode(instance.a, 'input'); - dispatchEventOnNode(instance.a, 'blur'); - - expect(instance.a.value).toBe('giraffe'); - expect(instance.switchedFocus).toBe(true); - }); - - it('should control values in reentrant events with different targets', () => { - class ControlledInputs extends React.Component { - state = {value: 'lion'}; - a = null; - b = null; - change(newValue) { - // This click will change the checkbox's value to false. Then it will - // invoke an inner change event. When we finally, flush, we need to - // reset the checkbox's value to true since that is its controlled - // value. - this.b.click(); - } - render() { - return ( -
- (this.a = n)} - value="lion" - onChange={e => this.change(e.target.value)} - /> - (this.b = n)} - checked={true} - onChange={() => {}} - /> -
- ); - } - } - - const instance = ReactDOM.render(, container); - - setUntrackedValue.call(instance.a, 'giraffe'); - // This must use the native event dispatching. If we simulate, we will - // bypass the lazy event attachment system so we won't actually test this. - dispatchEventOnNode(instance.a, 'input'); - - expect(instance.a.value).toBe('lion'); - expect(instance.b.checked).toBe(true); - }); - - describe('switching text inputs between numeric and string numbers', () => { - it('does change the number 2 to "2.0" with no change handler', () => { - const stub = ; - const node = ReactDOM.render(stub, container); - - setUntrackedValue.call(node, '2.0'); - - dispatchEventOnNode(node, 'input'); - - expect(node.hasAttribute('value')).toBe(false); - expect(node.value).toBe('2'); - }); - - it('does change the string "2" to "2.0" with no change handler', () => { - const stub = ; - const node = ReactDOM.render(stub, container); - - setUntrackedValue.call(node, '2.0'); - - dispatchEventOnNode(node, 'input'); - - expect(node.hasAttribute('value')).toBe(false); - expect(node.value).toBe('2'); - }); - - it('changes the number 2 to "2.0" using a change handler', () => { - class Stub extends React.Component { - state = { - value: 2, - }; - onChange = event => { - this.setState({value: event.target.value}); - }; - render() { - const {value} = this.state; - - return ; - } - } - - const stub = ReactDOM.render(, container); - const node = ReactDOM.findDOMNode(stub); - - setUntrackedValue.call(node, '2.0'); - - dispatchEventOnNode(node, 'input'); - - expect(node.hasAttribute('value')).toBe(false); - expect(node.value).toBe('2.0'); - }); - }); - - it('does change the string ".98" to "0.98" with no change handler', () => { - class Stub extends React.Component { - state = { - value: '.98', - }; - render() { - return ; - } - } - - let stub; - expect(() => { - stub = ReactDOM.render(, container); - }).toWarnDev( - 'You provided a `value` prop to a form field ' + - 'without an `onChange` handler.', - ); - const node = ReactDOM.findDOMNode(stub); - stub.setState({value: '0.98'}); - - expect(node.value).toEqual('0.98'); - }); - - it('performs a state change from "" to 0', () => { - class Stub extends React.Component { - state = { - value: '', - }; - render() { - return ( - - ); - } - } - - const stub = ReactDOM.render(, container); - const node = ReactDOM.findDOMNode(stub); - stub.setState({value: 0}); - - expect(node.value).toEqual('0'); - }); - - it('updates the value on radio buttons from "" to 0', function() { - ReactDOM.render( - , - container, - ); - ReactDOM.render( - , - container, - ); - expect(container.firstChild.value).toBe('0'); - expect(container.firstChild.getAttribute('value')).toBe('0'); - }); - - it('updates the value on checkboxes from "" to 0', function() { - ReactDOM.render( - , - container, - ); - ReactDOM.render( - , - container, - ); - expect(container.firstChild.value).toBe('0'); - expect(container.firstChild.getAttribute('value')).toBe('0'); - }); - - it('distinguishes precision for extra zeroes in string number values', () => { - class Stub extends React.Component { - state = { - value: '3.0000', - }; - render() { - return ; - } - } - - let stub; - - expect(() => { - stub = ReactDOM.render(, container); - }).toWarnDev( - 'You provided a `value` prop to a form field ' + - 'without an `onChange` handler.', - ); - const node = ReactDOM.findDOMNode(stub); - stub.setState({value: '3'}); - - expect(node.value).toEqual('3'); - }); - - it('should display `defaultValue` of number 0', () => { - let stub = ; - const node = ReactDOM.render(stub, container); - - expect(node.getAttribute('value')).toBe('0'); - expect(node.value).toBe('0'); - }); - - it('only assigns defaultValue if it changes', () => { - class Test extends React.Component { - render() { - return ; - } - } - - const component = ReactDOM.render(, container); - const node = ReactDOM.findDOMNode(component); - - Object.defineProperty(node, 'defaultValue', { - get() { - return '0'; - }, - set(value) { - throw new Error( - `defaultValue was assigned ${value}, but it did not change!`, - ); - }, - }); - - component.forceUpdate(); - }); - - it('should display "true" for `defaultValue` of `true`', () => { - let stub = ; - const node = ReactDOM.render(stub, container); - - expect(node.value).toBe('true'); - }); - - it('should display "false" for `defaultValue` of `false`', () => { - let stub = ; - const node = ReactDOM.render(stub, container); - - expect(node.value).toBe('false'); - }); - - it('should update `defaultValue` for uncontrolled input', () => { - const node = ReactDOM.render( - , - container, - ); - - expect(node.value).toBe('0'); - expect(node.defaultValue).toBe('0'); - - ReactDOM.render(, container); - - expect(node.value).toBe('1'); - expect(node.defaultValue).toBe('1'); - }); - - it('should update `defaultValue` for uncontrolled date/time input', () => { - const node = ReactDOM.render( - , - container, - ); - - expect(node.value).toBe('1980-01-01'); - expect(node.defaultValue).toBe('1980-01-01'); - - ReactDOM.render( - , - container, - ); - - expect(node.value).toBe('2000-01-01'); - expect(node.defaultValue).toBe('2000-01-01'); - - ReactDOM.render(, container); - }); - - it('should take `defaultValue` when changing to uncontrolled input', () => { - const node = ReactDOM.render( - , - container, - ); - expect(node.value).toBe('0'); - expect(() => - ReactDOM.render(, container), - ).toWarnDev( - 'A component is changing a controlled input of type ' + - 'text to be uncontrolled.', - ); - expect(node.value).toBe('0'); - }); - - it('should render defaultValue for SSR', () => { - const markup = ReactDOMServer.renderToString( - , - ); - const div = document.createElement('div'); - div.innerHTML = markup; - expect(div.firstChild.getAttribute('value')).toBe('1'); - expect(div.firstChild.getAttribute('defaultValue')).toBe(null); - }); - - it('should render value for SSR', () => { - const element = {}} />; - const markup = ReactDOMServer.renderToString(element); - const div = document.createElement('div'); - div.innerHTML = markup; - expect(div.firstChild.getAttribute('value')).toBe('1'); - expect(div.firstChild.getAttribute('defaultValue')).toBe(null); - }); - - it('should render name attribute if it is supplied', () => { - const node = ReactDOM.render( - , - container, - ); - expect(node.name).toBe('name'); - expect(container.firstChild.getAttribute('name')).toBe('name'); - }); - - it('should render name attribute if it is supplied for SSR', () => { - const element = ; - const markup = ReactDOMServer.renderToString(element); - const div = document.createElement('div'); - div.innerHTML = markup; - expect(div.firstChild.getAttribute('name')).toBe('name'); - }); - - it('should not render name attribute if it is not supplied', () => { - ReactDOM.render(, container); - expect(container.firstChild.getAttribute('name')).toBe(null); - }); - - it('should not render name attribute if it is not supplied for SSR', () => { - const element = ; - const markup = ReactDOMServer.renderToString(element); - const div = document.createElement('div'); - div.innerHTML = markup; - expect(div.firstChild.getAttribute('name')).toBe(null); - }); - - it('should display "foobar" for `defaultValue` of `objToString`', () => { - const objToString = { - toString: function() { - return 'foobar'; - }, - }; - - const stub = ; - const node = ReactDOM.render(stub, container); - - expect(node.value).toBe('foobar'); - }); - - it('should display `value` of number 0', () => { - const stub = ; - const node = ReactDOM.render(stub, container); - - expect(node.value).toBe('0'); - }); - - it('should allow setting `value` to `true`', () => { - let stub = ; - const node = ReactDOM.render(stub, container); - - expect(node.value).toBe('yolo'); - - stub = ReactDOM.render( - , - container, - ); - expect(node.value).toEqual('true'); - }); - - it('should allow setting `value` to `false`', () => { - let stub = ; - const node = ReactDOM.render(stub, container); - - expect(node.value).toBe('yolo'); - - stub = ReactDOM.render( - , - container, - ); - expect(node.value).toEqual('false'); - }); - - it('should allow setting `value` to `objToString`', () => { - let stub = ; - const node = ReactDOM.render(stub, container); - - expect(node.value).toBe('foo'); - - const objToString = { - toString: function() { - return 'foobar'; - }, - }; - stub = ReactDOM.render( - , - container, - ); - expect(node.value).toEqual('foobar'); - }); - - it('should not incur unnecessary DOM mutations', () => { - ReactDOM.render( {}} />, container); - - const node = container.firstChild; - let nodeValue = 'a'; - const nodeValueSetter = jest.fn(); - Object.defineProperty(node, 'value', { - get: function() { - return nodeValue; - }, - set: nodeValueSetter.mockImplementation(function(newValue) { - nodeValue = newValue; - }), - }); - - ReactDOM.render( {}} />, container); - expect(nodeValueSetter).toHaveBeenCalledTimes(0); - - ReactDOM.render( {}} />, container); - expect(nodeValueSetter).toHaveBeenCalledTimes(1); - }); - - it('should not incur unnecessary DOM mutations for numeric type conversion', () => { - ReactDOM.render( {}} />, container); - - const node = container.firstChild; - let nodeValue = '0'; - const nodeValueSetter = jest.fn(); - Object.defineProperty(node, 'value', { - get: function() { - return nodeValue; - }, - set: nodeValueSetter.mockImplementation(function(newValue) { - nodeValue = newValue; - }), - }); - - ReactDOM.render( {}} />, container); - expect(nodeValueSetter).toHaveBeenCalledTimes(0); - }); - - it('should not incur unnecessary DOM mutations for the boolean type conversion', () => { - ReactDOM.render( {}} />, container); - - const node = container.firstChild; - let nodeValue = 'true'; - const nodeValueSetter = jest.fn(); - Object.defineProperty(node, 'value', { - get: function() { - return nodeValue; - }, - set: nodeValueSetter.mockImplementation(function(newValue) { - nodeValue = newValue; - }), - }); - - ReactDOM.render( {}} />, container); - expect(nodeValueSetter).toHaveBeenCalledTimes(0); - }); - - it('should properly control a value of number `0`', () => { - const stub = ; - const node = ReactDOM.render(stub, container); - - setUntrackedValue.call(node, 'giraffe'); - dispatchEventOnNode(node, 'input'); - expect(node.value).toBe('0'); - }); - - it('should properly control 0.0 for a text input', () => { - const stub = ; - const node = ReactDOM.render(stub, container); - - setUntrackedValue.call(node, '0.0'); - dispatchEventOnNode(node, 'input'); - expect(node.value).toBe('0'); - }); - - it('should properly control 0.0 for a number input', () => { - const stub = ; - const node = ReactDOM.render(stub, container); - - setUntrackedValue.call(node, '0.0'); - dispatchEventOnNode(node, 'input'); - expect(node.value).toBe('0.0'); - }); - - it('should properly transition from an empty value to 0', function() { - ReactDOM.render( - , - container, - ); - ReactDOM.render( - , - container, - ); - - const node = container.firstChild; - - expect(node.value).toBe('0'); - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should properly transition from 0 to an empty value', function() { - ReactDOM.render( - , - container, - ); - ReactDOM.render( - , - container, - ); - - const node = container.firstChild; - - expect(node.value).toBe(''); - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should properly transition a text input from 0 to an empty 0.0', function() { - ReactDOM.render( - , - container, - ); - ReactDOM.render( - , - container, - ); - - const node = container.firstChild; - - expect(node.value).toBe('0.0'); - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should properly transition a number input from "" to 0', function() { - ReactDOM.render( - , - container, - ); - ReactDOM.render( - , - container, - ); - - const node = container.firstChild; - - expect(node.value).toBe('0'); - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should properly transition a number input from "" to "0"', function() { - ReactDOM.render( - , - container, - ); - ReactDOM.render( - , - container, - ); - - const node = container.firstChild; - - expect(node.value).toBe('0'); - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should not set a value for submit buttons unnecessarily', () => { - const stub = ; - ReactDOM.render(stub, container); - const node = container.firstChild; - - // The value shouldn't be '', or else the button will have no text; it - // should have the default "Submit" or "Submit Query" label. Most browsers - // report this as not having a `value` attribute at all; IE reports it as - // the actual label that the user sees. - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should remove the value attribute on submit inputs when value is updated to undefined', () => { - const stub = ; - ReactDOM.render(stub, container); - - // Not really relevant to this particular test, but changing to undefined - // should nonetheless trigger a warning - expect(() => - ReactDOM.render( - , - container, - ), - ).toWarnDev( - 'A component is changing a controlled input of type ' + - 'submit to be uncontrolled.', - ); - - const node = container.firstChild; - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should remove the value attribute on reset inputs when value is updated to undefined', () => { - const stub = ; - ReactDOM.render(stub, container); - - // Not really relevant to this particular test, but changing to undefined - // should nonetheless trigger a warning - expect(() => - ReactDOM.render( - , - container, - ), - ).toWarnDev( - 'A component is changing a controlled input of type ' + - 'reset to be uncontrolled.', - ); - - const node = container.firstChild; - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should set a value on a submit input', () => { - let stub = ; - ReactDOM.render(stub, container); - const node = container.firstChild; - - expect(node.getAttribute('value')).toBe('banana'); - }); - - it('should not set an undefined value on a submit input', () => { - let stub = ; - ReactDOM.render(stub, container); - const node = container.firstChild; - - // Note: it shouldn't be an empty string - // because that would erase the "submit" label. - expect(node.hasAttribute('value')).toBe(false); - - ReactDOM.render(stub, container); - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should not set an undefined value on a reset input', () => { - let stub = ; - ReactDOM.render(stub, container); - const node = container.firstChild; - - // Note: it shouldn't be an empty string - // because that would erase the "reset" label. - expect(node.hasAttribute('value')).toBe(false); - - ReactDOM.render(stub, container); - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should not set a null value on a submit input', () => { - let stub = ; - expect(() => { - ReactDOM.render(stub, container); - }).toWarnDev('`value` prop on `input` should not be null'); - const node = container.firstChild; - - // Note: it shouldn't be an empty string - // because that would erase the "submit" label. - expect(node.hasAttribute('value')).toBe(false); - - ReactDOM.render(stub, container); - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should not set a null value on a reset input', () => { - let stub = ; - expect(() => { - ReactDOM.render(stub, container); - }).toWarnDev('`value` prop on `input` should not be null'); - const node = container.firstChild; - - // Note: it shouldn't be an empty string - // because that would erase the "reset" label. - expect(node.hasAttribute('value')).toBe(false); - - ReactDOM.render(stub, container); - expect(node.hasAttribute('value')).toBe(false); - }); - - it('should set a value on a reset input', () => { - let stub = ; - ReactDOM.render(stub, container); - const node = container.firstChild; - - expect(node.getAttribute('value')).toBe('banana'); - }); - - it('should set an empty string value on a submit input', () => { - let stub = ; - ReactDOM.render(stub, container); - const node = container.firstChild; - - expect(node.getAttribute('value')).toBe(''); - }); - - it('should set an empty string value on a reset input', () => { - let stub = ; - ReactDOM.render(stub, container); - const node = container.firstChild; - - expect(node.getAttribute('value')).toBe(''); - }); - - it('should control radio buttons', () => { - class RadioGroup extends React.Component { - render() { - return ( -
- - A - - B -
- -
-
- ); - } - } - - const stub = ReactDOM.render(, container); - const aNode = stub.refs.a; - const bNode = stub.refs.b; - const cNode = stub.refs.c; - - expect(aNode.checked).toBe(true); - expect(bNode.checked).toBe(false); - // c is in a separate form and shouldn't be affected at all here - expect(cNode.checked).toBe(true); - - setUntrackedChecked.call(bNode, true); - expect(aNode.checked).toBe(false); - expect(cNode.checked).toBe(true); - - // The original 'checked' attribute should be unchanged - expect(aNode.hasAttribute('checked')).toBe(false); - expect(bNode.hasAttribute('checked')).toBe(false); - expect(cNode.hasAttribute('checked')).toBe(true); - - // Now let's run the actual ReactDOMInput change event handler - dispatchEventOnNode(bNode, 'click'); - - // The original state should have been restored - expect(aNode.checked).toBe(true); - expect(cNode.checked).toBe(true); - }); - - it('should update defaultValue to empty string', () => { - ReactDOM.render(, container); - ReactDOM.render(, container); - expect(container.firstChild.getAttribute('value')).toBe(''); - }); - - it('sets type, step, min, max before value always', () => { - const log = []; - const originalCreateElement = document.createElement; - spyOnDevAndProd(document, 'createElement').and.callFake(function(type) { - const el = originalCreateElement.apply(this, arguments); - let value = ''; - - if (type === 'input') { - Object.defineProperty(el, 'value', { - get: function() { - return value; - }, - set: function(val) { - value = '' + val; - log.push('set property value'); - }, - }); - spyOnDevAndProd(el, 'setAttribute').and.callFake(function(name) { - log.push('set attribute ' + name); - }); - } - return el; - }); - - ReactDOM.render( - {}} - type="range" - min="0" - max="100" - step="1" - />, - container, - ); - - expect(log).toEqual([ - 'set attribute type', - 'set attribute min', - 'set attribute max', - 'set attribute step', - 'set property value', - ]); - }); - - it('resets value of date/time input to fix bugs in iOS Safari', () => { - function strify(x) { - return JSON.stringify(x, null, 2); - } - - const log = []; - const originalCreateElement = document.createElement; - spyOnDevAndProd(document, 'createElement').and.callFake(function(type) { - const el = originalCreateElement.apply(this, arguments); - let value = ''; - if (type === 'input') { - Object.defineProperty(el, 'value', { - get: function() { - return value; - }, - set: function(val) { - value = '' + val; - log.push(`node.value = ${strify(val)}`); - }, - }); - spyOnDevAndProd(el, 'setAttribute').and.callFake(function(name, val) { - log.push(`node.setAttribute(${strify(name)}, ${strify(val)})`); - }); - } - return el; - }); - - ReactDOM.render( - , - container, - ); - expect(log).toEqual([ - 'node.setAttribute("type", "date")', - 'node.setAttribute("value", "1980-01-01")', - ]); - }); - - describe('assigning the value attribute on controlled inputs', function() { - function getTestInput() { - return class extends React.Component { - state = { - value: this.props.value == null ? '' : this.props.value, - }; - onChange = event => { - this.setState({value: event.target.value}); - }; - render() { - const type = this.props.type; - const value = this.state.value; - - return ; - } - }; - } - - it('retains the value attribute when values change on text inputs', function() { - const Input = getTestInput(); - const stub = ReactDOM.render(, container); - const node = ReactDOM.findDOMNode(stub); - - setUntrackedValue.call(node, '2'); - dispatchEventOnNode(node, 'input'); - - expect(node.hasAttribute('value')).toBe(false); - }); - - it('an uncontrolled number input will not update the value attribute on blur', () => { - const node = ReactDOM.render( - , - container, - ); - - node.focus(); - - setUntrackedValue.call(node, 4); - dispatchEventOnNode(node, 'input'); - - // TODO: it is unclear why blur must be triggered twice, - // manual testing in the fixtures shows that the active element - // is no longer the input, however blur() + a blur event seem to - // be the only way to remove focus in JSDOM - node.blur(); - dispatchEventOnNode(node, 'blur'); - - expect(node.value).toBe('4'); - expect(node.getAttribute('value')).toBe('1'); - }); - - it('an uncontrolled text input will not update the value attribute on blur', () => { - const node = ReactDOM.render( - , - container, - ); - - node.focus(); - - setUntrackedValue.call(node, '2'); - dispatchEventOnNode(node, 'input'); - - // TODO: it is unclear why blur must be triggered twice, - // manual testing in the fixtures shows that the active element - // is no longer the input, however blur() + a blur event seem to - // be the only way to remove focus in JSDOM - node.blur(); - dispatchEventOnNode(node, 'blur'); - - expect(node.value).toBe('2'); - expect(node.getAttribute('value')).toBe('1'); - }); - }); - - describe('setting a controlled input to undefined', () => { - let input; - - function renderInputWithStringThenWithUndefined() { - let setValueToUndefined; - class Input extends React.Component { - constructor() { - super(); - setValueToUndefined = () => this.setState({value: undefined}); - } - state = {value: 'first'}; - render() { - return ( - this.setState({value: e.target.value})} - value={this.state.value} - /> - ); - } - } - - const stub = ReactDOM.render(, container); - input = ReactDOM.findDOMNode(stub); - setUntrackedValue.call(input, 'latest'); - dispatchEventOnNode(input, 'input'); - setValueToUndefined(); - } - - it('reverts the value attribute to the initial value', () => { - expect(renderInputWithStringThenWithUndefined).toWarnDev( - 'Input elements should not switch from controlled to ' + - 'uncontrolled (or vice versa).', - ); - expect(input.getAttribute('value')).toBe(null); - }); - }); - - describe('setting a controlled input to null', () => { - let input; - - function renderInputWithStringThenWithNull() { - let setValueToNull; - class Input extends React.Component { - constructor() { - super(); - setValueToNull = () => this.setState({value: null}); - } - state = {value: 'first'}; - render() { - return ( - this.setState({value: e.target.value})} - value={this.state.value} - /> - ); - } - } - - const stub = ReactDOM.render(, container); - input = ReactDOM.findDOMNode(stub); - setUntrackedValue.call(input, 'latest'); - dispatchEventOnNode(input, 'input'); - setValueToNull(); - } - - it('reverts the value attribute to the initial value', () => { - expect(renderInputWithStringThenWithNull).toWarnDev([ - '`value` prop on `input` should not be null. ' + - 'Consider using an empty string to clear the component ' + - 'or `undefined` for uncontrolled components.', - 'Input elements should not switch from controlled ' + - 'to uncontrolled (or vice versa).', - ]); - expect(input.hasAttribute('value')).toBe(false); - }); - }); - - describe('When given a function value', function() { - it('treats initial function value as an empty string', function() { - expect(() => - ReactDOM.render( - {}} onChange={() => {}} />, - container, - ), - ).toWarnDev('Invalid value for prop `value`'); - const node = container.firstChild; - - expect(node.value).toBe(''); - expect(node.getAttribute('value')).toBe(null); - }); - - it('treats updated function value as an empty string', function() { - ReactDOM.render( {}} />, container); - expect(() => - ReactDOM.render( - {}} onChange={() => {}} />, - container, - ), - ).toWarnDev('Invalid value for prop `value`'); - const node = container.firstChild; - - expect(node.value).toBe(''); - expect(node.getAttribute('value')).toBe(null); - }); - }); - - describe('checked inputs without a value property', function() { - // In absence of a value, radio and checkboxes report a value of "on". - // Between 16 and 16.2, we assigned a node's value to it's current - // value in order to "dettach" it from defaultValue. This had the unfortunate - // side-effect of assigning value="on" to radio and checkboxes - it('does not add "on" in absence of value on a checkbox', function() { - ReactDOM.render( - , - container, - ); - const node = container.firstChild; - - expect(node.value).toBe('on'); - expect(node.hasAttribute('value')).toBe(false); - }); - - it('does not add "on" in absence of value on a radio', function() { - ReactDOM.render( - , - container, - ); - const node = container.firstChild; - - expect(node.value).toBe('on'); - expect(node.hasAttribute('value')).toBe(false); - }); - }); - }); -}); diff --git a/packages/react-dom/src/events/__tests__/ChangeEventPlugin-test.internal.js b/packages/react-dom/src/events/__tests__/ChangeEventPlugin-test.internal.js index 46569e192783e..36abb97b6e7fa 100644 --- a/packages/react-dom/src/events/__tests__/ChangeEventPlugin-test.internal.js +++ b/packages/react-dom/src/events/__tests__/ChangeEventPlugin-test.internal.js @@ -32,6 +32,7 @@ describe('ChangeEventPlugin', () => { let container; beforeEach(() => { + ReactFeatureFlags = require('shared/ReactFeatureFlags'); // TODO pull this into helper method, reduce repetition. // mock the browser APIs which are used in schedule: // - requestAnimationFrame should pass the DOMHighResTimeStamp argument @@ -87,8 +88,14 @@ describe('ChangeEventPlugin', () => { ); node.dispatchEvent(new Event('input', {bubbles: true, cancelable: true})); node.dispatchEvent(new Event('change', {bubbles: true, cancelable: true})); - // There should be no React change events because the value stayed the same. - expect(called).toBe(0); + + if (ReactFeatureFlags.disableInputAttributeSyncing) { + // TODO: figure out why. This might be a bug. + expect(called).toBe(1); + } else { + // There should be no React change events because the value stayed the same. + expect(called).toBe(0); + } }); it('should consider initial checkbox checked=true to be current', () => { diff --git a/scripts/jest/setupFire.js b/scripts/jest/setupFire.js index 2fa152d8e0157..363c8180e313f 100644 --- a/scripts/jest/setupFire.js +++ b/scripts/jest/setupFire.js @@ -2,6 +2,6 @@ jest.mock('shared/ReactFeatureFlags', () => { const ReactFeatureFlags = require.requireActual('shared/ReactFeatureFlags'); - // TODO: Set feature flags for Fire + ReactFeatureFlags.disableInputAttributeSyncing = true; return ReactFeatureFlags; });