Testing

You don't need an HTTP interceptor


Need to write tests? Use libraries like msw or nock? Well you don't need them with starfx. If the mdw.fetch() middleware detects ctx.response is already filled then it skips making the request. Let's take the update user endpoint example and provide stubbed data for our tests.

 1import { fireEvent, render, screen } from "@testing-library/react";
 2import { useDispatch, useSelector } from "starfx/react";
 3import { db } from "./schema.ts";
 4import { updateUser } from "./user.ts";
 5
 6function UserSettingsPage() {
 7  const id = "1";
 8  const dispatch = useDispatch();
 9  const user = useSelector((state) => db.users.selectById(state, { id }));
10
11  return (
12    <div>
13      <div>Name: {user.name}</div>
14      <button onClick={() => dispatch(updateUser({ id, name: "bobby" }))}>
15        Update User
16      </button>
17    </div>
18  );
19}
20
21describe("UserSettingsPage", () => {
22  it("should update the user", async () => {
23    // just for this test -- inject a new middleware into the endpoint stack
24    updateUser.use(function* (ctx, next) {
25      ctx.response = new Response(
26        JSON.stringify({ id: ctx.payload.id, name: ctx.payload.name }),
27      );
28      yield* next();
29    });
30
31    render(<UserSettingsPage />);
32
33    const btn = await screen.findByRole("button", { name: /Update User/ });
34    fireEvent.click(btn);
35
36    await screen.findByText(/Name: bobby/);
37  });
38});

That's it. No need for http interceptors and the core functionality works exactly the same, we just skip making the fetch request for our tests.

What if we don't have an API endpoint yet and want to stub the data? We use the same concept but inline inside the updateUser endpoint:

 1export const updateUser = api.post<{ id: string; name: string }>(
 2  "/users/:id",
 3  [
 4    function* (ctx, next) {
 5      ctx.request = ctx.req({
 6        body: JSON.stringify({ name: ctx.payload.name }),
 7      });
 8      yield* next();
 9    },
10    function* (ctx, next) {
11      ctx.response = new Response(
12        JSON.stringify({ id: ctx.payload.id, name: ctx.payload.name }),
13      );
14      yield* next();
15    },
16  ],
17);

Wow! Our stubbed data is now colocated next to our actual endpoint we are trying to mock! Once we have a real API we want to hit, we can just remove that second middleware function and everything will work exactly the same.

<< PREV
Supervisors