Files
Clarium/src/test/helpers.tsx
T
mroberts 9d7b0e805c style: drop redundant comments and apply formatting
Frontend now uses double quotes and semicolons. No behaviour change.
2026-10-02 15:06:56 -05:00

72 lines
2.2 KiB
TypeScript

import { render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MemoryRouter } from "react-router";
import { vi } from "vitest";
import type { Book, Genre, User } from "../api";
import { AppRoutes } from "../App";
import { AuthProvider } from "../auth/AuthContext";
export const alice: User = { id: 1, username: "alice" };
export const genres: Genre[] = [
{ id: 3, name: "Fantasy" },
{ id: 5, name: "Science Fiction" },
];
export const dune: Book = {
id: 7,
title: "Dune",
author: "Frank Herbert",
genre: { id: 5, name: "Science Fiction" },
total_pages: 380,
current_page: 142,
status: "reading",
created_at: "2026-10-01T10:00:00+00:00",
updated_at: "2026-10-01T10:00:00+00:00",
};
type Reply = [status: number, body?: unknown];
type Handler = (request: { body: unknown; url: URL }) => Reply;
export type Call = { method: string; path: string; body: unknown };
export function mockApi(routes: Record<string, Handler>): Call[] {
const calls: Call[] = [];
vi.stubGlobal(
"fetch",
vi.fn(async (input: string, init: RequestInit = {}) => {
const url = new URL(input, "http://localhost");
const method = init.method ?? "GET";
const body =
typeof init.body === "string" ? JSON.parse(init.body) : undefined;
calls.push({ method, path: url.pathname + url.search, body });
const handler = routes[`${method} ${url.pathname}`];
const [status, data] = handler
? handler({ body, url })
: [500, { error: `No mock for ${method} ${url.pathname}` }];
return new Response(status === 204 ? null : JSON.stringify(data), {
status,
headers: { "Content-Type": "application/json" },
});
}),
);
return calls;
}
export function signedIn(routes: Record<string, Handler> = {}): Call[] {
return mockApi({
"GET /api/auth/me": () => [200, alice],
"GET /api/genres": () => [200, genres],
...routes,
});
}
export function renderApp(url: string) {
const user = userEvent.setup();
render(
<MemoryRouter initialEntries={[url]}>
<AuthProvider>
<AppRoutes />
</AuthProvider>
</MemoryRouter>,
);
return user;
}