Eric Bower
·
14 Feb 24
testing.md
1---
2title: Testing
3description: You don't need an HTTP interceptor
4---
5
6Need to write tests? Use libraries like `msw` or `nock`? Well you don't need
7them with `starfx`. If the `mdw.fetch()` middleware detects `ctx.response` is
8already filled then it skips making the request. Let's take the update user
9endpoint example and provide stubbed data for our tests.
10
11```tsx
12import { fireEvent, render, screen } from "@testing-library/react";
13import { useDispatch, useSelector } from "starfx/react";
14import { db } from "./schema.ts";
15import { updateUser } from "./user.ts";
16
17function UserSettingsPage() {
18 const id = "1";
19 const dispatch = useDispatch();
20 const user = useSelector((state) => db.users.selectById(state, { id }));
21
22 return (
23 <div>
24 <div>Name: {user.name}</div>
25 <button onClick={() => dispatch(updateUser({ id, name: "bobby" }))}>
26 Update User
27 </button>
28 </div>
29 );
30}
31
32describe("UserSettingsPage", () => {
33 it("should update the user", async () => {
34 // just for this test -- inject a new middleware into the endpoint stack
35 updateUser.use(function* (ctx, next) {
36 ctx.response = new Response(
37 JSON.stringify({ id: ctx.payload.id, name: ctx.payload.name }),
38 );
39 yield* next();
40 });
41
42 render(<UserSettingsPage />);
43
44 const btn = await screen.findByRole("button", { name: /Update User/ });
45 fireEvent.click(btn);
46
47 await screen.findByText(/Name: bobby/);
48 });
49});
50```
51
52That's it. No need for http interceptors and the core functionality works
53exactly the same, we just skip making the fetch request for our tests.
54
55What if we don't have an API endpoint yet and want to stub the data? We use the
56same concept but inline inside the `updateUser` endpoint:
57
58```ts
59export const updateUser = api.post<{ id: string; name: string }>(
60 "/users/:id",
61 [
62 function* (ctx, next) {
63 ctx.request = ctx.req({
64 body: JSON.stringify({ name: ctx.payload.name }),
65 });
66 yield* next();
67 },
68 function* (ctx, next) {
69 ctx.response = new Response(
70 JSON.stringify({ id: ctx.payload.id, name: ctx.payload.name }),
71 );
72 yield* next();
73 },
74 ],
75);
76```
77
78Wow! Our stubbed data is now colocated next to our actual endpoint we are trying
79to mock! Once we have a real API we want to hit, we can just remove that second
80middleware function and everything will work exactly the same.