I am struggling to get nested components working correctly. Namely, I want to check the contents of a nested component and get a function from one.
import * as React from "react";
import { Expect, TestFixture, Test } from "alsatian";
import { shallow } from "enzyme";
class Foo extends React.Component<{
fn: () => any
}, {}> {
render() {
return <div>Foo</div>;
}
}
class Qux extends React.Component<{}, {}> {
render() {
return <span>{ this.props.children }</span>;
}
}
class Bar extends React.Component<{
title: string
}, {}> {
render() {
return <section>
<h1>{ this.props.title }</h1>
<Foo fn={ () => console.log("hello") }/>
<section>
<Qux>Qux number one</Qux>
<Qux>And another Qux</Qux>
</section>
</section>;
}
}
class Baz extends React.Component<{}, {}> {
render() {
return <Bar title="Baz" />;
}
}
@TestFixture()
export class EnzymeNestTests {
@Test()
public fnShouldBeFunction() {
const wrapper = shallow(<Baz />);
const fooFunction = wrapper.find(Foo).prop("fn");
Expect(typeof(fooFunction)).toBe("function");
}
@Test()
public shouldContainTwoQux() {
const wrapper = shallow(<Baz />);
const expectedContents = <section>
<Qux>Qux number one</Qux>
<Qux>And another Qux</Qux>
</section>;
Expect(wrapper.contains(expectedContents)).toBe(true);
}
}
Both tests fail: shouldContainTwoQux returns false for contains, but fnShouldBeFunction fails with this error:
Error: Method “props” is only meant to be run on a single node. 0 found instead.
at ShallowWrapper.single (C:\Code\NewOrbit.SimpleUI\NewOrbit.SimpleUI\node_modules\enzyme\build\ShallowWrapper.js:1502:17)
at ShallowWrapper.props (C:\Code\NewOrbit.SimpleUI\NewOrbit.SimpleUI\node_modules\enzyme\build\ShallowWrapper.js:855:21)
at ShallowWrapper.prop (C:\Code\NewOrbit.SimpleUI\NewOrbit.SimpleUI\node_modules\enzyme\build\ShallowWrapper.js:1061:21)
Am I doing something wrong with my setup?
Shallow-rendering is only meant to go one level deep. When you shallow-render Baz, you only get a Bar (and none of its children) - you're meant to merely assert that Baz renders a Bar with the appropriate props, and leave the testing of Bar to the Bar tests.
Thanks @ljharb. On a second look at the documentation of shallow that is fairly clear, but I think there could be some improvement to the docs to make it a bit clearer that there won't be any children rendered at all.
Would you like me to submit a PR?
PRs to improve the docs are always welcome!
@ljharb I have a similar problem, where I get the error:
Error: Method “props” is only meant to be run on a single node. 0 found instead.
Let's say the Bar component, being rendered in Baz, was passed a component instead of a string. For example:
class Baz extends React.Component<{}, {}> {
render() {
return <Bar title={<Title name="Baz"/>} />;
}
}
Then our test looks like this:
```
@Test()
public fnShouldBeFunction() {
const wrapper = shallow(
const titleComponent = wrapper.find(Bar).prop("title");
Expect(titleComponent.props.name).toEqual("Baz");
}
```
I need to test a prop (in this case name) on the component being passed (in this case Bar) as a prop to the component being tested (in this case Baz). Is there a way to do this in enzyme?
This is a simple example, but the use of this in more complex examples can be really helpful.
I can create an issue about this if you feel it isn't a simple answer.
Yes, you have to wrap it in a div and shallow render that.
@ljharb can you help me brother??i tried to solve this problem 10 different ways but still same problem
Error: Method “props” is only meant to be run on a single node. 0 found instead.**
export class AddExpensePage extends React.Component {
onSubmit = ({ id, description, note, createdat, amount }) => {
this.props.onSubmit({ id, description, note, createdat, amount });
this.props.history.push("/");
};
render() {
return (
<div>
<ExpenseForm onSubmit={this.onSubmit} />
</div>
);
}
}
const mapDispatchtoProps = dispatch => {
return {
onSubmit: ({ id, description, note, createdat, amount }) =>
dispatch(addExpense({ id, description, note, createdat, amount }))
};
};
export default connect(
undefined,
mapDispatchtoProps
)(AddExpensePage);
AddExpensePage.test.js
import toJson from 'enzyme-to-json';
import React from 'react';
import { shallow } from 'enzyme';
import {AddExpensePage} from '../../components/AddExpensePage';
import setupTests from '../setupTests';
import getFilterExpense from '../getFilterExpense/getFilterExpense.test.js';
import { addExpense } from '../../Actions/expenses';
const expense={
id:'1',
description:'January',
note:'',
createdat:1300,
amount:2000
};
test("should set ExpenseForm in AddExpensePage",()=>{
const history={push:jest.fn()};
const dispatch=jest.fn();
const wrapper=shallow(<AddExpensePage dispatch={dispatch} history={history.push} />);
wrapper.find('ExpenseForm').prop('onSubmit')({...expense});
expect(dispatch).toHaveBeenLastCalledWith(addExpense({...expense}));
})
How can i solve this problem??thanks in advance
@tanveerctg please file a new issue rather than reviving an old one; in your case, you want wrapper.dive() to get through the connect HOC.
Most helpful comment
Shallow-rendering is only meant to go one level deep. When you shallow-render Baz, you only get a Bar (and none of its children) - you're meant to merely assert that Baz renders a Bar with the appropriate props, and leave the testing of Bar to the Bar tests.