9
10
'use strict';
11
12
+// Set by `yarn test-fire`.
13
+const {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags');
14
+
15
function emptyFunction() {}
16
17
describe('ReactDOMInput', () => {
233
const node = ReactDOM.render(stub, container);
234
235
setUntrackedValue.call(node, '2.0');
233
-
236
dispatchEventOnNode(node, 'input');
237
236
- expect(node.getAttribute('value')).toBe('2');
238
expect(node.value).toBe('2');
239
+ if (disableInputAttributeSyncing) {
240
+ expect(node.hasAttribute('value')).toBe(false);
241
+ } else {
242
+ expect(node.getAttribute('value')).toBe('2');
243
+ }
244
});
245
246
it('does change the string "2" to "2.0" with no change handler', () => {
248
const node = ReactDOM.render(stub, container);
249
250
setUntrackedValue.call(node, '2.0');
245
-
251
dispatchEventOnNode(node, 'input');
252
248
- expect(node.getAttribute('value')).toBe('2');
253
expect(node.value).toBe('2');
254
+ if (disableInputAttributeSyncing) {
255
+ expect(node.hasAttribute('value')).toBe(false);
256
+ } else {
257
+ expect(node.getAttribute('value')).toBe('2');
258
+ }
259
});
260
261
it('changes the number 2 to "2.0" using a change handler', () => {
277
const node = ReactDOM.findDOMNode(stub);
278
279
setUntrackedValue.call(node, '2.0');
271
-
280
dispatchEventOnNode(node, 'input');
281
274
- expect(node.getAttribute('value')).toBe('2.0');
282
expect(node.value).toBe('2.0');
283
+ if (disableInputAttributeSyncing) {
284
+ expect(node.hasAttribute('value')).toBe(false);
285
+ } else {
286
+ expect(node.getAttribute('value')).toBe('2.0');
287
+ }
288
});
289
});
290
431
);
432
433
expect(node.value).toBe('0');
434
+ expect(node.defaultValue).toBe('0');
435
436
ReactDOM.render(<input type="text" defaultValue="1" />, container);
437
425
- expect(node.value).toBe('0');
426
- expect(node.defaultValue).toBe('1');
438
+ if (disableInputAttributeSyncing) {
439
+ expect(node.value).toBe('1');
440
+ expect(node.defaultValue).toBe('1');
441
+ } else {
442
+ expect(node.value).toBe('0');
443
+ expect(node.defaultValue).toBe('1');
444
+ }
445
});
446
447
it('should update `defaultValue` for uncontrolled date/time input', () => {
451
);
452
453
expect(node.value).toBe('1980-01-01');
454
+ expect(node.defaultValue).toBe('1980-01-01');
455
456
ReactDOM.render(<input type="date" defaultValue="2000-01-01" />, container);
457
439
- expect(node.value).toBe('1980-01-01');
440
- expect(node.defaultValue).toBe('2000-01-01');
458
+ if (disableInputAttributeSyncing) {
459
+ expect(node.value).toBe('2000-01-01');
460
+ expect(node.defaultValue).toBe('2000-01-01');
461
+ } else {
462
+ expect(node.value).toBe('1980-01-01');
463
+ expect(node.defaultValue).toBe('2000-01-01');
464
+ }
465
466
ReactDOM.render(<input type="date" />, container);
467
});
675
676
setUntrackedValue.call(node, '0.0');
677
dispatchEventOnNode(node, 'input');
654
- expect(node.value).toBe('0.0');
678
+
679
+ if (disableInputAttributeSyncing) {
680
+ expect(node.value).toBe('0.0');
681
+ expect(node.hasAttribute('value')).toBe(false);
682
+ } else {
683
+ dispatchEventOnNode(node, 'blur');
684
+
685
+ expect(node.value).toBe('0.0');
686
+ expect(node.getAttribute('value')).toBe('0.0');
687
+ }
688
});
689
690
it('should properly transition from an empty value to 0', function() {
698
);
699
700
const node = container.firstChild;
668
-
701
expect(node.value).toBe('0');
670
- expect(node.defaultValue).toBe('0');
702
+
703
+ if (disableInputAttributeSyncing) {
704
+ expect(node.hasAttribute('value')).toBe(false);
705
+ } else {
706
+ expect(node.defaultValue).toBe('0');
707
+ }
708
});
709
710
it('should properly transition from 0 to an empty value', function() {
736
const node = container.firstChild;
737
738
expect(node.value).toBe('0.0');
702
- expect(node.defaultValue).toBe('0.0');
739
+ if (disableInputAttributeSyncing) {
740
+ expect(node.hasAttribute('value')).toBe(false);
741
+ } else {
742
+ expect(node.defaultValue).toBe('0.0');
743
+ }
744
});
745
746
it('should properly transition a number input from "" to 0', function() {
756
const node = container.firstChild;
757
758
expect(node.value).toBe('0');
718
- expect(node.defaultValue).toBe('0');
759
+ if (disableInputAttributeSyncing) {
760
+ expect(node.hasAttribute('value')).toBe(false);
761
+ } else {
762
+ expect(node.defaultValue).toBe('0');
763
+ }
764
});
765
766
it('should properly transition a number input from "" to "0"', function() {
776
const node = container.firstChild;
777
778
expect(node.value).toBe('0');
734
- expect(node.defaultValue).toBe('0');
779
+ if (disableInputAttributeSyncing) {
780
+ expect(node.hasAttribute('value')).toBe(false);
781
+ } else {
782
+ expect(node.defaultValue).toBe('0');
783
+ }
784
});
785
786
it('should have the correct target value', () => {
1005
const cNode = stub.refs.c;
1006
1007
expect(aNode.checked).toBe(true);
959
- expect(aNode.hasAttribute('checked')).toBe(true);
1008
expect(bNode.checked).toBe(false);
961
- expect(bNode.hasAttribute('checked')).toBe(false);
1009
// c is in a separate form and shouldn't be affected at all here
1010
expect(cNode.checked).toBe(true);
964
- expect(cNode.hasAttribute('checked')).toBe(true);
1011
+
1012
+ if (disableInputAttributeSyncing) {
1013
+ expect(aNode.hasAttribute('checked')).toBe(false);
1014
+ expect(bNode.hasAttribute('checked')).toBe(false);
1015
+ expect(cNode.hasAttribute('checked')).toBe(true);
1016
+ } else {
1017
+ expect(aNode.hasAttribute('checked')).toBe(true);
1018
+ expect(bNode.hasAttribute('checked')).toBe(false);
1019
+ expect(cNode.hasAttribute('checked')).toBe(true);
1020
+ }
1021
1022
setUntrackedChecked.call(bNode, true);
1023
expect(aNode.checked).toBe(false);
1024
expect(cNode.checked).toBe(true);
1025
1026
// The original 'checked' attribute should be unchanged
971
- expect(aNode.hasAttribute('checked')).toBe(true);
972
- expect(bNode.hasAttribute('checked')).toBe(false);
973
- expect(cNode.hasAttribute('checked')).toBe(true);
1027
+ if (disableInputAttributeSyncing) {
1028
+ expect(aNode.hasAttribute('checked')).toBe(false);
1029
+ expect(bNode.hasAttribute('checked')).toBe(false);
1030
+ expect(cNode.hasAttribute('checked')).toBe(true);
1031
+ } else {
1032
+ expect(aNode.hasAttribute('checked')).toBe(true);
1033
+ expect(bNode.hasAttribute('checked')).toBe(false);
1034
+ expect(cNode.hasAttribute('checked')).toBe(true);
1035
+ }
1036
1037
// Now let's run the actual ReactDOMInput change event handler
1038
dispatchEventOnNode(bNode, 'click');
1578
/>,
1579
container,
1580
);
1519
- expect(log).toEqual([
1520
- 'set attribute type',
1521
- 'set attribute min',
1522
- 'set attribute max',
1523
- 'set attribute step',
1524
- 'set property value',
1525
- 'set attribute value',
1526
- 'set attribute checked',
1527
- ]);
1581
+
1582
+ if (disableInputAttributeSyncing) {
1583
+ expect(log).toEqual([
1584
+ 'set attribute type',
1585
+ 'set attribute min',
1586
+ 'set attribute max',
1587
+ 'set attribute step',
1588
+ 'set property value',
1589
+ ]);
1590
+ } else {
1591
+ expect(log).toEqual([
1592
+ 'set attribute type',
1593
+ 'set attribute min',
1594
+ 'set attribute max',
1595
+ 'set attribute step',
1596
+ 'set property value',
1597
+ 'set attribute value',
1598
+ 'set attribute checked',
1599
+ ]);
1600
+ }
1601
});
1602
1603
it('sets value properly with type coming later in props', () => {
1652
});
1653
1654
ReactDOM.render(<input type="date" defaultValue="1980-01-01" />, container);
1582
- expect(log).toEqual([
1583
- 'node.setAttribute("type", "date")',
1584
- 'node.value = "1980-01-01"',
1585
- 'node.setAttribute("value", "1980-01-01")',
1586
- 'node.setAttribute("checked", "")',
1587
- ]);
1655
+
1656
+ if (disableInputAttributeSyncing) {
1657
+ expect(log).toEqual([
1658
+ 'node.setAttribute("type", "date")',
1659
+ 'node.setAttribute("value", "1980-01-01")',
1660
+ ]);
1661
+ } else {
1662
+ expect(log).toEqual([
1663
+ 'node.setAttribute("type", "date")',
1664
+ 'node.value = "1980-01-01"',
1665
+ 'node.setAttribute("value", "1980-01-01")',
1666
+ 'node.setAttribute("checked", "")',
1667
+ ]);
1668
+ }
1669
});
1670
1671
describe('assigning the value attribute on controlled inputs', function() {
1694
setUntrackedValue.call(node, '2');
1695
dispatchEventOnNode(node, 'input');
1696
1616
- expect(node.getAttribute('value')).toBe('2');
1697
+ if (disableInputAttributeSyncing) {
1698
+ expect(node.hasAttribute('value')).toBe(false);
1699
+ } else {
1700
+ expect(node.getAttribute('value')).toBe('2');
1701
+ }
1702
});
1703
1704
it('does not set the value attribute on number inputs if focused', () => {
1714
setUntrackedValue.call(node, '2');
1715
dispatchEventOnNode(node, 'input');
1716
1632
- expect(node.getAttribute('value')).toBe('1');
1717
+ if (disableInputAttributeSyncing) {
1718
+ expect(node.hasAttribute('value')).toBe(false);
1719
+ } else {
1720
+ expect(node.getAttribute('value')).toBe('1');
1721
+ }
1722
});
1723
1724
it('sets the value attribute on number inputs on blur', () => {
1729
);
1730
const node = ReactDOM.findDOMNode(stub);
1731
1732
+ node.focus();
1733
setUntrackedValue.call(node, '2');
1734
dispatchEventOnNode(node, 'input');
1735
+ // TODO: it is unclear why blur must be triggered twice,
1736
+ // manual testing in the fixtures shows that the active element
1737
+ // is no longer the input, however blur() + a blur event seem to
1738
+ // be the only way to remove focus in JSDOM
1739
+ node.blur();
1740
dispatchEventOnNode(node, 'blur');
1741
1647
- expect(node.getAttribute('value')).toBe('2');
1742
+ if (disableInputAttributeSyncing) {
1743
+ expect(node.value).toBe('2');
1744
+ expect(node.hasAttribute('value')).toBe(false);
1745
+ } else {
1746
+ expect(node.value).toBe('2');
1747
+ expect(node.getAttribute('value')).toBe('2');
1748
+ }
1749
});
1750
1751
it('an uncontrolled number input will not update the value attribute on blur', () => {
1754
container,
1755
);
1756
1757
+ node.focus();
1758
setUntrackedValue.call(node, 4);
1657
-
1759
+ dispatchEventOnNode(node, 'input');
1760
+ // TODO: it is unclear why blur must be triggered twice,
1761
+ // manual testing in the fixtures shows that the active element
1762
+ // is no longer the input, however blur() + a blur event seem to
1763
+ // be the only way to remove focus in JSDOM
1764
+ node.blur();
1765
dispatchEventOnNode(node, 'blur');
1766
1767
expect(node.getAttribute('value')).toBe('1');
1773
container,
1774
);
1775
1776
+ node.focus();
1777
setUntrackedValue.call(node, 4);
1670
-
1778
+ dispatchEventOnNode(node, 'input');
1779
+ // TODO: it is unclear why blur must be triggered twice,
1780
+ // manual testing in the fixtures shows that the active element
1781
+ // is no longer the input, however blur() + a blur event seem to
1782
+ // be the only way to remove focus in JSDOM
1783
+ node.blur();
1784
dispatchEventOnNode(node, 'blur');
1785
1786
expect(node.getAttribute('value')).toBe('1');
1820
'Input elements should not switch from controlled to ' +
1821
'uncontrolled (or vice versa).',
1822
);
1710
- expect(input.getAttribute('value')).toBe('first');
1823
+ if (disableInputAttributeSyncing) {
1824
+ expect(input.getAttribute('value')).toBe(null);
1825
+ } else {
1826
+ expect(input.getAttribute('value')).toBe('first');
1827
+ }
1828
});
1829
1830
it('preserves the value property', () => {
1872
'Input elements should not switch from controlled ' +
1873
'to uncontrolled (or vice versa).',
1874
]);
1758
- expect(input.getAttribute('value')).toBe('first');
1875
+ if (disableInputAttributeSyncing) {
1876
+ expect(input.hasAttribute('value')).toBe(false);
1877
+ } else {
1878
+ expect(input.getAttribute('value')).toBe('first');
1879
+ }
1880
});
1881
1882
it('preserves the value property', () => {
1902
const node = container.firstChild;
1903
1904
expect(node.value).toBe('');
1784
- expect(node.getAttribute('value')).toBe('');
1905
+ if (disableInputAttributeSyncing) {
1906
+ expect(node.hasAttribute('value')).toBe(false);
1907
+ } else {
1908
+ expect(node.getAttribute('value')).toBe('');
1909
+ }
1910
});
1911
1912
it('treats updated Symbol value as an empty string', function() {
1920
const node = container.firstChild;
1921
1922
expect(node.value).toBe('');
1798
- expect(node.getAttribute('value')).toBe('');
1923
+ if (disableInputAttributeSyncing) {
1924
+ expect(node.hasAttribute('value')).toBe(false);
1925
+ } else {
1926
+ expect(node.getAttribute('value')).toBe('');
1927
+ }
1928
});
1929
1930
it('treats initial Symbol defaultValue as an empty string', function() {
1941
ReactDOM.render(<input defaultValue={Symbol('foobar')} />, container);
1942
const node = container.firstChild;
1943
1815
- expect(node.value).toBe('foo');
1944
+ if (disableInputAttributeSyncing) {
1945
+ expect(node.value).toBe('');
1946
+ } else {
1947
+ expect(node.value).toBe('foo');
1948
+ }
1949
expect(node.getAttribute('value')).toBe('');
1950
// TODO: we should warn here.
1951
});
1962
const node = container.firstChild;
1963
1964
expect(node.value).toBe('');
1832
- expect(node.getAttribute('value')).toBe('');
1965
+ if (disableInputAttributeSyncing) {
1966
+ expect(node.hasAttribute('value')).toBe(false);
1967
+ } else {
1968
+ expect(node.getAttribute('value')).toBe('');
1969
+ }
1970
});
1971
1972
it('treats updated function value as an empty string', function() {
1980
const node = container.firstChild;
1981
1982
expect(node.value).toBe('');
1846
- expect(node.getAttribute('value')).toBe('');
1983
+ if (disableInputAttributeSyncing) {
1984
+ expect(node.hasAttribute('value')).toBe(false);
1985
+ } else {
1986
+ expect(node.getAttribute('value')).toBe('');
1987
+ }
1988
});
1989
1990
it('treats initial function defaultValue as an empty string', function() {
2001
ReactDOM.render(<input defaultValue={() => {}} />, container);
2002
const node = container.firstChild;
2003
1863
- expect(node.value).toBe('foo');
1864
- expect(node.getAttribute('value')).toBe('');
2004
+ if (disableInputAttributeSyncing) {
2005
+ expect(node.value).toBe('');
2006
+ expect(node.getAttribute('value')).toBe('');
2007
+ } else {
2008
+ expect(node.value).toBe('foo');
2009
+ expect(node.getAttribute('value')).toBe('');
2010
+ }
2011
// TODO: we should warn here.
2012
});
2013
});