withTestDb sets up an in-memory SQLite handle with migrations applied, swaps the production singleton via _setDbForTest, and restores in a finally block. installFetchStub captures every outbound request and throws if restored twice. requestApp wraps Oak's app.handle so route tests can run without listen(). stubAuthenticate flips the server's authenticator indirection.
58 lines
1.3 KiB
TypeScript
58 lines
1.3 KiB
TypeScript
export type FetchHandler = (
|
|
req: Request,
|
|
) => Response | Promise<Response>;
|
|
|
|
export type CapturedRequest = {
|
|
method: string;
|
|
url: string;
|
|
headers: Headers;
|
|
body: string;
|
|
};
|
|
|
|
export type FetchStub = {
|
|
calls: CapturedRequest[];
|
|
restore: () => void;
|
|
};
|
|
|
|
export const installFetchStub = (handler: FetchHandler): FetchStub => {
|
|
const original = globalThis.fetch;
|
|
const calls: CapturedRequest[] = [];
|
|
let restored = false;
|
|
|
|
globalThis.fetch = async (input, init) => {
|
|
const req = new Request(input as RequestInfo, init);
|
|
const body = req.method === "GET" || req.method === "HEAD"
|
|
? ""
|
|
: await req.clone().text();
|
|
calls.push({
|
|
method: req.method,
|
|
url: req.url,
|
|
headers: new Headers(req.headers),
|
|
body,
|
|
});
|
|
return await handler(req);
|
|
};
|
|
|
|
return {
|
|
calls,
|
|
restore: () => {
|
|
if (restored) throw new Error("FetchStub.restore() called twice");
|
|
restored = true;
|
|
globalThis.fetch = original;
|
|
},
|
|
};
|
|
};
|
|
|
|
export const jsonResponse = (
|
|
body: unknown,
|
|
init: ResponseInit = {},
|
|
): Response => {
|
|
return new Response(JSON.stringify(body), {
|
|
status: init.status ?? 200,
|
|
headers: { "Content-Type": "application/json", ...(init.headers ?? {}) },
|
|
});
|
|
};
|
|
|
|
export const errorResponse = (status: number, text = "error"): Response =>
|
|
new Response(text, { status });
|