Skip to content

Commit 045f1a7

Browse files
jquensejimfb
authored andcommitted
Only fire input value change events when the value changes (#5746)
* Only fire input value change events when the value changes fixes #554, fixes #1471, fixes #2185 (still trying to figure out why) * catch programmatic value changes * move value tracking to seperate module
1 parent 4016e71 commit 045f1a7

File tree

7 files changed

+606
-90
lines changed

7 files changed

+606
-90
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/**
2+
* Copyright 2013-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*
9+
* @emails react-core
10+
*/
11+
'use strict';
12+
13+
var React = require('React');
14+
var ReactTestUtils = require('ReactTestUtils');
15+
var inputValueTracking = require('inputValueTracking');
16+
17+
describe('inputValueTracking', function() {
18+
var input, checkbox, mockComponent;
19+
20+
beforeEach(function() {
21+
input = document.createElement('input');
22+
input.type = 'text';
23+
checkbox = document.createElement('input');
24+
checkbox.type = 'checkbox';
25+
mockComponent = { _nativeNode: input, _wrapperState: {} };
26+
});
27+
28+
it('should attach tracker to wrapper state', function() {
29+
inputValueTracking.track(mockComponent);
30+
31+
expect(
32+
mockComponent._wrapperState.hasOwnProperty('valueTracker')
33+
).toBe(true);
34+
});
35+
36+
it('should define `value` on the instance node', function() {
37+
inputValueTracking.track(mockComponent);
38+
39+
expect(
40+
input.hasOwnProperty('value')
41+
).toBe(true);
42+
});
43+
44+
it('should define `checked` on the instance node', function() {
45+
mockComponent._nativeNode = checkbox;
46+
inputValueTracking.track(mockComponent);
47+
48+
expect(checkbox.hasOwnProperty('checked')).toBe(true);
49+
});
50+
51+
it('should initialize with the current value', function() {
52+
input.value ='foo';
53+
54+
inputValueTracking.track(mockComponent);
55+
56+
var tracker = mockComponent._wrapperState.valueTracker;
57+
58+
expect(tracker.getValue()).toEqual('foo');
59+
});
60+
61+
it('should initialize with the current `checked`', function() {
62+
mockComponent._nativeNode = checkbox;
63+
checkbox.checked = true;
64+
inputValueTracking.track(mockComponent);
65+
66+
var tracker = mockComponent._wrapperState.valueTracker;
67+
68+
expect(tracker.getValue()).toEqual('true');
69+
});
70+
71+
it('should track value changes', function() {
72+
input.value ='foo';
73+
74+
inputValueTracking.track(mockComponent);
75+
76+
var tracker = mockComponent._wrapperState.valueTracker;
77+
78+
input.value ='bar';
79+
expect(tracker.getValue()).toEqual('bar');
80+
});
81+
82+
it('should tracked`checked` changes', function() {
83+
mockComponent._nativeNode = checkbox;
84+
checkbox.checked = true;
85+
inputValueTracking.track(mockComponent);
86+
87+
var tracker = mockComponent._wrapperState.valueTracker;
88+
89+
checkbox.checked = false;
90+
expect(tracker.getValue()).toEqual('false');
91+
});
92+
93+
it('should update value manually', function() {
94+
input.value ='foo';
95+
inputValueTracking.track(mockComponent);
96+
97+
var tracker = mockComponent._wrapperState.valueTracker;
98+
99+
tracker.setValue('bar');
100+
expect(tracker.getValue()).toEqual('bar');
101+
});
102+
103+
it('should coerce value to a string', function() {
104+
input.value ='foo';
105+
inputValueTracking.track(mockComponent);
106+
107+
var tracker = mockComponent._wrapperState.valueTracker;
108+
109+
tracker.setValue(500);
110+
expect(tracker.getValue()).toEqual('500');
111+
});
112+
113+
it('should update value if it changed and return result', function() {
114+
inputValueTracking.track(mockComponent);
115+
input.value ='foo';
116+
117+
var tracker = mockComponent._wrapperState.valueTracker;
118+
119+
expect(
120+
inputValueTracking.updateValueIfChanged(mockComponent)
121+
).toBe(false);
122+
123+
tracker.setValue('bar');
124+
125+
expect(
126+
inputValueTracking.updateValueIfChanged(mockComponent)
127+
).toBe(true);
128+
129+
expect(tracker.getValue()).toEqual('foo');
130+
});
131+
132+
it('should track value and return true when updating untracked instance', function() {
133+
input.value ='foo';
134+
135+
expect(
136+
inputValueTracking.updateValueIfChanged(mockComponent)
137+
)
138+
.toBe(true);
139+
140+
var tracker = mockComponent._wrapperState.valueTracker;
141+
expect(tracker.getValue()).toEqual('foo');
142+
});
143+
144+
it('should return tracker from node', function() {
145+
var node = ReactTestUtils.renderIntoDocument(<input type="text" defaultValue="foo" />);
146+
var tracker = inputValueTracking._getTrackerFromNode(node);
147+
expect(tracker.getValue()).toEqual('foo');
148+
});
149+
150+
it('should stop tracking', function() {
151+
inputValueTracking.track(mockComponent);
152+
153+
expect(
154+
mockComponent._wrapperState.hasOwnProperty('valueTracker')
155+
).toBe(true);
156+
157+
inputValueTracking.stopTracking(mockComponent);
158+
159+
expect(
160+
mockComponent._wrapperState.hasOwnProperty('valueTracker')
161+
).toBe(false);
162+
163+
expect(input.hasOwnProperty('value')).toBe(false);
164+
});
165+
});

0 commit comments

Comments
 (0)