From 87b967a7a32863f0cef185015a7fe781b95c199f Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 29 Mar 2018 21:03:53 -0600 Subject: [PATCH] upgrade react-testing-library and use wait instead. Much improved --- client/package.json | 3 +-- client/src/__tests__/app.create-post.js | 17 ++++++++----- client/src/__tests__/app.login.js | 25 +++++++++---------- client/src/__tests__/app.login.todo.js | 4 +-- client/src/__tests__/app.register.js | 20 +++++++++------ client/src/__tests__/app.register.todo.js | 4 +-- .../__tests__/app.snapshot.not-recommended.js | 8 +++--- client/src/components/__tests__/user.js | 16 ++++++------ client/src/screens/__tests__/editor.js | 9 ++++--- client/test/client-test-utils.js | 7 ++++-- 10 files changed, 62 insertions(+), 51 deletions(-) diff --git a/client/package.json b/client/package.json index d4ce7f71..08181f3e 100644 --- a/client/package.json +++ b/client/package.json @@ -31,8 +31,7 @@ "devDependencies": { "jest-glamor-react": "^4.2.0", "react-scripts": "^2.0.0-next.47d2d941", - "react-test-renderer": "^16.2.0", - "react-testing-library": "^1.6.0", + "react-testing-library": "^1.9.1", "til-shared": "file:../shared" }, "browserslist": { diff --git a/client/src/__tests__/app.create-post.js b/client/src/__tests__/app.create-post.js index 647d33d5..a25573cd 100644 --- a/client/src/__tests__/app.create-post.js +++ b/client/src/__tests__/app.create-post.js @@ -9,7 +9,7 @@ import React from 'react' import {Simulate} from 'react-dom/test-utils' import axiosMock from 'axios' -import {renderWithRouter, flushPromises, generate} from 'client-test-utils' +import {renderWithRouter, generate} from 'client-test-utils' import {init as initAPI} from '../utils/api' import App from '../app' @@ -42,10 +42,15 @@ test('create post', async () => { } }) - const {container, getByText, getByLabelText} = renderWithRouter() + const { + container, + getByText, + getByLabelText, + finishLoading, + } = renderWithRouter() - // wait for /me request to settle - await flushPromises() + // wait for the app to finish loading the mocked requests + await finishLoading() axiosMock.__mock.reset() // navigate to register @@ -86,8 +91,8 @@ test('create post', async () => { date: expect.any(String), }) - // wait for promises to settle - await flushPromises() + // wait for the mocked requests to finish + await finishLoading() expect(window.location.href).not.toContain('editor') diff --git a/client/src/__tests__/app.login.js b/client/src/__tests__/app.login.js index 61b73160..07b70d0d 100644 --- a/client/src/__tests__/app.login.js +++ b/client/src/__tests__/app.login.js @@ -8,12 +8,7 @@ import React from 'react' import axiosMock from 'axios' -import { - renderWithRouter, - flushPromises, - generate, - Simulate, -} from 'client-test-utils' +import {renderWithRouter, generate, Simulate} from 'client-test-utils' import {init as initAPI} from '../utils/api' import App from '../app' @@ -24,12 +19,16 @@ beforeEach(() => { }) test('login as an existing user', async () => { - const {getByTestId, container, getByText, getByLabelText} = renderWithRouter( - , - ) + const { + getByTestId, + container, + getByText, + getByLabelText, + finishLoading, + } = renderWithRouter() - // wait for /me request to settle - await flushPromises() + // wait for the app to finish loading the mocked requests + await finishLoading() // navigate to login const leftClick = {button: 0} @@ -54,8 +53,8 @@ test('login as an existing user', async () => { ) Simulate.submit(formWrapper) - // wait for promises to settle - await flushPromises() + // wait for the mocked requests to finish + await finishLoading() // assert calls expect(axiosMock.__mock.instance.post).toHaveBeenCalledTimes(1) diff --git a/client/src/__tests__/app.login.todo.js b/client/src/__tests__/app.login.todo.js index 4da83adf..6b0329cb 100644 --- a/client/src/__tests__/app.login.todo.js +++ b/client/src/__tests__/app.login.todo.js @@ -3,7 +3,7 @@ test('login as an existing user', async () => { // render the app with the router provider and custom history // - // wait for /me request to settle + // wait for the app to finish loading the mocked requests // // navigate to login by clicking login-link // @@ -16,7 +16,7 @@ test('login as an existing user', async () => { // which you can generate with generate.token(fakeUser) // Now simulate a submit event on the form // - // wait for promises to settle + // wait for the mocked requests to finish // // assert post was called correctly // assert localStorage is correct diff --git a/client/src/__tests__/app.register.js b/client/src/__tests__/app.register.js index f63ac6c9..91f61b42 100644 --- a/client/src/__tests__/app.register.js +++ b/client/src/__tests__/app.register.js @@ -9,7 +9,7 @@ import React from 'react' import {Simulate} from 'react-dom/test-utils' import axiosMock from 'axios' -import {renderWithRouter, flushPromises, generate} from 'client-test-utils' +import {renderWithRouter, generate} from 'client-test-utils' import {init as initAPI} from '../utils/api' import App from '../app' @@ -20,12 +20,16 @@ beforeEach(() => { }) test('register a new user', async () => { - const {container, getByTestId, getByText, getByLabelText} = renderWithRouter( - , - ) + const { + container, + getByTestId, + getByText, + finishLoading, + getByLabelText, + } = renderWithRouter() - // wait for /me request to settle - await flushPromises() + // wait for the app to finish loading the mocked requests + await finishLoading() // navigate to register const leftClick = {button: 0} @@ -50,8 +54,8 @@ test('register a new user', async () => { ) Simulate.submit(formWrapper) - // wait for promises to settle - await flushPromises() + // wait for the mocked requests to finish + await finishLoading() // assert calls expect(axiosMock.__mock.instance.post).toHaveBeenCalledTimes(1) diff --git a/client/src/__tests__/app.register.todo.js b/client/src/__tests__/app.register.todo.js index 4456918c..b2acca1e 100644 --- a/client/src/__tests__/app.register.todo.js +++ b/client/src/__tests__/app.register.todo.js @@ -4,7 +4,7 @@ test('register a new user', async () => { // render the app with the router provider and custom history // - // wait for /me request to settle + // wait for the app to finish loading the mocked requests // // navigate to register by clicking register-link // @@ -17,7 +17,7 @@ test('register a new user', async () => { // which you can generate with generate.token(fakeUser) // Now simulate a submit event on the form // - // wait for promises to settle + // wait for the mocked requests to finish // // assert post was called correctly // assert localStorage is correct diff --git a/client/src/__tests__/app.snapshot.not-recommended.js b/client/src/__tests__/app.snapshot.not-recommended.js index bfb04dcb..718e0fd7 100644 --- a/client/src/__tests__/app.snapshot.not-recommended.js +++ b/client/src/__tests__/app.snapshot.not-recommended.js @@ -8,7 +8,7 @@ import React from 'react' import axiosMock from 'axios' -import {renderWithRouter, flushPromises, generate} from 'client-test-utils' +import {renderWithRouter} from 'client-test-utils' import {init as initAPI} from '../utils/api' import App from '../app' @@ -41,9 +41,9 @@ test('snapshot', async () => { } }) - const {container} = renderWithRouter() + const {container, finishLoading} = renderWithRouter() - // wait for /me request to settle - await flushPromises() + // wait for the app to finish loading the mocked requests + await finishLoading() expect(container.firstChild).toMatchSnapshot() }) diff --git a/client/src/components/__tests__/user.js b/client/src/components/__tests__/user.js index f98c5f02..3d77c8ea 100644 --- a/client/src/components/__tests__/user.js +++ b/client/src/components/__tests__/user.js @@ -8,7 +8,7 @@ import React from 'react' import ReactDOM from 'react-dom' -import {flushPromises, generate} from 'client-test-utils' +import {wait, generate} from 'client-test-utils' import User from '../user' import * as apiMock from '../../utils/api' @@ -48,10 +48,11 @@ test('login rerenders with the retrieved user', async () => { ) const form = generate.loginForm(fakeUser) controller.login(form) - await flushPromises() expect(apiMock.auth.login).toHaveBeenCalledTimes(1) expect(apiMock.auth.login).toHaveBeenCalledWith(form) - expect(children).toHaveBeenCalledTimes(2) + + await wait(() => expect(children).toHaveBeenCalledTimes(2)) + expect(children).toHaveBeenCalledWith( expect.objectContaining({ pending: true, @@ -71,9 +72,8 @@ test('login rerenders with the retrieved user', async () => { test('logout rerenders with a null user', async () => { const {children, controller} = await setup() controller.logout() - await flushPromises() expect(apiMock.auth.logout).toHaveBeenCalledTimes(1) - expect(children).toHaveBeenCalledTimes(2) + await wait(() => expect(children).toHaveBeenCalledTimes(2)) expect(children).toHaveBeenCalledWith( expect.objectContaining({ pending: true, @@ -99,10 +99,9 @@ test('on register failure, rerenders with the error', async () => { const form = generate.loginForm() // the catch below is simply to ignore the error thrown controller.register(form).catch(i => i) - await flushPromises() expect(apiMock.auth.register).toHaveBeenCalledTimes(1) expect(apiMock.auth.register).toHaveBeenCalledWith(form) - expect(children).toHaveBeenCalledTimes(2) + await wait(() => expect(children).toHaveBeenCalledTimes(2)) expect(children).toHaveBeenCalledWith( expect.objectContaining({ pending: true, @@ -127,7 +126,8 @@ async function setup() { }) const div = document.createElement('div') ReactDOM.render({children}, div) - await flushPromises() + children.mockClear() + await wait(() => expect(children).toHaveBeenCalledTimes(1)) children.mockClear() return {controller, children} } diff --git a/client/src/screens/__tests__/editor.js b/client/src/screens/__tests__/editor.js index cef09b47..91f706be 100644 --- a/client/src/screens/__tests__/editor.js +++ b/client/src/screens/__tests__/editor.js @@ -1,5 +1,5 @@ import React from 'react' -import {generate, render, Simulate, flushPromises} from 'client-test-utils' +import {generate, render, Simulate, wait} from 'client-test-utils' import Editor from '../editor' test('calls onSubmit with the username and password when submitted', async () => { @@ -26,15 +26,16 @@ test('calls onSubmit with the username and password when submitted', async () => // Act Simulate.submit(formNode) - const postDate = Date.now() - await flushPromises() - // Assert expect(fakeApi.posts.create).toHaveBeenCalledTimes(1) expect(fakeApi.posts.create).toHaveBeenCalledWith({ ...fakePost, date: expect.any(String), }) + + const postDate = Date.now() + await wait(() => expect(fakeHistory.push).toHaveBeenCalledTimes(1)) + expect(fakeHistory.push).toHaveBeenCalledWith('/') const date = new Date(fakeApi.posts.create.mock.calls[0][0].date).getTime() expect(date).toBeGreaterThanOrEqual(preDate) expect(date).toBeLessThanOrEqual(postDate) diff --git a/client/test/client-test-utils.js b/client/test/client-test-utils.js index c8bcb039..ff175888 100644 --- a/client/test/client-test-utils.js +++ b/client/test/client-test-utils.js @@ -1,16 +1,19 @@ import React from 'react' import {Router} from 'react-router-dom' -import {render, flushPromises, Simulate} from 'react-testing-library' +import {render, wait, Simulate} from 'react-testing-library' import {createMemoryHistory} from 'history' import * as generate from 'til-shared/generate' function renderWithRouter(ui, {route = '/', ...renderOptions} = {}) { const history = createMemoryHistory({initialEntries: [route]}) const utils = render({ui}, renderOptions) + const finishLoading = () => + wait(() => expect(utils.queryByText('Loading')).toBeNull()) return { ...utils, + finishLoading, history, } } -export {renderWithRouter, generate, render, flushPromises, Simulate} +export {renderWithRouter, generate, render, wait, Simulate}