diff --git a/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js b/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js index 1fba16247e2b..56319c95d76a 100644 --- a/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js +++ b/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js @@ -79,7 +79,7 @@ describe('DOMPropertyOperations', () => { it('should not remove empty attributes for special properties', () => { const container = document.createElement('div'); - ReactDOM.render(, container); + ReactDOM.render( {}} />, container); expect(container.firstChild.getAttribute('value')).toBe(''); expect(container.firstChild.value).toBe(''); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMInput-test.js b/packages/react-dom/src/__tests__/ReactDOMInput-test.js index 480287cfc008..5afa9dcf7aaf 100644 --- a/packages/react-dom/src/__tests__/ReactDOMInput-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMInput-test.js @@ -47,6 +47,71 @@ describe('ReactDOMInput', () => { document.body.removeChild(container); }); + it('should warn for controlled value of 0 with missing onChange', () => { + expect(() => { + ReactDOM.render(, container); + }).toWarnDev( + 'Failed prop type: You provided a `value` prop to a form field without an `onChange` handler.', + ); + }); + + it('should warn for controlled value of "" with missing onChange', () => { + expect(() => { + ReactDOM.render(, container); + }).toWarnDev( + 'Failed prop type: You provided a `value` prop to a form field without an `onChange` handler.', + ); + }); + + it('should warn for controlled value of "0" with missing onChange', () => { + expect(() => { + ReactDOM.render(, container); + }).toWarnDev( + 'Failed prop type: You provided a `value` prop to a form field without an `onChange` handler.', + ); + }); + + it('should warn for controlled value of false with missing onChange', () => { + expect(() => + ReactDOM.render(, container), + ).toWarnDev( + 'Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler.', + ); + }); + + it('should warn with checked and no onChange handler with readOnly specified', () => { + ReactDOM.render( + , + container, + ); + ReactDOM.unmountComponentAtNode(container); + + expect(() => + ReactDOM.render( + , + container, + ), + ).toWarnDev( + 'Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler. ' + + 'This will render a read-only field. If the field should be mutable use `defaultChecked`. ' + + 'Otherwise, set either `onChange` or `readOnly`.', + ); + }); + + it('should not warn about missing onChange in uncontrolled inputs', () => { + ReactDOM.render(, container); + ReactDOM.unmountComponentAtNode(container); + ReactDOM.render(, container); + ReactDOM.unmountComponentAtNode(container); + ReactDOM.render(, container); + ReactDOM.unmountComponentAtNode(container); + ReactDOM.render(, container); + ReactDOM.unmountComponentAtNode(container); + ReactDOM.render(, container); + ReactDOM.unmountComponentAtNode(container); + ReactDOM.render(, container); + }); + it('should properly control a value even if no event listener exists', () => { let node; @@ -452,7 +517,7 @@ describe('ReactDOMInput', () => { }); it('should display `value` of number 0', () => { - const stub = ; + const stub = ; const node = ReactDOM.render(stub, container); expect(node.value).toBe('0'); @@ -590,8 +655,14 @@ describe('ReactDOMInput', () => { }); it('should properly transition from an empty value to 0', function() { - ReactDOM.render(, container); - ReactDOM.render(, container); + ReactDOM.render( + , + container, + ); + ReactDOM.render( + , + container, + ); const node = container.firstChild; @@ -600,8 +671,14 @@ describe('ReactDOMInput', () => { }); it('should properly transition from 0 to an empty value', function() { - ReactDOM.render(, container); - ReactDOM.render(, container); + ReactDOM.render( + , + container, + ); + ReactDOM.render( + , + container, + ); const node = container.firstChild; @@ -610,8 +687,14 @@ describe('ReactDOMInput', () => { }); it('should properly transition a text input from 0 to an empty 0.0', function() { - ReactDOM.render(, container); - ReactDOM.render(, container); + ReactDOM.render( + , + container, + ); + ReactDOM.render( + , + container, + ); const node = container.firstChild; @@ -620,8 +703,14 @@ describe('ReactDOMInput', () => { }); it('should properly transition a number input from "" to 0', function() { - ReactDOM.render(, container); - ReactDOM.render(, container); + ReactDOM.render( + , + container, + ); + ReactDOM.render( + , + container, + ); const node = container.firstChild; @@ -630,8 +719,14 @@ describe('ReactDOMInput', () => { }); it('should properly transition a number input from "" to "0"', function() { - ReactDOM.render(, container); - ReactDOM.render(, container); + ReactDOM.render( + , + container, + ); + ReactDOM.render( + , + container, + ); const node = container.firstChild; @@ -874,25 +969,6 @@ describe('ReactDOMInput', () => { dispatchEventOnNode(node, 'input'); }); - it('should warn with checked and no onChange handler with readOnly specified', () => { - ReactDOM.render( - , - container, - ); - ReactDOM.unmountComponentAtNode(container); - - expect(() => - ReactDOM.render( - , - container, - ), - ).toWarnDev( - 'Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler. ' + - 'This will render a read-only field. If the field should be mutable use `defaultChecked`. ' + - 'Otherwise, set either `onChange` or `readOnly`.', - ); - }); - it('should update defaultValue to empty string', () => { ReactDOM.render(, container); ReactDOM.render(, container); diff --git a/packages/react-dom/src/__tests__/ReactDOMSelect-test.js b/packages/react-dom/src/__tests__/ReactDOMSelect-test.js index 5548c039316a..e94cc7895cbb 100644 --- a/packages/react-dom/src/__tests__/ReactDOMSelect-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMSelect-test.js @@ -654,6 +654,13 @@ describe('ReactDOMSelect', () => { ); }); + it('should not warn about missing onChange in uncontrolled textareas', () => { + const container = document.createElement('div'); + ReactDOM.render(, container); + }); + it('should be able to safely remove select onChange', () => { function changeView() { ReactDOM.unmountComponentAtNode(container); diff --git a/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js b/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js index 73522ace5d4c..fa5d717974aa 100644 --- a/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMTextarea-test.js @@ -97,7 +97,7 @@ describe('ReactDOMTextarea', () => { }); it('should display `value` of number 0', () => { - const stub =