diff --git a/src/renderers/testing/ReactTestMount.js b/src/renderers/testing/ReactTestMount.js index d964a1390a65f..c22c59320187f 100644 --- a/src/renderers/testing/ReactTestMount.js +++ b/src/renderers/testing/ReactTestMount.js @@ -20,6 +20,10 @@ var getHostComponentFromComposite = require('getHostComponentFromComposite'); var instantiateReactComponent = require('instantiateReactComponent'); var invariant = require('invariant'); +type TestRendererMockConfig = { + getMockRef: (element: ReactElement) => Object, +}; + /** * Temporary (?) hack so that we can store all top-level pending updates on * composites instead of having to worry about different types of components @@ -45,7 +49,9 @@ TopLevelWrapper.isReactTopLevelWrapper = true; */ function mountComponentIntoNode( componentInstance, - transaction) { + transaction, + mockConfig, + ) { var image = ReactReconciler.mountComponent( componentInstance, transaction, @@ -54,6 +60,9 @@ function mountComponentIntoNode( emptyObject ); componentInstance._renderedComponent._topLevelWrapper = componentInstance; + if (mockConfig) { + componentInstance._renderedComponent._mockConfig = mockConfig; + } return image; } @@ -65,13 +74,16 @@ function mountComponentIntoNode( * @param {number} containerTag container element to mount into. */ function batchedMountComponentIntoNode( - componentInstance) { + componentInstance, + mockConfig, + ) { var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(); var image = transaction.perform( mountComponentIntoNode, null, componentInstance, - transaction + transaction, + mockConfig, ); ReactUpdates.ReactReconcileTransaction.release(transaction); return image; @@ -135,11 +147,12 @@ ReactTestInstance.prototype.toJSON = function() { var ReactTestMount = { render: function( - nextElement: ReactElement + nextElement: ReactElement, + mockConfig: TestRendererMockConfig, ): ReactTestInstance { var nextWrappedElement = React.createElement( TopLevelWrapper, - { child: nextElement } + { child: nextElement }, ); var instance = instantiateReactComponent(nextWrappedElement, false); @@ -147,10 +160,12 @@ var ReactTestMount = { // The initial render is synchronous but any updates that happen during // rendering, in componentWillMount or componentDidMount, will be batched // according to the current batching strategy. + // ReactUpdates.batchedUpdates( batchedMountComponentIntoNode, - instance + instance, + mockConfig, ); return new ReactTestInstance(instance); }, diff --git a/src/renderers/testing/ReactTestRenderer.js b/src/renderers/testing/ReactTestRenderer.js index ac9d1f47248d8..946a93429dfa5 100644 --- a/src/renderers/testing/ReactTestRenderer.js +++ b/src/renderers/testing/ReactTestRenderer.js @@ -42,6 +42,7 @@ var ReactTestComponent = function(element) { this._currentElement = element; this._renderedChildren = null; this._topLevelWrapper = null; + this._mockConfig = null; }; ReactTestComponent.prototype.mountComponent = function( transaction, @@ -62,9 +63,13 @@ ReactTestComponent.prototype.receiveComponent = function( }; ReactTestComponent.prototype.getHostNode = function() {}; ReactTestComponent.prototype.getPublicInstance = function() { - // I can't say this makes a ton of sense but it seems better than throwing. - // Maybe we'll revise later if someone has a good use case. - return null; + if (this._mockConfig) { + var { getMockRef } = this._mockConfig; + if (getMockRef) { + return getMockRef(this._currentElement); + } + } + return {}; }; ReactTestComponent.prototype.unmountComponent = function() {}; ReactTestComponent.prototype.toJSON = function() { @@ -134,9 +139,9 @@ ReactComponentEnvironment.injection.injectEnvironment({ replaceNodeWithMarkup: function() {}, }); + var ReactTestRenderer = { create: ReactTestMount.render, - /* eslint-disable camelcase */ unstable_batchedUpdates: ReactUpdates.batchedUpdates, /* eslint-enable camelcase */ diff --git a/src/renderers/testing/__tests__/ReactTestRenderer-test.js b/src/renderers/testing/__tests__/ReactTestRenderer-test.js index e562867fd2dbb..e184dcebdfe0d 100644 --- a/src/renderers/testing/__tests__/ReactTestRenderer-test.js +++ b/src/renderers/testing/__tests__/ReactTestRenderer-test.js @@ -203,7 +203,24 @@ describe('ReactTestRenderer', function() { it('gives a ref to native components', function() { var log = []; ReactTestRenderer.create(
log.push(r)} />); - expect(log).toEqual([null]); + expect(log).toEqual([{}]); + }); + + it('allows an optional getMockRef function', function() { + var mockDOMInstance = { focus: () => {} }; + var log = []; + ReactTestRenderer.create( +
log.push(r)} />, + { + getMockRef: instance => { + return mockDOMInstance; + }, + } + ); + ReactTestRenderer.create( +
log.push(r)} />, + ); + expect(log).toEqual([mockDOMInstance, {}]); }); it('supports error boundaries', function() {