Refactor ShallowRenderer (#7739)
* Separate ReactShallowRenderer from TestUtils * Use ES classes to ReactShallowRenderer
Toru Kobayashi committed
Oct 4, 2016 at 20:28 UTC
85b0377bfd1b7f3598b7ae5ccea3234a6453a0eb
2 files changed
+140
-136
src/test/ReactShallowRenderer.js
new
+139
@@ -0,0 +1,139 @@
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
+ * @providesModule ReactShallowRenderer
10
+ */
11
+
12
+'use strict';
13
+
14
+var React = require('React');
15
+var ReactDefaultInjection = require('ReactDefaultInjection');
16
+var ReactCompositeComponent = require('ReactCompositeComponent');
17
+var ReactReconciler = require('ReactReconciler');
18
+var ReactUpdates = require('ReactUpdates');
19
+
20
+var emptyObject = require('emptyObject');
21
+var invariant = require('invariant');
22
+
23
+var nextDebugID = 1;
24
+
25
+class NoopInternalComponent {
26
+ constructor(element) {
27
+ this._renderedOutput = element;
28
+ this._currentElement = element;
29
+
30
+ if (__DEV__) {
31
+ this._debugID = nextDebugID++;
32
+ }
33
+ }
34
+ mountComponent() {}
35
+ receiveComponent(element) {
36
+ this._renderedOutput = element;
37
+ this._currentElement = element;
38
+ }
39
+ unmountComponent() {}
40
+ getHostNode() {
41
+ return undefined;
42
+ }
43
+ getPublicInstance() {
44
+ return null;
45
+ }
46
+}
47
+
48
+var ShallowComponentWrapper = function(element) {
49
+ // TODO: Consolidate with instantiateReactComponent
50
+ if (__DEV__) {
51
+ this._debugID = nextDebugID++;
52
+ }
53
+
54
+ this.construct(element);
55
+};
56
+Object.assign(
57
+ ShallowComponentWrapper.prototype,
58
+ ReactCompositeComponent, {
59
+ _constructComponent:
60
+ ReactCompositeComponent._constructComponentWithoutOwner,
61
+ _instantiateReactComponent: function(element) {
62
+ return new NoopInternalComponent(element);
63
+ },
64
+ _replaceNodeWithMarkup: function() {},
65
+ _renderValidatedComponent:
66
+ ReactCompositeComponent
67
+ ._renderValidatedComponentWithoutOwnerOrContext,
68
+ }
69
+);
70
+
71
+function _batchedRender(renderer, element, context) {
72
+ var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(true);
73
+ renderer._render(element, transaction, context);
74
+ ReactUpdates.ReactReconcileTransaction.release(transaction);
75
+}
76
+
77
+class ReactShallowRenderer {
78
+ _instance = null;
79
+ getMountedInstance() {
80
+ return this._instance ? this._instance._instance : null;
81
+ }
82
+ render(element, context) {
83
+ // Ensure we've done the default injections. This might not be true in the
84
+ // case of a simple test that only requires React and the TestUtils in
85
+ // conjunction with an inline-requires transform.
86
+ ReactDefaultInjection.inject();
87
+
88
+ invariant(
89
+ React.isValidElement(element),
90
+ 'ReactShallowRenderer render(): Invalid component element.%s',
91
+ typeof element === 'function' ?
92
+ ' Instead of passing a component class, make sure to instantiate ' +
93
+ 'it by passing it to React.createElement.' :
94
+ ''
95
+ );
96
+ invariant(
97
+ typeof element.type !== 'string',
98
+ 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
99
+ 'components, not primitives (%s). Instead of calling `.render(el)` and ' +
100
+ 'inspecting the rendered output, look at `el.props` directly instead.',
101
+ element.type
102
+ );
103
+
104
+ if (!context) {
105
+ context = emptyObject;
106
+ }
107
+ ReactUpdates.batchedUpdates(_batchedRender, this, element, context);
108
+
109
+ return this.getRenderOutput();
110
+ }
111
+ getRenderOutput() {
112
+ return (
113
+ (this._instance && this._instance._renderedComponent &&
114
+ this._instance._renderedComponent._renderedOutput)
115
+ || null
116
+ );
117
+ }
118
+ unmount() {
119
+ if (this._instance) {
120
+ ReactReconciler.unmountComponent(this._instance, false);
121
+ }
122
+ }
123
+ _render(element, transaction, context) {
124
+ if (this._instance) {
125
+ ReactReconciler.receiveComponent(
126
+ this._instance,
127
+ element,
128
+ transaction,
129
+ context
130
+ );
131
+ } else {
132
+ var instance = new ShallowComponentWrapper(element);
133
+ ReactReconciler.mountComponent(instance, transaction, null, null, context, 0);
134
+ this._instance = instance;
135
+ }
136
+ }
137
+}
138
+
139
+module.exports = ReactShallowRenderer;
src/test/ReactTestUtils.js
+1
-136
@@ -16,17 +16,14 @@ var EventPluginHub = require('EventPluginHub');
16
var EventPluginRegistry = require('EventPluginRegistry');
17
var EventPropagators = require('EventPropagators');
18
var React = require('React');
19
-var ReactDefaultInjection = require('ReactDefaultInjection');
19
var ReactDOM = require('ReactDOM');
20
var ReactDOMComponentTree = require('ReactDOMComponentTree');
21
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
23
-var ReactCompositeComponent = require('ReactCompositeComponent');
22
var ReactInstanceMap = require('ReactInstanceMap');
25
-var ReactReconciler = require('ReactReconciler');
23
var ReactUpdates = require('ReactUpdates');
24
var SyntheticEvent = require('SyntheticEvent');
25
+var ReactShallowRenderer = require('ReactShallowRenderer');
26
29
-var emptyObject = require('emptyObject');
27
var findDOMNode = require('findDOMNode');
28
var invariant = require('invariant');
29
@@ -365,138 +362,6 @@ var ReactTestUtils = {
362
SimulateNative: {},
363
};
364
368
-/**
369
- * @class ReactShallowRenderer
370
- */
371
-var ReactShallowRenderer = function() {
372
- this._instance = null;
373
-};
374
-
375
-ReactShallowRenderer.prototype.getMountedInstance = function() {
376
- return this._instance ? this._instance._instance : null;
377
-};
378
-
379
-var nextDebugID = 1;
380
-
381
-var NoopInternalComponent = function(element) {
382
- this._renderedOutput = element;
383
- this._currentElement = element;
384
-
385
- if (__DEV__) {
386
- this._debugID = nextDebugID++;
387
- }
388
-};
389
-
390
-NoopInternalComponent.prototype = {
391
-
392
- mountComponent: function() {
393
- },
394
-
395
- receiveComponent: function(element) {
396
- this._renderedOutput = element;
397
- this._currentElement = element;
398
- },
399
-
400
- getHostNode: function() {
401
- return undefined;
402
- },
403
-
404
- unmountComponent: function() {
405
- },
406
-
407
- getPublicInstance: function() {
408
- return null;
409
- },
410
-};
411
-
412
-var ShallowComponentWrapper = function(element) {
413
- // TODO: Consolidate with instantiateReactComponent
414
- if (__DEV__) {
415
- this._debugID = nextDebugID++;
416
- }
417
-
418
- this.construct(element);
419
-};
420
-Object.assign(
421
- ShallowComponentWrapper.prototype,
422
- ReactCompositeComponent, {
423
- _constructComponent:
424
- ReactCompositeComponent._constructComponentWithoutOwner,
425
- _instantiateReactComponent: function(element) {
426
- return new NoopInternalComponent(element);
427
- },
428
- _replaceNodeWithMarkup: function() {},
429
- _renderValidatedComponent:
430
- ReactCompositeComponent
431
- ._renderValidatedComponentWithoutOwnerOrContext,
432
- }
433
-);
434
-
435
-ReactShallowRenderer.prototype.render = function(element, context) {
436
- // Ensure we've done the default injections. This might not be true in the
437
- // case of a simple test that only requires React and the TestUtils in
438
- // conjunction with an inline-requires transform.
439
- ReactDefaultInjection.inject();
440
-
441
- invariant(
442
- React.isValidElement(element),
443
- 'ReactShallowRenderer render(): Invalid component element.%s',
444
- typeof element === 'function' ?
445
- ' Instead of passing a component class, make sure to instantiate ' +
446
- 'it by passing it to React.createElement.' :
447
- ''
448
- );
449
- invariant(
450
- typeof element.type !== 'string',
451
- 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
452
- 'components, not primitives (%s). Instead of calling `.render(el)` and ' +
453
- 'inspecting the rendered output, look at `el.props` directly instead.',
454
- element.type
455
- );
456
-
457
- if (!context) {
458
- context = emptyObject;
459
- }
460
- ReactUpdates.batchedUpdates(_batchedRender, this, element, context);
461
-
462
- return this.getRenderOutput();
463
-};
464
-
465
-function _batchedRender(renderer, element, context) {
466
- var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(true);
467
- renderer._render(element, transaction, context);
468
- ReactUpdates.ReactReconcileTransaction.release(transaction);
469
-}
470
-
471
-ReactShallowRenderer.prototype.getRenderOutput = function() {
472
- return (
473
- (this._instance && this._instance._renderedComponent &&
474
- this._instance._renderedComponent._renderedOutput)
475
- || null
476
- );
477
-};
478
-
479
-ReactShallowRenderer.prototype.unmount = function() {
480
- if (this._instance) {
481
- ReactReconciler.unmountComponent(this._instance, false);
482
- }
483
-};
484
-
485
-ReactShallowRenderer.prototype._render = function(element, transaction, context) {
486
- if (this._instance) {
487
- ReactReconciler.receiveComponent(
488
- this._instance,
489
- element,
490
- transaction,
491
- context
492
- );
493
- } else {
494
- var instance = new ShallowComponentWrapper(element);
495
- ReactReconciler.mountComponent(instance, transaction, null, null, context, 0);
496
- this._instance = instance;
497
- }
498
-};
499
-
365
/**
366
* Exports:
367
*