159
* utilities will suffice for testing purposes.
160
* @lends ReactTestUtils
161
*/
162
-const ReactTestUtils = {
163
- renderIntoDocument: function(element) {
164
- const div = document.createElement('div');
165
- // None of our tests actually require attaching the container to the
166
- // DOM, and doing so creates a mess that we rely on test isolation to
167
- // clean up, so we're going to stop honoring the name of this method
168
- // (and probably rename it eventually) if no problems arise.
169
- // document.documentElement.appendChild(div);
170
- return ReactDOM.render(element, div);
171
- },
172
-
173
- isElement: function(element) {
174
- return React.isValidElement(element);
175
- },
176
-
177
- isElementOfType: function(inst, convenienceConstructor) {
178
- return React.isValidElement(inst) && inst.type === convenienceConstructor;
179
- },
180
-
181
- isDOMComponent: function(inst) {
182
- return !!(inst && inst.nodeType === ELEMENT_NODE && inst.tagName);
183
- },
184
-
185
- isDOMComponentElement: function(inst) {
186
- return !!(inst && React.isValidElement(inst) && !!inst.tagName);
187
- },
188
-
189
- isCompositeComponent: function(inst) {
190
- if (ReactTestUtils.isDOMComponent(inst)) {
191
- // Accessing inst.setState warns; just return false as that'll be what
192
- // this returns when we have DOM nodes as refs directly
193
- return false;
194
- }
195
- return (
196
- inst != null &&
197
- typeof inst.render === 'function' &&
198
- typeof inst.setState === 'function'
199
- );
200
- },
162
+function renderIntoDocument(element) {
163
+ const div = document.createElement('div');
164
+ // None of our tests actually require attaching the container to the
165
+ // DOM, and doing so creates a mess that we rely on test isolation to
166
+ // clean up, so we're going to stop honoring the name of this method
167
+ // (and probably rename it eventually) if no problems arise.
168
+ // document.documentElement.appendChild(div);
169
+ return ReactDOM.render(element, div);
170
+}
171
202
- isCompositeComponentWithType: function(inst, type) {
203
- if (!ReactTestUtils.isCompositeComponent(inst)) {
204
- return false;
205
- }
206
- const internalInstance = getInstance(inst);
207
- const constructor = internalInstance.type;
208
- return constructor === type;
209
- },
210
-
211
- findAllInRenderedTree: function(inst, test) {
212
- validateClassInstance(inst, 'findAllInRenderedTree');
213
- if (!inst) {
214
- return [];
215
- }
216
- const internalInstance = getInstance(inst);
217
- return findAllInRenderedFiberTreeInternal(internalInstance, test);
218
- },
172
+function isElement(element) {
173
+ return React.isValidElement(element);
174
+}
175
220
- /**
221
- * Finds all instance of components in the rendered tree that are DOM
222
- * components with the class name matching `className`.
223
- * @return {array} an array of all the matches.
224
- */
225
- scryRenderedDOMComponentsWithClass: function(root, classNames) {
226
- validateClassInstance(root, 'scryRenderedDOMComponentsWithClass');
227
- return ReactTestUtils.findAllInRenderedTree(root, function(inst) {
228
- if (ReactTestUtils.isDOMComponent(inst)) {
229
- let className = inst.className;
230
- if (typeof className !== 'string') {
231
- // SVG, probably.
232
- className = inst.getAttribute('class') || '';
233
- }
234
- const classList = className.split(/\s+/);
235
-
236
- if (!Array.isArray(classNames)) {
237
- invariant(
238
- classNames !== undefined,
239
- 'TestUtils.scryRenderedDOMComponentsWithClass expects a ' +
240
- 'className as a second argument.',
241
- );
242
- classNames = classNames.split(/\s+/);
243
- }
244
- return classNames.every(function(name) {
245
- return classList.indexOf(name) !== -1;
246
- });
247
- }
248
- return false;
249
- });
250
- },
176
+function isElementOfType(inst, convenienceConstructor) {
177
+ return React.isValidElement(inst) && inst.type === convenienceConstructor;
178
+}
179
252
- /**
253
- * Like scryRenderedDOMComponentsWithClass but expects there to be one result,
254
- * and returns that one result, or throws exception if there is any other
255
- * number of matches besides one.
256
- * @return {!ReactDOMComponent} The one match.
257
- */
258
- findRenderedDOMComponentWithClass: function(root, className) {
259
- validateClassInstance(root, 'findRenderedDOMComponentWithClass');
260
- const all = ReactTestUtils.scryRenderedDOMComponentsWithClass(
261
- root,
262
- className,
263
- );
264
- if (all.length !== 1) {
265
- throw new Error(
266
- 'Did not find exactly one match (found: ' +
267
- all.length +
268
- ') ' +
269
- 'for class:' +
270
- className,
271
- );
272
- }
273
- return all[0];
274
- },
180
+function isDOMComponent(inst) {
181
+ return !!(inst && inst.nodeType === ELEMENT_NODE && inst.tagName);
182
+}
183
276
- /**
277
- * Finds all instance of components in the rendered tree that are DOM
278
- * components with the tag name matching `tagName`.
279
- * @return {array} an array of all the matches.
280
- */
281
- scryRenderedDOMComponentsWithTag: function(root, tagName) {
282
- validateClassInstance(root, 'scryRenderedDOMComponentsWithTag');
283
- return ReactTestUtils.findAllInRenderedTree(root, function(inst) {
284
- return (
285
- ReactTestUtils.isDOMComponent(inst) &&
286
- inst.tagName.toUpperCase() === tagName.toUpperCase()
287
- );
288
- });
289
- },
184
+function isDOMComponentElement(inst) {
185
+ return !!(inst && React.isValidElement(inst) && !!inst.tagName);
186
+}
187
291
- /**
292
- * Like scryRenderedDOMComponentsWithTag but expects there to be one result,
293
- * and returns that one result, or throws exception if there is any other
294
- * number of matches besides one.
295
- * @return {!ReactDOMComponent} The one match.
296
- */
297
- findRenderedDOMComponentWithTag: function(root, tagName) {
298
- validateClassInstance(root, 'findRenderedDOMComponentWithTag');
299
- const all = ReactTestUtils.scryRenderedDOMComponentsWithTag(root, tagName);
300
- if (all.length !== 1) {
301
- throw new Error(
302
- 'Did not find exactly one match (found: ' +
303
- all.length +
304
- ') ' +
305
- 'for tag:' +
306
- tagName,
307
- );
308
- }
309
- return all[0];
310
- },
188
+function isCompositeComponent(inst) {
189
+ if (isDOMComponent(inst)) {
190
+ // Accessing inst.setState warns; just return false as that'll be what
191
+ // this returns when we have DOM nodes as refs directly
192
+ return false;
193
+ }
194
+ return (
195
+ inst != null &&
196
+ typeof inst.render === 'function' &&
197
+ typeof inst.setState === 'function'
198
+ );
199
+}
200
312
- /**
313
- * Finds all instances of components with type equal to `componentType`.
314
- * @return {array} an array of all the matches.
315
- */
316
- scryRenderedComponentsWithType: function(root, componentType) {
317
- validateClassInstance(root, 'scryRenderedComponentsWithType');
318
- return ReactTestUtils.findAllInRenderedTree(root, function(inst) {
319
- return ReactTestUtils.isCompositeComponentWithType(inst, componentType);
320
- });
321
- },
201
+function isCompositeComponentWithType(inst, type) {
202
+ if (!isCompositeComponent(inst)) {
203
+ return false;
204
+ }
205
+ const internalInstance = getInstance(inst);
206
+ const constructor = internalInstance.type;
207
+ return constructor === type;
208
+}
209
323
- /**
324
- * Same as `scryRenderedComponentsWithType` but expects there to be one result
325
- * and returns that one result, or throws exception if there is any other
326
- * number of matches besides one.
327
- * @return {!ReactComponent} The one match.
328
- */
329
- findRenderedComponentWithType: function(root, componentType) {
330
- validateClassInstance(root, 'findRenderedComponentWithType');
331
- const all = ReactTestUtils.scryRenderedComponentsWithType(
332
- root,
333
- componentType,
334
- );
335
- if (all.length !== 1) {
336
- throw new Error(
337
- 'Did not find exactly one match (found: ' +
338
- all.length +
339
- ') ' +
340
- 'for componentType:' +
341
- componentType,
342
- );
343
- }
344
- return all[0];
345
- },
210
+function findAllInRenderedTree(inst, test) {
211
+ validateClassInstance(inst, 'findAllInRenderedTree');
212
+ if (!inst) {
213
+ return [];
214
+ }
215
+ const internalInstance = getInstance(inst);
216
+ return findAllInRenderedFiberTreeInternal(internalInstance, test);
217
+}
218
347
- /**
348
- * Pass a mocked component module to this method to augment it with
349
- * useful methods that allow it to be used as a dummy React component.
350
- * Instead of rendering as usual, the component will become a simple
351
- * <div> containing any provided children.
352
- *
353
- * @param {object} module the mock function object exported from a
354
- * module that defines the component to be mocked
355
- * @param {?string} mockTagName optional dummy root tag name to return
356
- * from render method (overrides
357
- * module.mockTagName if provided)
358
- * @return {object} the ReactTestUtils object (for chaining)
359
- */
360
- mockComponent: function(module, mockTagName) {
361
- if (__DEV__) {
362
- if (!hasWarnedAboutDeprecatedMockComponent) {
363
- hasWarnedAboutDeprecatedMockComponent = true;
364
- console.warn(
365
- 'ReactTestUtils.mockComponent() is deprecated. ' +
366
- 'Use shallow rendering or jest.mock() instead.\n\n' +
367
- 'See https://fb.me/test-utils-mock-component for more information.',
219
+/**
220
+ * Finds all instance of components in the rendered tree that are DOM
221
+ * components with the class name matching `className`.
222
+ * @return {array} an array of all the matches.
223
+ */
224
+function scryRenderedDOMComponentsWithClass(root, classNames) {
225
+ validateClassInstance(root, 'scryRenderedDOMComponentsWithClass');
226
+ return findAllInRenderedTree(root, function(inst) {
227
+ if (isDOMComponent(inst)) {
228
+ let className = inst.className;
229
+ if (typeof className !== 'string') {
230
+ // SVG, probably.
231
+ className = inst.getAttribute('class') || '';
232
+ }
233
+ const classList = className.split(/\s+/);
234
+
235
+ if (!Array.isArray(classNames)) {
236
+ invariant(
237
+ classNames !== undefined,
238
+ 'TestUtils.scryRenderedDOMComponentsWithClass expects a ' +
239
+ 'className as a second argument.',
240
);
241
+ classNames = classNames.split(/\s+/);
242
}
243
+ return classNames.every(function(name) {
244
+ return classList.indexOf(name) !== -1;
245
+ });
246
}
247
+ return false;
248
+ });
249
+}
250
372
- mockTagName = mockTagName || module.mockTagName || 'div';
251
+/**
252
+ * Like scryRenderedDOMComponentsWithClass but expects there to be one result,
253
+ * and returns that one result, or throws exception if there is any other
254
+ * number of matches besides one.
255
+ * @return {!ReactDOMComponent} The one match.
256
+ */
257
+function findRenderedDOMComponentWithClass(root, className) {
258
+ validateClassInstance(root, 'findRenderedDOMComponentWithClass');
259
+ const all = scryRenderedDOMComponentsWithClass(root, className);
260
+ if (all.length !== 1) {
261
+ throw new Error(
262
+ 'Did not find exactly one match (found: ' +
263
+ all.length +
264
+ ') ' +
265
+ 'for class:' +
266
+ className,
267
+ );
268
+ }
269
+ return all[0];
270
+}
271
374
- module.prototype.render.mockImplementation(function() {
375
- return React.createElement(mockTagName, null, this.props.children);
376
- });
272
+/**
273
+ * Finds all instance of components in the rendered tree that are DOM
274
+ * components with the tag name matching `tagName`.
275
+ * @return {array} an array of all the matches.
276
+ */
277
+function scryRenderedDOMComponentsWithTag(root, tagName) {
278
+ validateClassInstance(root, 'scryRenderedDOMComponentsWithTag');
279
+ return findAllInRenderedTree(root, function(inst) {
280
+ return (
281
+ isDOMComponent(inst) &&
282
+ inst.tagName.toUpperCase() === tagName.toUpperCase()
283
+ );
284
+ });
285
+}
286
378
- return this;
379
- },
287
+/**
288
+ * Like scryRenderedDOMComponentsWithTag but expects there to be one result,
289
+ * and returns that one result, or throws exception if there is any other
290
+ * number of matches besides one.
291
+ * @return {!ReactDOMComponent} The one match.
292
+ */
293
+function findRenderedDOMComponentWithTag(root, tagName) {
294
+ validateClassInstance(root, 'findRenderedDOMComponentWithTag');
295
+ const all = scryRenderedDOMComponentsWithTag(root, tagName);
296
+ if (all.length !== 1) {
297
+ throw new Error(
298
+ 'Did not find exactly one match (found: ' +
299
+ all.length +
300
+ ') ' +
301
+ 'for tag:' +
302
+ tagName,
303
+ );
304
+ }
305
+ return all[0];
306
+}
307
381
- nativeTouchData: function(x, y) {
382
- return {
383
- touches: [{pageX: x, pageY: y}],
384
- };
385
- },
308
+/**
309
+ * Finds all instances of components with type equal to `componentType`.
310
+ * @return {array} an array of all the matches.
311
+ */
312
+function scryRenderedComponentsWithType(root, componentType) {
313
+ validateClassInstance(root, 'scryRenderedComponentsWithType');
314
+ return findAllInRenderedTree(root, function(inst) {
315
+ return isCompositeComponentWithType(inst, componentType);
316
+ });
317
+}
318
387
- Simulate: null,
388
- SimulateNative: {},
319
+/**
320
+ * Same as `scryRenderedComponentsWithType` but expects there to be one result
321
+ * and returns that one result, or throws exception if there is any other
322
+ * number of matches besides one.
323
+ * @return {!ReactComponent} The one match.
324
+ */
325
+function findRenderedComponentWithType(root, componentType) {
326
+ validateClassInstance(root, 'findRenderedComponentWithType');
327
+ const all = scryRenderedComponentsWithType(root, componentType);
328
+ if (all.length !== 1) {
329
+ throw new Error(
330
+ 'Did not find exactly one match (found: ' +
331
+ all.length +
332
+ ') ' +
333
+ 'for componentType:' +
334
+ componentType,
335
+ );
336
+ }
337
+ return all[0];
338
+}
339
390
- act,
391
-};
340
+/**
341
+ * Pass a mocked component module to this method to augment it with
342
+ * useful methods that allow it to be used as a dummy React component.
343
+ * Instead of rendering as usual, the component will become a simple
344
+ * <div> containing any provided children.
345
+ *
346
+ * @param {object} module the mock function object exported from a
347
+ * module that defines the component to be mocked
348
+ * @param {?string} mockTagName optional dummy root tag name to return
349
+ * from render method (overrides
350
+ * module.mockTagName if provided)
351
+ * @return {object} the ReactTestUtils object (for chaining)
352
+ */
353
+function mockComponent(module, mockTagName) {
354
+ if (__DEV__) {
355
+ if (!hasWarnedAboutDeprecatedMockComponent) {
356
+ hasWarnedAboutDeprecatedMockComponent = true;
357
+ console.warn(
358
+ 'ReactTestUtils.mockComponent() is deprecated. ' +
359
+ 'Use shallow rendering or jest.mock() instead.\n\n' +
360
+ 'See https://fb.me/test-utils-mock-component for more information.',
361
+ );
362
+ }
363
+ }
364
+
365
+ mockTagName = mockTagName || module.mockTagName || 'div';
366
+
367
+ module.prototype.render.mockImplementation(function() {
368
+ return React.createElement(mockTagName, null, this.props.children);
369
+ });
370
+
371
+ return this;
372
+}
373
+
374
+function nativeTouchData(x, y) {
375
+ return {
376
+ touches: [{pageX: x, pageY: y}],
377
+ };
378
+}
379
+
380
+const Simulate = {};
381
+const SimulateNative = {};
382
383
/**
384
* Exports:
385
*
396
- * - `ReactTestUtils.Simulate.click(Element)`
397
- * - `ReactTestUtils.Simulate.mouseMove(Element)`
398
- * - `ReactTestUtils.Simulate.change(Element)`
386
+ * - `Simulate.click(Element)`
387
+ * - `Simulate.mouseMove(Element)`
388
+ * - `Simulate.change(Element)`
389
* - ... (All keys from event plugin `eventTypes` objects)
390
*/
391
function makeSimulator(eventType) {
397
'Note that TestUtils.Simulate will not work if you are using shallow rendering.',
398
);
399
invariant(
410
- !ReactTestUtils.isCompositeComponent(domNode),
400
+ !isCompositeComponent(domNode),
401
'TestUtils.Simulate expected a DOM node as the first argument but received ' +
402
'a component instance. Pass the DOM node you wish to simulate the event on instead.',
403
);
440
}
441
442
function buildSimulators() {
453
- ReactTestUtils.Simulate = {};
454
-
443
let eventType;
444
for (eventType in eventNameDispatchConfigs) {
445
/**
446
* @param {!Element|ReactDOMComponent} domComponentOrNode
447
* @param {?object} eventData Fake event data to use in SyntheticEvent.
448
*/
461
- ReactTestUtils.Simulate[eventType] = makeSimulator(eventType);
449
+ Simulate[eventType] = makeSimulator(eventType);
450
}
451
}
452
455
/**
456
* Exports:
457
*
470
- * - `ReactTestUtils.SimulateNative.click(Element/ReactDOMComponent)`
471
- * - `ReactTestUtils.SimulateNative.mouseMove(Element/ReactDOMComponent)`
472
- * - `ReactTestUtils.SimulateNative.mouseIn/ReactDOMComponent)`
473
- * - `ReactTestUtils.SimulateNative.mouseOut(Element/ReactDOMComponent)`
458
+ * - `SimulateNative.click(Element/ReactDOMComponent)`
459
+ * - `SimulateNative.mouseMove(Element/ReactDOMComponent)`
460
+ * - `SimulateNative.mouseIn/ReactDOMComponent)`
461
+ * - `SimulateNative.mouseOut(Element/ReactDOMComponent)`
462
* - ... (All keys from `BrowserEventConstants.topLevelTypes`)
463
*
464
* Note: Top level event types are a subset of the entire set of handler types
465
* (which include a broader set of "synthetic" events). For example, onDragDone
466
* is a synthetic event. Except when testing an event plugin or React's event
479
- * handling code specifically, you probably want to use ReactTestUtils.Simulate
467
+ * handling code specifically, you probably want to use Simulate
468
* to dispatch synthetic events.
469
*/
470
472
return function(domComponentOrNode, nativeEventData) {
473
const fakeNativeEvent = new Event(eventType);
474
Object.assign(fakeNativeEvent, nativeEventData);
487
- if (ReactTestUtils.isDOMComponent(domComponentOrNode)) {
475
+ if (isDOMComponent(domComponentOrNode)) {
476
simulateNativeEventOnDOMComponent(
477
topLevelType,
478
domComponentOrNode,
564
* @param {!Element|ReactDOMComponent} domComponentOrNode
565
* @param {?Event} nativeEventData Fake native event to use in SyntheticEvent.
566
*/
579
- ReactTestUtils.SimulateNative[eventType] = makeNativeSimulator(
580
- eventType,
581
- topLevelType,
582
- );
567
+ SimulateNative[eventType] = makeNativeSimulator(eventType, topLevelType);
568
});
569
585
-export default ReactTestUtils;
570
+export {
571
+ renderIntoDocument,
572
+ isElement,
573
+ isElementOfType,
574
+ isDOMComponent,
575
+ isDOMComponentElement,
576
+ isCompositeComponent,
577
+ isCompositeComponentWithType,
578
+ findAllInRenderedTree,
579
+ scryRenderedDOMComponentsWithClass,
580
+ findRenderedDOMComponentWithClass,
581
+ scryRenderedDOMComponentsWithTag,
582
+ findRenderedDOMComponentWithTag,
583
+ scryRenderedComponentsWithType,
584
+ findRenderedComponentWithType,
585
+ mockComponent,
586
+ nativeTouchData,
587
+ Simulate,
588
+ SimulateNative,
589
+ act,
590
+};