Reputation: 10190
I have a simple React component using react-router which redirects the user if they don't have permission to view a certain route:
class App extends Component {
constructor(props) {
super(props);
this.state = {permission: false};
}
render() {
return (
<Switch>
<Route exact path="/users">
<h2>A list of users</h2>
</Route>
<Route path="/users/:userId">
{({match}) => this.state.permission ? <h1>{match.params.userId}</h1> : <Redirect to="/users" />}
</Route>
</Switch>
);
}
}
I am trying to test the different scenarios when accessing /users/:userId
using Jest and Enzyme, but am unable to get the test to succeed when the user has permission.
My tests are as follows:
describe("render()", () => {
describe("when route is /users/:userId", () => {
let wrapper;
let app;
beforeEach(() => {
wrapper = mount(
<MemoryRouter initialEntries={["/users/1"]}>
<App />
</MemoryRouter>
);
app = wrapper.find(App).instance();
});
describe("when user has permission", () => {
beforeEach(() => {
app.setState({permission: true});
});
it("should show users id", () => {
expect(wrapper.exists("h1")).toBe(true);
});
});
describe("when user doesn't have permission", () => {
beforeEach(() => {
app.setState({permission: false});
});
it("should redirect to users list", () => {
expect(wrapper.exists("h2")).toBe(true);
});
});
});
});
The first test fails while the second succeeds. I've used console.log(wrapper.debug());
in the first test and it shows that the component is rendering the first route (i.e. being redirected) and I've printed out the state so I can see that the setState
call is working.
How should I rewrite my tests to make this work?
Upvotes: 4
Views: 7685
Reputation: 45860
The initial location is set to /users/1
but when the component first mounts it renders the Redirect
which sets the location to /users
.
permission
is then set to true
but since location is /users
the result is <h2>A list of users</h2>
.
After setting permission
to true
, set the location to /users/1
so the location is correct and the test successfully renders <h1>1</h1>
:
describe("render()", () => {
describe("when route is /users/:userId", () => {
let wrapper;
let app;
beforeEach(() => {
wrapper = mount(
<MemoryRouter initialEntries={["/users/1"]}>
<App />
</MemoryRouter>
); // the Redirect sets location to /users during the initial render
app = wrapper.find(App).instance();
});
describe("when user has permission", () => {
beforeEach(() => {
app.setState({permission: true});
wrapper.instance().history.replace('/users/1'); // replace the MemoryRouter location with /users/1
wrapper.update(); // update the wrapper with the changes
});
it("should show users id", () => {
expect(wrapper.exists("h1")).toBe(true); // SUCCESS
});
});
describe("when user doesn't have permission", () => {
beforeEach(() => {
app.setState({permission: false});
});
it("should redirect to users list", () => {
expect(wrapper.exists("h2")).toBe(true);
});
});
});
});
Upvotes: 3