diff --git a/src/renderers/testing/ReactTestMount.js b/src/renderers/testing/ReactTestMount.js index a3f2e61aff7..89f964b7b2c 100644 --- a/src/renderers/testing/ReactTestMount.js +++ b/src/renderers/testing/ReactTestMount.js @@ -130,6 +130,18 @@ ReactTestInstance.prototype.toJSON = function() { var inst = getHostComponentFromComposite(this._component); return inst.toJSON(); }; +ReactTestInstance.prototype.find = function(selector) { + var inst = getHostComponentFromComposite(this._component); + return inst.find(selector, false); +}; +ReactTestInstance.prototype.findAll = function(selector) { + var inst = getHostComponentFromComposite(this._component); + return inst.findAll(selector); +}; +ReactTestInstance.prototype.findByProps = function(props) { + var inst = getHostComponentFromComposite(this._component); + return inst.findByProps(props); +}; /** * As soon as `ReactMount` is refactored to not rely on the DOM, we can share diff --git a/src/renderers/testing/ReactTestRenderer.js b/src/renderers/testing/ReactTestRenderer.js index b2d18464629..f82839d2c09 100644 --- a/src/renderers/testing/ReactTestRenderer.js +++ b/src/renderers/testing/ReactTestRenderer.js @@ -90,6 +90,66 @@ ReactTestComponent.prototype.toJSON = function() { }); return object; }; +ReactTestComponent.prototype.getType = function() { + return this._currentElement.type; +}; +ReactTestComponent.prototype.getProps = function() { + return this._currentElement.props; +}; +ReactTestComponent.prototype.getChildren = function() { + return Object.keys(this._renderedChildren || {}).map(function(key) { + return this._renderedChildren[key]; + }, this); +}; +ReactTestComponent.prototype.find = function(selector) { + if (this.getType() === selector) { + return this; + } + var children = this.getChildren(); + + for (var key in children) { + var inst = children[key]; + let result = inst.find(selector); + if (result) { + return result; + } + } + return null; +}; +ReactTestComponent.prototype.findAll = function(selector, props) { + var output = []; + + if (this.getType() === selector) { + output.push(this); + } + + return this.getChildren().reduce(function(current, inst) { + return current.concat(inst.findAll(selector)); + }, output); +}; +ReactTestComponent.prototype.findByProps = function(props) { + var propsEqual = true; + for (var key in props) { + if (this.getProps()[key] !== props[key]) { + propsEqual = false; + break; + } + } + if (propsEqual) { + return this; + } + + var children = this.getChildren(); + for (key in children) { + var inst = children[key]; + let result = inst.findByProps(props); + if (result) { + return result; + } + } + return null; +}; + Object.assign(ReactTestComponent.prototype, ReactMultiChild.Mixin); // ============================================================================= @@ -106,6 +166,15 @@ ReactTestTextComponent.prototype.unmountComponent = function() {}; ReactTestTextComponent.prototype.toJSON = function() { return this._currentElement; }; +ReactTestTextComponent.prototype.find = function() { + return null; +}; +ReactTestTextComponent.prototype.findAll = function() { + return []; +}; +ReactTestTextComponent.prototype.findByProps = function() { + return null; +}; // ============================================================================= diff --git a/src/renderers/testing/__tests__/ReactTestRenderer-test.js b/src/renderers/testing/__tests__/ReactTestRenderer-test.js index a20d442686d..4e700f028b0 100644 --- a/src/renderers/testing/__tests__/ReactTestRenderer-test.js +++ b/src/renderers/testing/__tests__/ReactTestRenderer-test.js @@ -198,4 +198,134 @@ describe('ReactTestRenderer', function() { expect(log).toEqual([null]); }); + describe('selectors API', function() { + it('finds one element by name', function() { + class Component extends React.Component { + render() { + return ( +