Description
Thanks for this awesome testing library!
react-testing-library
version: 4.0.1react
version: 16.3.1node
version: 8.4.0npm
(oryarn
) version: yarn 0.27.5
Relevant code or config:
// test.js
import React from 'react';
import { render, fireEvent, cleanup, waitForElement } from 'react-testing-library';
import 'jest-dom/extend-expect';
import axiosMock from 'axios';
import renderAppWithState from '../../__mocks__/integration-utils';
// returns app wrapped in memory router and with created store
import DATA from '../../__mocks__/api/DATA';
describe('Questionnaire flow', () => {
beforeEach(() => {
axiosMock.get.mockResolvedValue({data: {data: { ...DATA }}})
});
afterEach(() => {
cleanup();
});
it('First test', async () => {
const { getByText } = render(renderAppWithState('/start'));
await waitForElement(() => getByText('Some text'));
expect(getByText('Some text')).toBeTruthy();
});
it('Second test', async () => {
const { getByText } = render(renderAppWithState('/start'));
await waitForElement(() => getByText('Some text'));
expect(getByText('Some text')).toBeTruthy();
});
});
// renderAppWithState.js
import React from 'react';
import { MemoryRouter, Route } from 'react-router-dom';
import { Provider } from 'react-redux';
import sampleData from '../src/initialState.json';
import MainLayout from '../src/components/views/MainLayout';
import storeFactory from '../src/store';
import SubRoutes from '../src/subroutes';
export default function renderAppWithState(url, state) {
const store = state ? storeFactory(state) : storeFactory(sampleData);
// automatically unmount and cleanup DOM after the test is finished.
return (
<MemoryRouter basename={env.basename} initialEntries={[url]}>
<Provider store={store}>
<MainLayout>
<Route
path="/"
render={({location}) => {
return (
<div>
<SubRoutes />
</div>
);
}}
/>
</MainLayout>
</Provider>
</MemoryRouter>
)
}
What you did:
I am setting up integration tests for my react app. I use react, react-router and redux. I am following the react-testing-library example, using axiosMock and await for the promise to be resolved.
When going to the /start route:
- an redux action is triggered that uses a promise-based API call
- this api call is intercepted with the axiosMock
- the response data is used to update the app state
- after state has been updated, a history.push() changes the current route of the app, rendering a different component
What happened:
In the example above I used two identical tests. I wanted to make sure tests are isolated. But while the first test always succeeds, the second test always fails due to timeout at await waitForElement(...) with the message 'Unable to find an element with the text...'
Problem description:
Identical, rather simple tests fail, although they should be indempotent. In the first test, history.push is called as expected, the route is changed and the correct component is rendered. In the second test component state / route are not updated as they should.
Suggested solution:
Without internal konwledge of react testing library I can think of two possible reasons: 1.) I made a mistake in the setup or misunderstood how react-testing-library works. 2.) async and waitForElement have some impact on consecutive tests.