From 510155e027d56ce3cf5c890c9939d894528cf007 Mon Sep 17 00:00:00 2001 From: Ben Alpert Date: Wed, 25 May 2016 09:46:50 -0700 Subject: [PATCH] Fix instrumentation in shallow rendering (#6867) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, this threw: ``` FAIL src/test/__tests__/ReactTestUtils-test.js (7.291s) ● ReactTestUtils › it can fail context when shallowly rendering - TypeError: Cannot read property '_source' of null at describeID (src/renderers/shared/devtools/ReactComponentTreeDevtool.js:70:46) at Object.ReactComponentTreeDevtool.getStackAddendumByID (src/renderers/shared/devtools/ReactComponentTreeDevtool.js:203:15) at checkReactTypeSpec (src/isomorphic/classic/types/checkReactTypeSpec.js:76:58) at ReactCompositeComponentMixin._checkContextTypes (src/renderers/shared/stack/reconciler/ReactCompositeComponent.js:668:5) at ReactCompositeComponentMixin._processContext (src/renderers/shared/stack/reconciler/ReactCompositeComponent.js:607:14) at ReactCompositeComponentMixin.mountComponent (src/renderers/shared/stack/reconciler/ReactCompositeComponent.js:191:30) at ReactShallowRenderer._render (src/test/ReactTestUtils.js:483:14) at _batchedRender (src/test/ReactTestUtils.js:460:12) at ReactDefaultBatchingStrategyTransaction.Mixin.perform (src/shared/utils/Transaction.js:140:20) at Object.ReactDefaultBatchingStrategy.batchedUpdates (src/renderers/shared/stack/reconciler/ReactDefaultBatchingStrategy.js:65:19) at Object.batchedUpdates (src/renderers/shared/stack/reconciler/ReactUpdates.js:112:20) at ReactShallowRenderer.render (src/test/ReactTestUtils.js:453:16) at Spec.eval (src/test/__tests__/ReactTestUtils-test.js:289:34) at jasmine.Block.execute (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:1067:17) at jasmine.Queue.next_ (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2100:31) at jasmine.Queue.start (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2053:8) at Spec.jasmine.Spec.execute (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2380:14) at jasmine.Queue.next_ (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2100:31) at onComplete (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2096:18) at Spec.jasmine.Spec.finish (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2354:5) at eval [as onComplete] (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2381:10) at jasmine.Queue.next_ (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2110:14) at eval (node_modules/jest-jasmine1/vendor/jasmine-1.3.0.js:2090:18) at Timeout.e [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:440:19) at tryOnTimeout (timers.js:224:11) at Timer.listOnTimeout (timers.js:198:5) ``` --- src/test/ReactTestUtils.js | 17 ++++++++++++++--- src/test/__tests__/ReactTestUtils-test.js | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/test/ReactTestUtils.js b/src/test/ReactTestUtils.js index 6e3bfd260d..093bfad0dd 100644 --- a/src/test/ReactTestUtils.js +++ b/src/test/ReactTestUtils.js @@ -23,6 +23,8 @@ var ReactElement = require('ReactElement'); var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter'); var ReactCompositeComponent = require('ReactCompositeComponent'); var ReactInstanceMap = require('ReactInstanceMap'); +var ReactInstrumentation = require('ReactInstrumentation'); +var ReactReconciler = require('ReactReconciler'); var ReactUpdates = require('ReactUpdates'); var SyntheticEvent = require('SyntheticEvent'); @@ -407,7 +409,11 @@ NoopInternalComponent.prototype = { }; var ShallowComponentWrapper = function(element) { + // TODO: Consolidate with instantiateReactComponent this._debugID = nextDebugID++; + var displayName = element.type.displayName || element.type.name || 'Unknown'; + ReactInstrumentation.debugTool.onSetDisplayName(this._debugID, displayName); + this.construct(element); }; Object.assign( @@ -471,16 +477,21 @@ ReactShallowRenderer.prototype.getRenderOutput = function() { ReactShallowRenderer.prototype.unmount = function() { if (this._instance) { - this._instance.unmountComponent(false); + ReactReconciler.unmountComponent(this._instance, false); } }; ReactShallowRenderer.prototype._render = function(element, transaction, context) { if (this._instance) { - this._instance.receiveComponent(element, transaction, context); + ReactReconciler.receiveComponent( + this._instance, + element, + transaction, + context + ); } else { var instance = new ShallowComponentWrapper(element); - instance.mountComponent(transaction, null, null, context); + ReactReconciler.mountComponent(instance, transaction, null, null, context); this._instance = instance; } }; diff --git a/src/test/__tests__/ReactTestUtils-test.js b/src/test/__tests__/ReactTestUtils-test.js index 493e88e4bd..4bf66e297a 100644 --- a/src/test/__tests__/ReactTestUtils-test.js +++ b/src/test/__tests__/ReactTestUtils-test.js @@ -275,6 +275,29 @@ describe('ReactTestUtils', function() { expect(result).toEqual(
foo
); }); + it('can fail context when shallowly rendering', function() { + spyOn(console, 'error'); + var SimpleComponent = React.createClass({ + contextTypes: { + name: React.PropTypes.string.isRequired, + }, + render: function() { + return
{this.context.name}
; + }, + }); + + var shallowRenderer = ReactTestUtils.createRenderer(); + shallowRenderer.render(); + expect(console.error.argsForCall.length).toBe(1); + expect( + console.error.argsForCall[0][0].replace(/\(at .+?:\d+\)/g, '(at **)') + ).toBe( + 'Warning: Failed context type: Required context `name` was not ' + + 'specified in `SimpleComponent`.\n' + + ' in SimpleComponent (at **)' + ); + }); + it('can scryRenderedDOMComponentsWithClass with TextComponent', function() { var Wrapper = React.createClass({ render: function() {