Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81155 views
1
/**
2
* Copyright 2013-2014, 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
12
/*jslint evil: true */
13
14
"use strict";
15
16
require('mock-modules');
17
18
var React = require('React');
19
var ReactTestUtils = require('ReactTestUtils');
20
21
var reactComponentExpect = require('reactComponentExpect');
22
23
// Helpers
24
var testAllPermutations = function(testCases) {
25
for (var i = 0; i < testCases.length; i += 2) {
26
var renderWithChildren = testCases[i];
27
var expectedResultAfterRender = testCases[i + 1];
28
29
for (var j = 0; j < testCases.length; j += 2) {
30
var updateWithChildren = testCases[j];
31
var expectedResultAfterUpdate = testCases[j + 1];
32
33
var d = renderChildren(renderWithChildren);
34
expectChildren(d, expectedResultAfterRender);
35
36
updateChildren(d, updateWithChildren);
37
expectChildren(d, expectedResultAfterUpdate);
38
}
39
}
40
};
41
42
var renderChildren = function(children) {
43
return ReactTestUtils.renderIntoDocument(
44
<div>{children}</div>
45
);
46
};
47
48
var updateChildren = function(d, children) {
49
d.replaceProps({children: children});
50
};
51
52
var expectChildren = function(d, children) {
53
var textNode;
54
if (typeof children === 'string') {
55
textNode = d.getDOMNode().firstChild;
56
57
if (children === '') {
58
expect(textNode != null).toBe(false);
59
} else {
60
expect(textNode != null).toBe(true);
61
expect(textNode.nodeType).toBe(3);
62
expect(textNode.data).toBe('' + children);
63
}
64
} else {
65
expect(d.getDOMNode().childNodes.length).toBe(children.length);
66
67
for (var i = 0; i < children.length; i++) {
68
var child = children[i];
69
70
if (typeof child === 'string') {
71
reactComponentExpect(d)
72
.expectRenderedChildAt(i)
73
.toBeTextComponent()
74
.instance();
75
76
textNode = d.getDOMNode().childNodes[i].firstChild;
77
78
if (child === '') {
79
expect(textNode != null).toBe(false);
80
} else {
81
expect(textNode != null).toBe(true);
82
expect(textNode.nodeType).toBe(3);
83
expect(textNode.data).toBe('' + child);
84
}
85
} else {
86
var elementDOMNode =
87
reactComponentExpect(d)
88
.expectRenderedChildAt(i)
89
.toBeComponentOfType('div')
90
.instance()
91
.getDOMNode();
92
93
expect(elementDOMNode.tagName).toBe('DIV');
94
}
95
}
96
}
97
};
98
99
100
/**
101
* ReactMultiChild DOM integration test. In ReactDOM components, we make sure
102
* that single children that are strings are treated as "content" which is much
103
* faster to render and update.
104
*/
105
describe('ReactMultiChildText', function() {
106
it('should correctly handle all possible children for render and update', function() {
107
testAllPermutations([
108
// basic values
109
undefined, [],
110
null, [],
111
false, [],
112
true, [],
113
0, '0',
114
1.2, '1.2',
115
'', '',
116
'foo', 'foo',
117
118
[], [],
119
[undefined], [],
120
[null], [],
121
[false], [],
122
[true], [],
123
[0], ['0'],
124
[1.2], ['1.2'],
125
[''], [''],
126
['foo'], ['foo'],
127
[<div />], [<div />],
128
129
// two adjacent values
130
[true, 0], ['0'],
131
[0, 0], ['0', '0'],
132
[1.2, 0], ['1.2', '0'],
133
[0, ''], ['0', ''],
134
['foo', 0], ['foo', '0'],
135
[0, <div />], ['0', <div />],
136
137
[true, 1.2], ['1.2'],
138
[1.2, 0], ['1.2', '0'],
139
[1.2, 1.2], ['1.2', '1.2'],
140
[1.2, ''], ['1.2', ''],
141
['foo', 1.2], ['foo', '1.2'],
142
[1.2, <div />], ['1.2', <div />],
143
144
[true, ''], [''],
145
['', 0], ['', '0'],
146
[1.2, ''], ['1.2', ''],
147
['', ''], ['', ''],
148
['foo', ''], ['foo', ''],
149
['', <div />], ['', <div />],
150
151
[true, 'foo'], ['foo'],
152
['foo', 0], ['foo', '0'],
153
[1.2, 'foo'], ['1.2', 'foo'],
154
['foo', ''], ['foo', ''],
155
['foo', 'foo'], ['foo', 'foo'],
156
['foo', <div />], ['foo', <div />],
157
158
// values separated by an element
159
[true, <div />, true], [<div />],
160
[1.2, <div />, 1.2], ['1.2', <div />, '1.2'],
161
['', <div />, ''], ['', <div />, ''],
162
['foo', <div />, 'foo'], ['foo', <div />, 'foo'],
163
164
[true, 1.2, <div />, '', 'foo'], ['1.2', <div />, '', 'foo'],
165
[1.2, '', <div />, 'foo', true], ['1.2', '', <div />, 'foo'],
166
['', 'foo', <div />, true, 1.2], ['', 'foo', <div />, '1.2'],
167
168
[true, 1.2, '', <div />, 'foo', true, 1.2], ['1.2', '', <div />, 'foo', '1.2'],
169
['', 'foo', true, <div />, 1.2, '', 'foo'], ['', 'foo', <div />, '1.2', '', 'foo'],
170
171
// values inside arrays
172
[[true], [true]], [],
173
[[1.2], [1.2]], ['1.2', '1.2'],
174
[[''], ['']], ['', ''],
175
[['foo'], ['foo']], ['foo', 'foo'],
176
[[<div />], [<div />]], [<div />, <div />],
177
178
[[true, 1.2, <div />], '', 'foo'], ['1.2', <div />, '', 'foo'],
179
[1.2, '', [<div />, 'foo', true]], ['1.2', '', <div />, 'foo'],
180
['', ['foo', <div />, true], 1.2], ['', 'foo', <div />, '1.2'],
181
182
[true, [1.2, '', <div />, 'foo'], true, 1.2], ['1.2', '', <div />, 'foo', '1.2'],
183
['', 'foo', [true, <div />, 1.2, ''], 'foo'], ['', 'foo', <div />, '1.2', '', 'foo'],
184
185
// values inside objects
186
[{a: true}, {a: true}], [],
187
[{a: 1.2}, {a: 1.2}], ['1.2', '1.2'],
188
[{a: ''}, {a: ''}], ['', ''],
189
[{a: 'foo'}, {a: 'foo'}], ['foo', 'foo'],
190
[{a: <div />}, {a: <div />}], [<div />, <div />],
191
192
[{a: true, b: 1.2, c: <div />}, '', 'foo'], ['1.2', <div />, '', 'foo'],
193
[1.2, '', {a: <div />, b: 'foo', c: true}], ['1.2', '', <div />, 'foo'],
194
['', {a: 'foo', b: <div />, c: true}, 1.2], ['', 'foo', <div />, '1.2'],
195
196
[true, {a: 1.2, b: '', c: <div />, d: 'foo'}, true, 1.2], ['1.2', '', <div />, 'foo', '1.2'],
197
['', 'foo', {a: true, b: <div />, c: 1.2, d: ''}, 'foo'], ['', 'foo', <div />, '1.2', '', 'foo'],
198
199
// values inside elements
200
[<div>{true}{1.2}{<div />}</div>, '', 'foo'], [<div />, '', 'foo'],
201
[1.2, '', <div>{<div />}{'foo'}{true}</div>], ['1.2', '', <div />],
202
['', <div>{'foo'}{<div />}{true}</div>, 1.2], ['', <div />, '1.2'],
203
204
[true, <div>{1.2}{''}{<div />}{'foo'}</div>, true, 1.2], [<div />, '1.2'],
205
['', 'foo', <div>{true}{<div />}{1.2}{''}</div>, 'foo'], ['', 'foo', <div />, 'foo']
206
]);
207
});
208
209
it('should throw if rendering both HTML and children', function() {
210
expect(function() {
211
ReactTestUtils.renderIntoDocument(
212
<div dangerouslySetInnerHTML={{_html: 'abcdef'}}>ghjkl</div>
213
);
214
}).toThrow();
215
});
216
217
it('should render between nested components and inline children', function() {
218
var container = document.createElement('div');
219
React.render(<div><h1><span /><span /></h1></div>, container);
220
221
expect(function() {
222
React.render(<div><h1>A</h1></div>, container);
223
}).not.toThrow();
224
225
React.render(<div><h1><span /><span /></h1></div>, container);
226
227
expect(function() {
228
React.render(<div><h1>{['A']}</h1></div>, container);
229
}).not.toThrow();
230
231
React.render(<div><h1><span /><span /></h1></div>, container);
232
233
expect(function() {
234
React.render(<div><h1>{['A', 'B']}</h1></div>, container);
235
}).not.toThrow();
236
});
237
});
238
239