@@ -18,6 +18,7 @@ describe('ReactDOMInput', function() {
1818 var EventConstants ;
1919 var React ;
2020 var ReactDOM ;
21+ var ReactDOMServer ;
2122 var ReactDOMFeatureFlags ;
2223 var ReactLink ;
2324 var ReactTestUtils ;
@@ -27,6 +28,7 @@ describe('ReactDOMInput', function() {
2728 EventConstants = require ( 'EventConstants' ) ;
2829 React = require ( 'React' ) ;
2930 ReactDOM = require ( 'ReactDOM' ) ;
31+ ReactDOMServer = require ( 'ReactDOMServer' ) ;
3032 ReactDOMFeatureFlags = require ( 'ReactDOMFeatureFlags' ) ;
3133 ReactLink = require ( 'ReactLink' ) ;
3234 ReactTestUtils = require ( 'ReactTestUtils' ) ;
@@ -38,6 +40,7 @@ describe('ReactDOMInput', function() {
3840 stub = ReactTestUtils . renderIntoDocument ( stub ) ;
3941 var node = ReactDOM . findDOMNode ( stub ) ;
4042
43+ expect ( node . getAttribute ( 'value' ) ) . toBe ( '0' ) ;
4144 expect ( node . value ) . toBe ( '0' ) ;
4245 } ) ;
4346
@@ -57,6 +60,48 @@ describe('ReactDOMInput', function() {
5760 expect ( node . value ) . toBe ( 'false' ) ;
5861 } ) ;
5962
63+ it ( 'should update `defaultValue` for uncontrolled input' , function ( ) {
64+ var container = document . createElement ( 'div' ) ;
65+
66+ var node = ReactDOM . render ( < input type = "text" defaultValue = "0" /> , container ) ;
67+
68+ expect ( node . value ) . toBe ( '0' ) ;
69+
70+ ReactDOM . render ( < input type = "text" defaultValue = "1" /> , container ) ;
71+
72+ expect ( node . value ) . toBe ( '0' ) ;
73+ expect ( node . defaultValue ) . toBe ( '1' ) ;
74+ } ) ;
75+
76+ it ( 'should take `defaultValue` when changing to uncontrolled input' , function ( ) {
77+ var container = document . createElement ( 'div' ) ;
78+
79+ var node = ReactDOM . render ( < input type = "text" value = "0" readOnly = "true" /> , container ) ;
80+
81+ expect ( node . value ) . toBe ( '0' ) ;
82+
83+ ReactDOM . render ( < input type = "text" defaultValue = "1" /> , container ) ;
84+
85+ expect ( node . value ) . toBe ( '0' ) ;
86+ } ) ;
87+
88+ it ( 'should render defaultValue for SSR' , function ( ) {
89+ var markup = ReactDOMServer . renderToString ( < input type = "text" defaultValue = "1" /> ) ;
90+ var div = document . createElement ( 'div' ) ;
91+ div . innerHTML = markup ;
92+ expect ( div . firstChild . getAttribute ( 'value' ) ) . toBe ( '1' ) ;
93+ expect ( div . firstChild . getAttribute ( 'defaultValue' ) ) . toBe ( null ) ;
94+ } ) ;
95+
96+ it ( 'should render value for SSR' , function ( ) {
97+ var element = < input type = "text" value = "1" onChange = { function ( ) { } } /> ;
98+ var markup = ReactDOMServer . renderToString ( element ) ;
99+ var div = document . createElement ( 'div' ) ;
100+ div . innerHTML = markup ;
101+ expect ( div . firstChild . getAttribute ( 'value' ) ) . toBe ( '1' ) ;
102+ expect ( div . firstChild . getAttribute ( 'defaultValue' ) ) . toBe ( null ) ;
103+ } ) ;
104+
60105 it ( 'should display "foobar" for `defaultValue` of `objToString`' , function ( ) {
61106 var objToString = {
62107 toString : function ( ) {
@@ -82,8 +127,7 @@ describe('ReactDOMInput', function() {
82127 it ( 'should allow setting `value` to `true`' , function ( ) {
83128 var container = document . createElement ( 'div' ) ;
84129 var stub = < input type = "text" value = "yolo" onChange = { emptyFunction } /> ;
85- stub = ReactDOM . render ( stub , container ) ;
86- var node = ReactDOM . findDOMNode ( stub ) ;
130+ var node = ReactDOM . render ( stub , container ) ;
87131
88132 expect ( node . value ) . toBe ( 'yolo' ) ;
89133
@@ -97,8 +141,7 @@ describe('ReactDOMInput', function() {
97141 it ( 'should allow setting `value` to `false`' , function ( ) {
98142 var container = document . createElement ( 'div' ) ;
99143 var stub = < input type = "text" value = "yolo" onChange = { emptyFunction } /> ;
100- stub = ReactDOM . render ( stub , container ) ;
101- var node = ReactDOM . findDOMNode ( stub ) ;
144+ var node = ReactDOM . render ( stub , container ) ;
102145
103146 expect ( node . value ) . toBe ( 'yolo' ) ;
104147
@@ -112,8 +155,7 @@ describe('ReactDOMInput', function() {
112155 it ( 'should allow setting `value` to `objToString`' , function ( ) {
113156 var container = document . createElement ( 'div' ) ;
114157 var stub = < input type = "text" value = "foo" onChange = { emptyFunction } /> ;
115- stub = ReactDOM . render ( stub , container ) ;
116- var node = ReactDOM . findDOMNode ( stub ) ;
158+ var node = ReactDOM . render ( stub , container ) ;
117159
118160 expect ( node . value ) . toBe ( 'foo' ) ;
119161
@@ -129,6 +171,29 @@ describe('ReactDOMInput', function() {
129171 expect ( node . value ) . toEqual ( 'foobar' ) ;
130172 } ) ;
131173
174+ it ( 'should not incur unnecessary DOM mutations' , function ( ) {
175+ var container = document . createElement ( 'div' ) ;
176+ ReactDOM . render ( < input value = "a" /> , container ) ;
177+
178+ var node = container . firstChild ;
179+ var nodeValue = 'a' ;
180+ var nodeValueSetter = jest . genMockFn ( ) ;
181+ Object . defineProperty ( node , 'value' , {
182+ get : function ( ) {
183+ return nodeValue ;
184+ } ,
185+ set : nodeValueSetter . mockImplementation ( function ( newValue ) {
186+ nodeValue = newValue ;
187+ } ) ,
188+ } ) ;
189+
190+ ReactDOM . render ( < input value = "a" /> , container ) ;
191+ expect ( nodeValueSetter . mock . calls . length ) . toBe ( 0 ) ;
192+
193+ ReactDOM . render ( < input value = "b" /> , container ) ;
194+ expect ( nodeValueSetter . mock . calls . length ) . toBe ( 1 ) ;
195+ } ) ;
196+
132197 it ( 'should properly control a value of number `0`' , function ( ) {
133198 var stub = < input type = "text" value = { 0 } onChange = { emptyFunction } /> ;
134199 stub = ReactTestUtils . renderIntoDocument ( stub ) ;
@@ -390,6 +455,13 @@ describe('ReactDOMInput', function() {
390455
391456 } ) ;
392457
458+ it ( 'should update defaultValue to empty string' , function ( ) {
459+ var container = document . createElement ( 'div' ) ;
460+ ReactDOM . render ( < input type = "text" defaultValue = { 'foo' } /> , container ) ;
461+ ReactDOM . render ( < input type = "text" defaultValue = { '' } /> , container ) ;
462+ expect ( container . firstChild . defaultValue ) . toBe ( '' ) ;
463+ } ) ;
464+
393465 it ( 'should throw if both checkedLink and valueLink are provided' , function ( ) {
394466 var node = document . createElement ( 'div' ) ;
395467 var link = new ReactLink ( true , jest . fn ( ) ) ;
@@ -609,6 +681,11 @@ describe('ReactDOMInput', function() {
609681 'set data-reactroot' ,
610682 'set type' ,
611683 'set value' ,
684+ 'set value' ,
685+ 'set name' ,
686+ 'set checked' ,
687+ 'set checked' ,
688+ 'set name' ,
612689 ] ) ;
613690 } ) ;
614691
0 commit comments