diff --git a/src/components/codeExamples/testingForm.ts b/src/components/codeExamples/testingForm.ts index a16093ca5..256edb3a5 100644 --- a/src/components/codeExamples/testingForm.ts +++ b/src/components/codeExamples/testingForm.ts @@ -54,82 +54,85 @@ const mockLogin = jest.fn((email, password) => { return Promise.resolve({ email, password }); }); -describe("App", () => { - beforeEach(() => { - render(); + +it("should display required error when value is invalid", async () => { + render(); + + fireEvent.submit(screen.getByRole("button")); + + expect(await screen.findAllByRole("alert")).toHaveLength(2); + expect(mockLogin).not.toBeCalled(); +}); + +it("should display matching error when email is invalid", async () => { + render(); + + fireEvent.input(screen.getByRole("textbox", { name: /email/i }), { + target: { + value: "test" + } }); - it("should display required error when value is invalid", async () => { - fireEvent.submit(screen.getByRole("button")); + fireEvent.input(screen.getByLabelText("password"), { + target: { + value: "password" + } + }); - expect(await screen.findAllByRole("alert")).toHaveLength(2); - expect(mockLogin).not.toBeCalled(); + fireEvent.submit(screen.getByRole("button")); + + expect(await screen.findAllByRole("alert")).toHaveLength(1); + expect(mockLogin).not.toBeCalled(); + expect(screen.getByRole("textbox", { name: /email/i })).toHaveValue("test"); + expect(screen.getByLabelText("password")).toHaveValue("password"); +}); + +it("should display min length error when password is invalid", async () => { + render(); + + fireEvent.input(screen.getByRole("textbox", { name: /email/i }), { + target: { + value: "test@mail.com" + } }); - it("should display matching error when email is invalid", async () => { - fireEvent.input(screen.getByRole("textbox", { name: /email/i }), { - target: { - value: "test" - } - }); - - fireEvent.input(screen.getByLabelText("password"), { - target: { - value: "password" - } - }); - - fireEvent.submit(screen.getByRole("button")); - - expect(await screen.findAllByRole("alert")).toHaveLength(1); - expect(mockLogin).not.toBeCalled(); - expect(screen.getByRole("textbox", { name: /email/i }).value).toBe("test"); - expect(screen.getByLabelText("password").value).toBe("password"); + fireEvent.input(screen.getByLabelText("password"), { + target: { + value: "pass" + } }); - it("should display min length error when password is invalid", async () => { - fireEvent.input(screen.getByRole("textbox", { name: /email/i }), { - target: { - value: "test@mail.com" - } - }); - - fireEvent.input(screen.getByLabelText("password"), { - target: { - value: "pass" - } - }); - - fireEvent.submit(screen.getByRole("button")); - - expect(await screen.findAllByRole("alert")).toHaveLength(1); - expect(mockLogin).not.toBeCalled(); - expect(screen.getByRole("textbox", { name: /email/i }).value).toBe( - "test@mail.com" - ); - expect(screen.getByLabelText("password").value).toBe("pass"); + fireEvent.submit(screen.getByRole("button")); + + expect(await screen.findAllByRole("alert")).toHaveLength(1); + expect(mockLogin).not.toBeCalled(); + expect(screen.getByRole("textbox", { name: /email/i })).toHaveValue( + "test@mail.com" + ); + expect(screen.getByLabelText("password")).toHaveValue("pass"); +}); + +it("should not display error when value is valid", async () => { + render(); + + fireEvent.input(screen.getByRole("textbox", { name: /email/i }), { + target: { + value: "test@mail.com" + } }); - it("should not display error when value is valid", async () => { - fireEvent.input(screen.getByRole("textbox", { name: /email/i }), { - target: { - value: "test@mail.com" - } - }); - - fireEvent.input(screen.getByLabelText("password"), { - target: { - value: "password" - } - }); - - fireEvent.submit(screen.getByRole("button")); - - await waitFor(() => expect(screen.queryAllByRole("alert")).toHaveLength(0)); - expect(mockLogin).toBeCalledWith("test@mail.com", "password"); - expect(screen.getByRole("textbox", { name: /email/i }).value).toBe(""); - expect(screen.getByLabelText("password").value).toBe(""); + fireEvent.input(screen.getByLabelText("password"), { + target: { + value: "password" + } }); + + fireEvent.submit(screen.getByRole("button")); + + await waitFor(() => expect(screen.queryAllByRole("alert")).toHaveLength(0)); + expect(mockLogin).toBeCalledWith("test@mail.com", "password"); + expect(screen.getByRole("textbox", { name: /email/i })).toHaveValue(""); + expect(screen.getByLabelText("password")).toHaveValue(""); }); ` @@ -159,29 +162,29 @@ export default function App() { ` export const actWarningTest = ` import React from "react"; -import { render, screen, act } from "@testing-library/react"; +import { render, screen } from "@testing-library/react"; import App from "./App"; -describe("App", () => { - it("should have a submit button", () => { - render(); - expect(screen.getByText("SUBMIT")).toBeInTheDocument(); - }); +it("should have a submit button", () => { + render(); + + expect(screen.getByText("SUBMIT")).toBeInTheDocument(); }); ` export const actWarningSolution = ` import React from "react"; -import { render, screen, act } from "@testing-library/react"; +import { render, screen } from "@testing-library/react"; import App from "./App"; -describe("App", () => { - it("should have a submit button", async () => { - await act(async () => { - render() - }); - expect(screen.getByText("SUBMIT")).toBeInTheDocument(); - }); +it("should have a submit button", async () => { + render() + + expect(await screen.findByText("SUBMIT")).toBeInTheDocument(); + + // Now that the UI was awaited until the async behavior was completed, + // you can keep asserting with \`get*\` queries. + expect(screen.getByRole('textbox')).toBeInTheDocument(); }); ` diff --git a/src/data/en/advanced.tsx b/src/data/en/advanced.tsx index 0a7a8b204..fe0e9e591 100644 --- a/src/data/en/advanced.tsx +++ b/src/data/en/advanced.tsx @@ -464,6 +464,27 @@ export default { url="https://codesandbox.io/s/react-hook-form-unit-test-docs-066zk" /> +

+ Additionally, you can set up{" "} + + eslint-plugin-testing-library + {" "} + and{" "} + + eslint-plugin-jest-dom + {" "} + to follow best practices and anticipate common mistakes when writing + your tests. +

+

Step 2: Create login form.

@@ -498,8 +519,8 @@ export default {

Test submission failure.

- We are using waitFor and find* methods - to detect submission feedback, because the{" "} + We are using waitFor util and find*{" "} + queries to detect submission feedback, because the{" "} handleSubmit method is executed asynchronously.

@@ -561,8 +582,18 @@ export default {

- To solve this, wrap your render() calls in{" "} - await act(async () ={`> {}`}): + To solve this, wait until some element from your UI appears with{" "} + find* queries. Note that you must not{" "} + wrap your render() calls in act().{" "} + + You can read more about wrapping things in act{" "} + unnecessarily here + + .