diff --git a/src/renderers/testing/ReactTestMount.js b/src/renderers/testing/ReactTestMount.js index 74d3c72d5011e..a3f2e61aff76a 100644 --- a/src/renderers/testing/ReactTestMount.js +++ b/src/renderers/testing/ReactTestMount.js @@ -19,6 +19,7 @@ var ReactUpdates = require('ReactUpdates'); var emptyObject = require('emptyObject'); var getHostComponentFromComposite = require('getHostComponentFromComposite'); var instantiateReactComponent = require('instantiateReactComponent'); +var invariant = require('invariant'); /** * Temporary (?) hack so that we can store all top-level pending updates on @@ -83,6 +84,48 @@ var ReactTestInstance = function(component) { ReactTestInstance.prototype.getInstance = function() { return this._component._renderedComponent.getPublicInstance(); }; +ReactTestInstance.prototype.update = function(nextElement) { + invariant( + this._component, + "ReactTestRenderer: .update() can't be called after unmount." + ); + var nextWrappedElement = new ReactElement( + TopLevelWrapper, + null, + null, + null, + null, + null, + nextElement + ); + var component = this._component; + ReactUpdates.batchedUpdates(function() { + var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(true); + transaction.perform(function() { + ReactReconciler.receiveComponent( + component, + nextWrappedElement, + transaction, + emptyObject + ); + }); + ReactUpdates.ReactReconcileTransaction.release(transaction); + }); +}; +ReactTestInstance.prototype.unmount = function(nextElement) { + var component = this._component; + ReactUpdates.batchedUpdates(function() { + var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(true); + transaction.perform(function() { + ReactReconciler.unmountComponent( + component, + false + ); + }); + ReactUpdates.ReactReconcileTransaction.release(transaction); + }); + this._component = null; +}; ReactTestInstance.prototype.toJSON = function() { var inst = getHostComponentFromComposite(this._component); return inst.toJSON(); @@ -92,7 +135,7 @@ ReactTestInstance.prototype.toJSON = function() { * As soon as `ReactMount` is refactored to not rely on the DOM, we can share * code between the two. For now, we'll hard code the ID logic. */ -var ReactHostMount = { +var ReactTestMount = { render: function( nextElement: ReactElement @@ -107,19 +150,6 @@ var ReactHostMount = { nextElement ); - // var prevComponent = ReactHostMount._instancesByContainerID[containerTag]; - // if (prevComponent) { - // var prevWrappedElement = prevComponent._currentElement; - // var prevElement = prevWrappedElement.props; - // if (shouldUpdateReactComponent(prevElement, nextElement)) { - // ReactUpdateQueue.enqueueElementInternal(prevComponent, nextWrappedElement); - // if (callback) { - // ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback); - // } - // return prevComponent; - // } - // } - var instance = instantiateReactComponent(nextWrappedElement, false); // The initial render is synchronous but any updates that happen during @@ -141,4 +171,4 @@ var ReactHostMount = { }; -module.exports = ReactHostMount; +module.exports = ReactTestMount; diff --git a/src/renderers/testing/ReactTestRenderer.js b/src/renderers/testing/ReactTestRenderer.js index ba6659fc4f6f9..b2d18464629bc 100644 --- a/src/renderers/testing/ReactTestRenderer.js +++ b/src/renderers/testing/ReactTestRenderer.js @@ -11,6 +11,7 @@ 'use strict'; +var ReactComponentEnvironment = require('ReactComponentEnvironment'); var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy'); var ReactEmptyComponent = require('ReactEmptyComponent'); var ReactMultiChild = require('ReactMultiChild'); @@ -62,6 +63,11 @@ ReactTestComponent.prototype.receiveComponent = function( this.updateChildren(nextElement.props.children, transaction, context); }; 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; +}; ReactTestComponent.prototype.unmountComponent = function() {}; ReactTestComponent.prototype.toJSON = function() { var {children, ...props} = this._currentElement.props; @@ -125,6 +131,11 @@ ReactEmptyComponent.injection.injectEmptyComponentFactory(function() { return new ReactTestEmptyComponent(); }); +ReactComponentEnvironment.injection.injectEnvironment({ + processChildrenUpdates: function() {}, + replaceNodeWithMarkup: function() {}, +}); + var ReactTestRenderer = { create: ReactTestMount.render, diff --git a/src/renderers/testing/__tests__/ReactTestRenderer-test.js b/src/renderers/testing/__tests__/ReactTestRenderer-test.js index 1d789c9ffcae0..e35e20d6d3d90 100644 --- a/src/renderers/testing/__tests__/ReactTestRenderer-test.js +++ b/src/renderers/testing/__tests__/ReactTestRenderer-test.js @@ -110,4 +110,91 @@ describe('ReactTestRenderer', function() { }); }); + it('updates types', function() { + var renderer = ReactTestRenderer.create(