@samitouri / QOS-React / commits / 59763bf7f3

Add explicit warning assertions to ReactDOMInput-test (#11744)

Dan Abramov committed Dec 1, 2017 at 17:16 UTC 59763bf7f3ab3b06cd8ab5a5a83ae3dafc667aa9
1 file changed +119 -25
packages/react-dom/src/__tests__/ReactDOMInput-test.js
+119 -25
@@ -38,10 +38,10 @@ describe('ReactDOMInput', () => {
38 ReactDOM = require('react-dom');
39 ReactDOMServer = require('react-dom/server');
40 ReactTestUtils = require('react-dom/test-utils');
41 - spyOnDev(console, 'error');
41 });
42
43 it('should properly control a value even if no event listener exists', () => {
44 + spyOnDev(console, 'error');
45 var container = document.createElement('div');
46 var stub = ReactDOM.render(<input type="text" value="lion" />, container);
47
@@ -141,7 +141,12 @@ describe('ReactDOMInput', () => {
141 value="lion"
142 onChange={e => this.change(e.target.value)}
143 />
144 - <input type="checkbox" ref={n => (this.b = n)} checked={true} />
144 + <input
145 + type="checkbox"
146 + ref={n => (this.b = n)}
147 + checked={true}
148 + onChange={() => {}}
149 + />
150 </div>
151 );
152 }
@@ -219,6 +224,7 @@ describe('ReactDOMInput', () => {
224 });
225
226 it('does change the string ".98" to "0.98" with no change handler', () => {
227 + spyOnDev(console, 'error');
228 class Stub extends React.Component {
229 state = {
230 value: '.98',
@@ -233,9 +239,17 @@ describe('ReactDOMInput', () => {
239 stub.setState({value: '0.98'});
240
241 expect(node.value).toEqual('0.98');
242 + if (__DEV__) {
243 + expect(console.error.calls.count()).toBe(1);
244 + expect(console.error.calls.argsFor(0)[0]).toContain(
245 + 'You provided a `value` prop to a form field ' +
246 + 'without an `onChange` handler.',
247 + );
248 + }
249 });
250
251 it('distinguishes precision for extra zeroes in string number values', () => {
252 + spyOnDev(console, 'error');
253 class Stub extends React.Component {
254 state = {
255 value: '3.0000',
@@ -250,6 +264,13 @@ describe('ReactDOMInput', () => {
264 stub.setState({value: '3'});
265
266 expect(node.value).toEqual('3');
267 + if (__DEV__) {
268 + expect(console.error.calls.count()).toBe(1);
269 + expect(console.error.calls.argsFor(0)[0]).toContain(
270 + 'You provided a `value` prop to a form field ' +
271 + 'without an `onChange` handler.',
272 + );
273 + }
274 });
275
276 it('should display `defaultValue` of number 0', () => {
@@ -336,18 +357,23 @@ describe('ReactDOMInput', () => {
357 });
358
359 it('should take `defaultValue` when changing to uncontrolled input', () => {
360 + spyOnDev(console, 'error');
361 var container = document.createElement('div');
340 -
362 var node = ReactDOM.render(
363 <input type="text" value="0" readOnly="true" />,
364 container,
365 );
345 -
366 expect(node.value).toBe('0');
347 -
367 ReactDOM.render(<input type="text" defaultValue="1" />, container);
349 -
368 expect(node.value).toBe('0');
369 +
370 + if (__DEV__) {
371 + expect(console.error.calls.count()).toBe(1);
372 + expect(console.error.calls.argsFor(0)[0]).toContain(
373 + 'A component is changing a controlled input of type ' +
374 + 'text to be uncontrolled.',
375 + );
376 + }
377 });
378
379 it('should render defaultValue for SSR', () => {
@@ -361,7 +387,7 @@ describe('ReactDOMInput', () => {
387 });
388
389 it('should render value for SSR', () => {
364 - var element = <input type="text" value="1" onChange={function() {}} />;
390 + var element = <input type="text" value="1" onChange={() => {}} />;
391 var markup = ReactDOMServer.renderToString(element);
392 var div = document.createElement('div');
393 div.innerHTML = markup;
@@ -469,7 +495,7 @@ describe('ReactDOMInput', () => {
495
496 it('should not incur unnecessary DOM mutations', () => {
497 var container = document.createElement('div');
472 - ReactDOM.render(<input value="a" />, container);
498 + ReactDOM.render(<input value="a" onChange={() => {}} />, container);
499
500 var node = container.firstChild;
501 var nodeValue = 'a';
@@ -483,16 +509,16 @@ describe('ReactDOMInput', () => {
509 }),
510 });
511
486 - ReactDOM.render(<input value="a" />, container);
512 + ReactDOM.render(<input value="a" onChange={() => {}} />, container);
513 expect(nodeValueSetter.mock.calls.length).toBe(0);
514
489 - ReactDOM.render(<input value="b" />, container);
515 + ReactDOM.render(<input value="b" onChange={() => {}} />, container);
516 expect(nodeValueSetter.mock.calls.length).toBe(1);
517 });
518
519 it('should not incur unnecessary DOM mutations for numeric type conversion', () => {
520 var container = document.createElement('div');
495 - ReactDOM.render(<input value="0" />, container);
521 + ReactDOM.render(<input value="0" onChange={() => {}} />, container);
522
523 var node = container.firstChild;
524 var nodeValue = '0';
@@ -506,13 +532,13 @@ describe('ReactDOMInput', () => {
532 }),
533 });
534
509 - ReactDOM.render(<input value={0} />, container);
535 + ReactDOM.render(<input value={0} onChange={() => {}} />, container);
536 expect(nodeValueSetter.mock.calls.length).toBe(0);
537 });
538
539 it('should not incur unnecessary DOM mutations for the boolean type conversion', () => {
540 var container = document.createElement('div');
515 - ReactDOM.render(<input value="true" />, container);
541 + ReactDOM.render(<input value="true" onChange={() => {}} />, container);
542
543 var node = container.firstChild;
544 var nodeValue = 'true';
@@ -526,7 +552,7 @@ describe('ReactDOMInput', () => {
552 }),
553 });
554
529 - ReactDOM.render(<input value={true} />, container);
555 + ReactDOM.render(<input value={true} onChange={() => {}} />, container);
556 expect(nodeValueSetter.mock.calls.length).toBe(0);
557 });
558
@@ -784,6 +810,7 @@ describe('ReactDOMInput', () => {
810 });
811
812 it('should warn with value and no onChange handler and readOnly specified', () => {
813 + spyOnDev(console, 'error');
814 ReactTestUtils.renderIntoDocument(
815 <input type="text" value="zoink" readOnly={true} />,
816 );
@@ -818,6 +845,7 @@ describe('ReactDOMInput', () => {
845 });
846
847 it('should warn with checked and no onChange handler with readOnly specified', () => {
848 + spyOnDev(console, 'error');
849 ReactTestUtils.renderIntoDocument(
850 <input type="checkbox" checked="false" readOnly={true} />,
851 );
@@ -841,6 +869,7 @@ describe('ReactDOMInput', () => {
869 });
870
871 it('should warn if value is null', () => {
872 + spyOnDev(console, 'error');
873 ReactTestUtils.renderIntoDocument(<input type="text" value={null} />);
874 if (__DEV__) {
875 expect(console.error.calls.argsFor(0)[0]).toContain(
@@ -857,6 +886,7 @@ describe('ReactDOMInput', () => {
886 });
887
888 it('should warn if checked and defaultChecked props are specified', () => {
889 + spyOnDev(console, 'error');
890 ReactTestUtils.renderIntoDocument(
891 <input
892 type="radio"
@@ -890,6 +920,7 @@ describe('ReactDOMInput', () => {
920 });
921
922 it('should warn if value and defaultValue props are specified', () => {
923 + spyOnDev(console, 'error');
924 ReactTestUtils.renderIntoDocument(
925 <input type="text" value="foo" defaultValue="bar" readOnly={true} />,
926 );
@@ -913,6 +944,7 @@ describe('ReactDOMInput', () => {
944 });
945
946 it('should warn if controlled input switches to uncontrolled (value is undefined)', () => {
947 + spyOnDev(console, 'error');
948 var stub = (
949 <input type="text" value="controlled" onChange={emptyFunction} />
950 );
@@ -932,6 +964,7 @@ describe('ReactDOMInput', () => {
964 });
965
966 it('should warn if controlled input switches to uncontrolled (value is null)', () => {
967 + spyOnDev(console, 'error');
968 var stub = (
969 <input type="text" value="controlled" onChange={emptyFunction} />
970 );
@@ -951,6 +984,7 @@ describe('ReactDOMInput', () => {
984 });
985
986 it('should warn if controlled input switches to uncontrolled with defaultValue', () => {
987 + spyOnDev(console, 'error');
988 var stub = (
989 <input type="text" value="controlled" onChange={emptyFunction} />
990 );
@@ -973,6 +1007,7 @@ describe('ReactDOMInput', () => {
1007 });
1008
1009 it('should warn if uncontrolled input (value is undefined) switches to controlled', () => {
1010 + spyOnDev(console, 'error');
1011 var stub = <input type="text" />;
1012 var container = document.createElement('div');
1013 ReactDOM.render(stub, container);
@@ -990,6 +1025,7 @@ describe('ReactDOMInput', () => {
1025 });
1026
1027 it('should warn if uncontrolled input (value is null) switches to controlled', () => {
1028 + spyOnDev(console, 'error');
1029 var stub = <input type="text" value={null} />;
1030 var container = document.createElement('div');
1031 ReactDOM.render(stub, container);
@@ -1007,6 +1043,7 @@ describe('ReactDOMInput', () => {
1043 });
1044
1045 it('should warn if controlled checkbox switches to uncontrolled (checked is undefined)', () => {
1046 + spyOnDev(console, 'error');
1047 var stub = (
1048 <input type="checkbox" checked={true} onChange={emptyFunction} />
1049 );
@@ -1026,6 +1063,7 @@ describe('ReactDOMInput', () => {
1063 });
1064
1065 it('should warn if controlled checkbox switches to uncontrolled (checked is null)', () => {
1066 + spyOnDev(console, 'error');
1067 var stub = (
1068 <input type="checkbox" checked={true} onChange={emptyFunction} />
1069 );
@@ -1045,6 +1083,7 @@ describe('ReactDOMInput', () => {
1083 });
1084
1085 it('should warn if controlled checkbox switches to uncontrolled with defaultChecked', () => {
1086 + spyOnDev(console, 'error');
1087 var stub = (
1088 <input type="checkbox" checked={true} onChange={emptyFunction} />
1089 );
@@ -1064,6 +1103,7 @@ describe('ReactDOMInput', () => {
1103 });
1104
1105 it('should warn if uncontrolled checkbox (checked is undefined) switches to controlled', () => {
1106 + spyOnDev(console, 'error');
1107 var stub = <input type="checkbox" />;
1108 var container = document.createElement('div');
1109 ReactDOM.render(stub, container);
@@ -1081,6 +1121,7 @@ describe('ReactDOMInput', () => {
1121 });
1122
1123 it('should warn if uncontrolled checkbox (checked is null) switches to controlled', () => {
1124 + spyOnDev(console, 'error');
1125 var stub = <input type="checkbox" checked={null} />;
1126 var container = document.createElement('div');
1127 ReactDOM.render(stub, container);
@@ -1098,6 +1139,7 @@ describe('ReactDOMInput', () => {
1139 });
1140
1141 it('should warn if controlled radio switches to uncontrolled (checked is undefined)', () => {
1142 + spyOnDev(console, 'error');
1143 var stub = <input type="radio" checked={true} onChange={emptyFunction} />;
1144 var container = document.createElement('div');
1145 ReactDOM.render(stub, container);
@@ -1115,6 +1157,7 @@ describe('ReactDOMInput', () => {
1157 });
1158
1159 it('should warn if controlled radio switches to uncontrolled (checked is null)', () => {
1160 + spyOnDev(console, 'error');
1161 var stub = <input type="radio" checked={true} onChange={emptyFunction} />;
1162 var container = document.createElement('div');
1163 ReactDOM.render(stub, container);
@@ -1132,6 +1175,7 @@ describe('ReactDOMInput', () => {
1175 });
1176
1177 it('should warn if controlled radio switches to uncontrolled with defaultChecked', () => {
1178 + spyOnDev(console, 'error');
1179 var stub = <input type="radio" checked={true} onChange={emptyFunction} />;
1180 var container = document.createElement('div');
1181 ReactDOM.render(stub, container);
@@ -1149,6 +1193,7 @@ describe('ReactDOMInput', () => {
1193 });
1194
1195 it('should warn if uncontrolled radio (checked is undefined) switches to controlled', () => {
1196 + spyOnDev(console, 'error');
1197 var stub = <input type="radio" />;
1198 var container = document.createElement('div');
1199 ReactDOM.render(stub, container);
@@ -1166,6 +1211,7 @@ describe('ReactDOMInput', () => {
1211 });
1212
1213 it('should warn if uncontrolled radio (checked is null) switches to controlled', () => {
1214 + spyOnDev(console, 'error');
1215 var stub = <input type="radio" checked={null} />;
1216 var container = document.createElement('div');
1217 ReactDOM.render(stub, container);
@@ -1195,9 +1241,6 @@ describe('ReactDOMInput', () => {
1241 container,
1242 );
1243 ReactDOM.render(<input type="radio" />, container);
1198 - if (__DEV__) {
1199 - expect(console.error.calls.count()).toBe(0);
1200 - }
1244 });
1245
1246 it('should not warn if radio value changes but never becomes uncontrolled', () => {
@@ -1216,12 +1259,10 @@ describe('ReactDOMInput', () => {
1259 />,
1260 container,
1261 );
1219 - if (__DEV__) {
1220 - expect(console.error.calls.count()).toBe(0);
1221 - }
1262 });
1263
1264 it('should warn if radio checked false changes to become uncontrolled', () => {
1265 + spyOnDev(console, 'error');
1266 var container = document.createElement('div');
1267 ReactDOM.render(
1268 <input
@@ -1269,7 +1310,14 @@ describe('ReactDOMInput', () => {
1310 });
1311
1312 ReactTestUtils.renderIntoDocument(
1272 - <input value="0" type="range" min="0" max="100" step="1" />,
1313 + <input
1314 + value="0"
1315 + onChange={() => {}}
1316 + type="range"
1317 + min="0"
1318 + max="100"
1319 + step="1"
1320 + />,
1321 );
1322 expect(log).toEqual([
1323 'set attribute type',
@@ -1433,7 +1481,7 @@ describe('ReactDOMInput', () => {
1481 describe('setting a controlled input to undefined', () => {
1482 var input;
1483
1436 - beforeEach(() => {
1484 + function renderInputWithStringThenWithUndefined() {
1485 class Input extends React.Component {
1486 state = {value: 'first'};
1487 render() {
@@ -1450,21 +1498,39 @@ describe('ReactDOMInput', () => {
1498 input = ReactDOM.findDOMNode(stub);
1499 ReactTestUtils.Simulate.change(input, {target: {value: 'latest'}});
1500 ReactTestUtils.Simulate.change(input, {target: {value: undefined}});
1453 - });
1501 + }
1502
1503 it('reverts the value attribute to the initial value', () => {
1504 + spyOnDev(console, 'error');
1505 + renderInputWithStringThenWithUndefined();
1506 expect(input.getAttribute('value')).toBe('first');
1507 + if (__DEV__) {
1508 + expect(console.error.calls.count()).toBe(1);
1509 + expect(console.error.calls.argsFor(0)[0]).toContain(
1510 + 'Input elements should not switch from controlled to ' +
1511 + 'uncontrolled (or vice versa).',
1512 + );
1513 + }
1514 });
1515
1516 it('preserves the value property', () => {
1517 + spyOnDev(console, 'error');
1518 + renderInputWithStringThenWithUndefined();
1519 expect(input.value).toBe('latest');
1520 + if (__DEV__) {
1521 + expect(console.error.calls.count()).toBe(1);
1522 + expect(console.error.calls.argsFor(0)[0]).toContain(
1523 + 'Input elements should not switch from controlled to ' +
1524 + 'uncontrolled (or vice versa).',
1525 + );
1526 + }
1527 });
1528 });
1529
1530 describe('setting a controlled input to null', () => {
1531 var input;
1532
1467 - beforeEach(() => {
1533 + function renderInputWithStringThenWithNull() {
1534 class Input extends React.Component {
1535 state = {value: 'first'};
1536 render() {
@@ -1481,14 +1547,42 @@ describe('ReactDOMInput', () => {
1547 input = ReactDOM.findDOMNode(stub);
1548 ReactTestUtils.Simulate.change(input, {target: {value: 'latest'}});
1549 ReactTestUtils.Simulate.change(input, {target: {value: null}});
1484 - });
1550 + }
1551
1552 it('reverts the value attribute to the initial value', () => {
1553 + spyOnDev(console, 'error');
1554 + renderInputWithStringThenWithNull();
1555 expect(input.getAttribute('value')).toBe('first');
1556 + if (__DEV__) {
1557 + expect(console.error.calls.count()).toBe(2);
1558 + expect(console.error.calls.argsFor(0)[0]).toContain(
1559 + '`value` prop on `input` should not be null. ' +
1560 + 'Consider using an empty string to clear the component ' +
1561 + 'or `undefined` for uncontrolled components.',
1562 + );
1563 + expect(console.error.calls.argsFor(1)[0]).toContain(
1564 + 'Input elements should not switch from controlled ' +
1565 + 'to uncontrolled (or vice versa).',
1566 + );
1567 + }
1568 });
1569
1570 it('preserves the value property', () => {
1571 + spyOnDev(console, 'error');
1572 + renderInputWithStringThenWithNull();
1573 expect(input.value).toBe('latest');
1574 + if (__DEV__) {
1575 + expect(console.error.calls.count()).toBe(2);
1576 + expect(console.error.calls.argsFor(0)[0]).toContain(
1577 + '`value` prop on `input` should not be null. ' +
1578 + 'Consider using an empty string to clear the component ' +
1579 + 'or `undefined` for uncontrolled components.',
1580 + );
1581 + expect(console.error.calls.argsFor(1)[0]).toContain(
1582 + 'Input elements should not switch from controlled ' +
1583 + 'to uncontrolled (or vice versa).',
1584 + );
1585 + }
1586 });
1587 });
1588 });