14
14
describe ( 'ReactChildren' , function ( ) {
15
15
var ReactChildren ;
16
16
var React ;
17
+ var ReactFragment ;
17
18
18
19
beforeEach ( function ( ) {
19
20
ReactChildren = require ( 'ReactChildren' ) ;
20
21
React = require ( 'React' ) ;
22
+ ReactFragment = require ( 'ReactFragment' ) ;
21
23
} ) ;
22
24
25
+ function frag ( obj ) {
26
+ return ReactFragment . create ( obj ) ;
27
+ }
28
+
29
+ function nthChild ( mappedChildren , n ) {
30
+ var result = null ;
31
+ ReactChildren . forEach ( mappedChildren , function ( child , index ) {
32
+ if ( index === n ) {
33
+ result = child ;
34
+ }
35
+ } ) ;
36
+ return result ;
37
+ }
38
+
39
+ function keyOfNthChild ( mappedChildren , n ) {
40
+ return Object . keys ( ReactFragment . extract ( mappedChildren ) ) [ n ] ;
41
+ }
23
42
24
43
it ( 'should support identity for simple' , function ( ) {
25
44
var callback = jasmine . createSpy ( ) . andCallFake ( function ( kid , index ) {
@@ -37,7 +56,7 @@ describe('ReactChildren', function() {
37
56
callback . reset ( ) ;
38
57
var mappedChildren = ReactChildren . map ( instance . props . children , callback ) ;
39
58
expect ( callback ) . toHaveBeenCalledWith ( simpleKid , 0 ) ;
40
- expect ( mappedChildren [ Object . keys ( mappedChildren ) [ 0 ] ] ) . toBe ( simpleKid ) ;
59
+ expect ( nthChild ( mappedChildren , 0 ) ) . toBe ( simpleKid ) ;
41
60
} ) ;
42
61
43
62
it ( 'should treat single arrayless child as being in array' , function ( ) {
@@ -52,7 +71,7 @@ describe('ReactChildren', function() {
52
71
callback . reset ( ) ;
53
72
var mappedChildren = ReactChildren . map ( instance . props . children , callback ) ;
54
73
expect ( callback ) . toHaveBeenCalledWith ( simpleKid , 0 ) ;
55
- expect ( mappedChildren [ Object . keys ( mappedChildren ) [ 0 ] ] ) . toBe ( simpleKid ) ;
74
+ expect ( nthChild ( mappedChildren , 0 ) ) . toBe ( simpleKid ) ;
56
75
} ) ;
57
76
58
77
it ( 'should treat single child in array as expected' , function ( ) {
@@ -67,7 +86,7 @@ describe('ReactChildren', function() {
67
86
callback . reset ( ) ;
68
87
var mappedChildren = ReactChildren . map ( instance . props . children , callback ) ;
69
88
expect ( callback ) . toHaveBeenCalledWith ( simpleKid , 0 ) ;
70
- expect ( mappedChildren [ Object . keys ( mappedChildren ) [ 0 ] ] ) . toBe ( simpleKid ) ;
89
+ expect ( nthChild ( mappedChildren , 0 ) ) . toBe ( simpleKid ) ;
71
90
} ) ;
72
91
73
92
it ( 'should pass key to returned component' , function ( ) {
@@ -80,11 +99,10 @@ describe('ReactChildren', function() {
80
99
var instance = < div > { simpleKid } </ div > ;
81
100
var mappedChildren = ReactChildren . map ( instance . props . children , mapFn ) ;
82
101
83
- var mappedKeys = Object . keys ( mappedChildren ) ;
84
- expect ( mappedKeys . length ) . toBe ( 1 ) ;
85
- expect ( mappedChildren [ mappedKeys [ 0 ] ] ) . not . toBe ( simpleKid ) ;
86
- expect ( mappedChildren [ mappedKeys [ 0 ] ] . props . children ) . toBe ( simpleKid ) ;
87
- expect ( mappedKeys [ 0 ] ) . toBe ( '.$simple' ) ;
102
+ expect ( ReactChildren . count ( mappedChildren ) ) . toBe ( 1 ) ;
103
+ expect ( nthChild ( mappedChildren , 0 ) ) . not . toBe ( simpleKid ) ;
104
+ expect ( nthChild ( mappedChildren , 0 ) . props . children ) . toBe ( simpleKid ) ;
105
+ expect ( keyOfNthChild ( mappedChildren , 0 ) ) . toBe ( '.$simple' ) ;
88
106
} ) ;
89
107
90
108
it ( 'should invoke callback with the right context' , function ( ) {
@@ -94,7 +112,8 @@ describe('ReactChildren', function() {
94
112
return this ;
95
113
} ;
96
114
97
- var scopeTester = { } ;
115
+ // TODO: Use an object to test, after non-object fragments has fully landed.
116
+ var scopeTester = 'scope tester' ;
98
117
99
118
var simpleKid = < span key = "simple" /> ;
100
119
var instance = < div > { simpleKid } </ div > ;
@@ -104,9 +123,8 @@ describe('ReactChildren', function() {
104
123
var mappedChildren =
105
124
ReactChildren . map ( instance . props . children , callback , scopeTester ) ;
106
125
107
- var mappedKeys = Object . keys ( mappedChildren ) ;
108
- expect ( mappedKeys . length ) . toBe ( 1 ) ;
109
- expect ( mappedChildren [ mappedKeys [ 0 ] ] ) . toBe ( scopeTester ) ;
126
+ expect ( ReactChildren . count ( mappedChildren ) ) . toBe ( 1 ) ;
127
+ expect ( nthChild ( mappedChildren , 0 ) ) . toBe ( scopeTester ) ;
110
128
} ) ;
111
129
112
130
it ( 'should be called for each child' , function ( ) {
@@ -149,28 +167,33 @@ describe('ReactChildren', function() {
149
167
150
168
var mappedChildren =
151
169
ReactChildren . map ( instance . props . children , callback ) ;
152
- var mappedKeys = Object . keys ( mappedChildren ) ;
153
170
expect ( callback . calls . length ) . toBe ( 5 ) ;
154
- expect ( mappedKeys . length ) . toBe ( 5 ) ;
171
+ expect ( ReactChildren . count ( mappedChildren ) ) . toBe ( 5 ) ;
155
172
// Keys default to indices.
156
- expect ( mappedKeys ) . toEqual (
173
+ expect ( [
174
+ keyOfNthChild ( mappedChildren , 0 ) ,
175
+ keyOfNthChild ( mappedChildren , 1 ) ,
176
+ keyOfNthChild ( mappedChildren , 2 ) ,
177
+ keyOfNthChild ( mappedChildren , 3 ) ,
178
+ keyOfNthChild ( mappedChildren , 4 )
179
+ ] ) . toEqual (
157
180
[ '.$keyZero' , '.1' , '.$keyTwo' , '.3' , '.$keyFour' ]
158
181
) ;
159
182
160
183
expect ( callback ) . toHaveBeenCalledWith ( zero , 0 ) ;
161
- expect ( mappedChildren [ mappedKeys [ 0 ] ] ) . toBe ( zeroMapped ) ;
184
+ expect ( nthChild ( mappedChildren , 0 ) ) . toBe ( zeroMapped ) ;
162
185
163
186
expect ( callback ) . toHaveBeenCalledWith ( one , 1 ) ;
164
- expect ( mappedChildren [ mappedKeys [ 1 ] ] ) . toBe ( oneMapped ) ;
187
+ expect ( nthChild ( mappedChildren , 1 ) ) . toBe ( oneMapped ) ;
165
188
166
189
expect ( callback ) . toHaveBeenCalledWith ( two , 2 ) ;
167
- expect ( mappedChildren [ mappedKeys [ 2 ] ] ) . toBe ( twoMapped ) ;
190
+ expect ( nthChild ( mappedChildren , 2 ) ) . toBe ( twoMapped ) ;
168
191
169
192
expect ( callback ) . toHaveBeenCalledWith ( three , 3 ) ;
170
- expect ( mappedChildren [ mappedKeys [ 3 ] ] ) . toBe ( threeMapped ) ;
193
+ expect ( nthChild ( mappedChildren , 3 ) ) . toBe ( threeMapped ) ;
171
194
172
195
expect ( callback ) . toHaveBeenCalledWith ( four , 4 ) ;
173
- expect ( mappedChildren [ mappedKeys [ 4 ] ] ) . toBe ( fourMapped ) ;
196
+ expect ( nthChild ( mappedChildren , 4 ) ) . toBe ( fourMapped ) ;
174
197
} ) ;
175
198
176
199
@@ -204,11 +227,11 @@ describe('ReactChildren', function() {
204
227
205
228
var instance = (
206
229
< div > {
207
- [ {
230
+ [ frag ( {
208
231
firstHalfKey : [ zero , one , two ] ,
209
232
secondHalfKey : [ three , four ] ,
210
233
keyFive : five
211
- } ]
234
+ } ) ]
212
235
} </ div >
213
236
) ;
214
237
@@ -222,11 +245,17 @@ describe('ReactChildren', function() {
222
245
callback . reset ( ) ;
223
246
224
247
var mappedChildren = ReactChildren . map ( instance . props . children , callback ) ;
225
- var mappedKeys = Object . keys ( mappedChildren ) ;
226
248
expect ( callback . calls . length ) . toBe ( 6 ) ;
227
- expect ( mappedKeys . length ) . toBe ( 6 ) ;
249
+ expect ( ReactChildren . count ( mappedChildren ) ) . toBe ( 6 ) ;
228
250
// Keys default to indices.
229
- expect ( mappedKeys ) . toEqual ( [
251
+ expect ( [
252
+ keyOfNthChild ( mappedChildren , 0 ) ,
253
+ keyOfNthChild ( mappedChildren , 1 ) ,
254
+ keyOfNthChild ( mappedChildren , 2 ) ,
255
+ keyOfNthChild ( mappedChildren , 3 ) ,
256
+ keyOfNthChild ( mappedChildren , 4 ) ,
257
+ keyOfNthChild ( mappedChildren , 5 )
258
+ ] ) . toEqual ( [
230
259
'.0:$firstHalfKey:0:$keyZero' ,
231
260
'.0:$firstHalfKey:0:1' ,
232
261
'.0:$firstHalfKey:0:$keyTwo' ,
@@ -236,22 +265,22 @@ describe('ReactChildren', function() {
236
265
] ) ;
237
266
238
267
expect ( callback ) . toHaveBeenCalledWith ( zero , 0 ) ;
239
- expect ( mappedChildren [ mappedKeys [ 0 ] ] ) . toBe ( zeroMapped ) ;
268
+ expect ( nthChild ( mappedChildren , 0 ) ) . toBe ( zeroMapped ) ;
240
269
241
270
expect ( callback ) . toHaveBeenCalledWith ( one , 1 ) ;
242
- expect ( mappedChildren [ mappedKeys [ 1 ] ] ) . toBe ( oneMapped ) ;
271
+ expect ( nthChild ( mappedChildren , 1 ) ) . toBe ( oneMapped ) ;
243
272
244
273
expect ( callback ) . toHaveBeenCalledWith ( two , 2 ) ;
245
- expect ( mappedChildren [ mappedKeys [ 2 ] ] ) . toBe ( twoMapped ) ;
274
+ expect ( nthChild ( mappedChildren , 2 ) ) . toBe ( twoMapped ) ;
246
275
247
276
expect ( callback ) . toHaveBeenCalledWith ( three , 3 ) ;
248
- expect ( mappedChildren [ mappedKeys [ 3 ] ] ) . toBe ( threeMapped ) ;
277
+ expect ( nthChild ( mappedChildren , 3 ) ) . toBe ( threeMapped ) ;
249
278
250
279
expect ( callback ) . toHaveBeenCalledWith ( four , 4 ) ;
251
- expect ( mappedChildren [ mappedKeys [ 4 ] ] ) . toBe ( fourMapped ) ;
280
+ expect ( nthChild ( mappedChildren , 4 ) ) . toBe ( fourMapped ) ;
252
281
253
282
expect ( callback ) . toHaveBeenCalledWith ( five , 5 ) ;
254
- expect ( mappedChildren [ mappedKeys [ 5 ] ] ) . toBe ( fiveMapped ) ;
283
+ expect ( nthChild ( mappedChildren , 5 ) ) . toBe ( fiveMapped ) ;
255
284
} ) ;
256
285
257
286
it ( 'should retain key across two mappings' , function ( ) {
@@ -325,7 +354,8 @@ describe('ReactChildren', function() {
325
354
var mapped = ReactChildren . map ( instance . props . children , mapFn ) ;
326
355
327
356
expect ( console . warn . calls . length ) . toEqual ( 1 ) ;
328
- expect ( mapped ) . toEqual ( { '.$something' : zero } ) ;
357
+ expect ( nthChild ( mapped , 0 ) ) . toBe ( zero ) ;
358
+ expect ( keyOfNthChild ( mapped , 0 ) ) . toBe ( '.$something' ) ;
329
359
} ) ;
330
360
331
361
it ( 'should return 0 for null children' , function ( ) {
@@ -380,14 +410,49 @@ describe('ReactChildren', function() {
380
410
381
411
var instance = (
382
412
< div > {
383
- [ {
413
+ [ frag ( {
384
414
firstHalfKey : [ zero , one , two ] ,
385
415
secondHalfKey : [ three , four ] ,
386
416
keyFive : five
387
- } ]
417
+ } ) ]
388
418
} </ div >
389
419
) ;
390
420
var numberOfChildren = ReactChildren . count ( instance . props . children ) ;
391
421
expect ( numberOfChildren ) . toBe ( 6 ) ;
392
422
} ) ;
423
+
424
+ it ( 'should warn if a fragment is used without the wrapper' , function ( ) {
425
+ spyOn ( console , 'warn' ) ;
426
+ var child = React . createElement ( 'span' ) ;
427
+ ReactChildren . forEach ( { a : child , b : child } , function ( c ) {
428
+ expect ( c ) . toBe ( child ) ;
429
+ } ) ;
430
+ expect ( console . warn . calls . length ) . toBe ( 1 ) ;
431
+ expect ( console . warn . calls [ 0 ] . args [ 0 ] ) . toContain ( 'use of a keyed object' ) ;
432
+ } ) ;
433
+
434
+ it ( 'should warn if a fragment is accessed' , function ( ) {
435
+ spyOn ( console , 'warn' ) ;
436
+ var child = React . createElement ( 'span' ) ;
437
+ var frag = ReactChildren . map ( [ child , child ] , function ( c ) {
438
+ return c ;
439
+ } ) ;
440
+ for ( var key in frag ) {
441
+ frag [ key ] ;
442
+ break ;
443
+ }
444
+ expect ( console . warn . calls . length ) . toBe ( 1 ) ;
445
+ expect ( console . warn . calls [ 0 ] . args [ 0 ] ) . toContain ( 'is an opaque type' ) ;
446
+
447
+ var frag2 = ReactChildren . map ( [ child , child ] , function ( c ) {
448
+ return c ;
449
+ } ) ;
450
+ for ( var key in frag2 ) {
451
+ frag2 [ key ] = 123 ;
452
+ break ;
453
+ }
454
+ expect ( console . warn . calls . length ) . toBe ( 2 ) ;
455
+ expect ( console . warn . calls [ 1 ] . args [ 0 ] ) . toContain ( 'is an immutable opaque' ) ;
456
+ } ) ;
457
+
393
458
} ) ;
0 commit comments