Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/renderers/testing/ReactTestMount.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
69 changes: 69 additions & 0 deletions src/renderers/testing/ReactTestRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

// =============================================================================
Expand All @@ -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;
};

// =============================================================================

Expand Down
130 changes: 130 additions & 0 deletions src/renderers/testing/__tests__/ReactTestRenderer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div>
<div>one element</div>
<myelement id={1} />
<span>
<div>
<myelement id={2}/>
</div>
</span>
</div>
);
}
}

var renderer = ReactTestRenderer.create(<Component />);

var myelement = renderer.find('myelement');
expect(myelement.getProps().id).toEqual(1);
});

it('concatenates finders', function() {
class Component extends React.Component {
render() {
return (
<div>
<div>one element</div>
<myelement id={1} />
<span>
<div>
<myelement id={2}/>
</div>
</span>
</div>
);
}
}

var renderer = ReactTestRenderer.create(<Component />);

var myelement = renderer.find('span').find('myelement');
expect(myelement.getProps().id).toEqual(2);
});

it('finds all elements by name', function() {
class Component extends React.Component {
render() {
return (
<div>
<div>one element</div>
<myelement id={1} />
<span>
<div>
<myelement id={2}/>
</div>
</span>
</div>
);
}
}

var renderer = ReactTestRenderer.create(<Component />);

var myelements = renderer.findAll('myelement');
expect(myelements.length).toBe(2);
expect(myelements[0].getProps().id).toBe(1);
expect(myelements[1].getProps().id).toBe(2);
});

it('finds an element by props', function() {
class Component extends React.Component {
render() {
return (
<div>
<div>one element</div>
<myelement className={'found'} id={1} />
<span>
<div>
<myelement className={'found'} id={2} another={true} />
</div>
</span>
</div>
);
}
}

var renderer = ReactTestRenderer.create(<Component />);

var myelement = renderer.findByProps({
className: 'found',
id: 2,
});
expect(myelement.getProps()).toEqual({
className: 'found',
id: 2,
another: true,
});
});

it('can use finders to trigger events', function() {
class Component extends React.Component {
constructor() {
super();
this.state = { clicked: 0 };
}

render() {
return (
<div>
<span>{this.state.clicked}</span>
<myelement onClick={this._onClick}/>
</div>
);
}
_onClick = () => {
this.setState({clicked: 1});
}
}

var renderer = ReactTestRenderer.create(<Component />);

expect(renderer.find('span').getChildren()[0].toJSON()).toEqual(0);

renderer.find('myelement').getProps().onClick();
expect(renderer.find('span').getChildren()[0].toJSON()).toEqual(1);
});
});
});