-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUsers.test.tsx
More file actions
136 lines (121 loc) · 3.78 KB
/
Users.test.tsx
File metadata and controls
136 lines (121 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { describe, expect, test, vitest } from "vitest";
import Users, { USERS_QUERY } from "./Users";
import { render, screen, waitFor } from "@testing-library/react";
import { MockedProvider } from "@apollo/client/testing/react";
import userEvent from "@testing-library/user-event";
import { ComponentProps } from "react";
import CreateUserDialog from "./CreateUserDialog";
vitest.mock("./CreateUserDialog", () => ({
// TypeScript helps keep your mock in sync with the real component.
default: (props: ComponentProps<typeof CreateUserDialog>) => {
if (!props.isOpen) return null;
return (
<dialog open={props.isOpen} onClose={props.onClose}>
<button
data-testid="mock-create-user-button"
onClick={() => {
props.onSuccess({
id: "1",
name: "John Doe",
email: "john.doe@example.com",
role: "admin",
});
props.onClose();
}}
>
Create
</button>
</dialog>
);
},
}));
describe("queries", () => {
test("renders loading state", () => {
render(
<MockedProvider
mocks={[
{
request: { query: USERS_QUERY },
result: { data: { users: [] } },
},
]}
>
<Users />
</MockedProvider>
);
expect(screen.getByText("Loading...")).toBeVisible();
});
test("renders empty state if there are no users", async () => {
render(
<MockedProvider
mocks={[
{
request: { query: USERS_QUERY },
result: { data: { users: [] } },
},
]}
>
<Users />
</MockedProvider>
);
expect(await screen.findByText("No users")).toBeVisible();
});
test("renders users if there are users", async () => {
render(
<MockedProvider
mocks={[
{
request: { query: USERS_QUERY },
result: { data: { users: [{ id: "1", name: "John Doe" }] } },
},
]}
>
<Users />
</MockedProvider>
);
expect(await screen.findByText("John Doe")).toBeVisible();
});
});
describe("mutations", () => {
test("refetches users after creating a user", async () => {
render(
<MockedProvider
mocks={[
// Our first MockedResponse contains no users.
{
request: { query: USERS_QUERY },
result: { data: { users: [] } },
},
// Our second MockedResponse will not be fetched automatically.
// It'll only be used if we refetch the query.
{
request: { query: USERS_QUERY },
result: { data: { users: [{ id: "1", name: "John Doe" }] } },
},
]}
>
<Users />
</MockedProvider>
);
expect(await screen.findByText("No users")).toBeVisible();
await userEvent.click(
screen.getByRole("button", {
name: "Create User",
})
);
expect(await screen.findByRole("dialog")).toBeVisible();
// For demonstration purposes, we'll assert that John Doe isn't visible yet.
expect(screen.queryByText("John Doe")).not.toBeInTheDocument();
// I prefer to use test IDs when mocking components like this.
// I think it makes it clear that we're not using the real component
// and minimizes the risk of breaking the test if user-facing labels change.
await userEvent.click(screen.getByTestId("mock-create-user-button"));
await waitFor(() =>
expect(screen.queryByRole("dialog")).not.toBeInTheDocument()
);
// You can make this test go red by commenting out the `refetch()` call
// in the `onSuccess` callback we passed to the CreateUserDialog component
// in Users.tsx.
expect(await screen.findByText("John Doe")).toBeVisible();
});
});