55 lines
2.3 KiB
TypeScript
55 lines
2.3 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { IncomingMessage, ServerResponse } from "node:http";
|
|
import { Socket } from "node:net";
|
|
import { test } from "node:test";
|
|
import { buildContext, type User } from "./context.ts";
|
|
import { createLogger } from "./logger.ts";
|
|
|
|
// A req/res pair without a live server — enough to build and inspect a context.
|
|
function reqRes(url?: string): { req: IncomingMessage; res: ServerResponse } {
|
|
const req = new IncomingMessage(new Socket());
|
|
if (url !== undefined) req.url = url;
|
|
req.method = "GET";
|
|
return { req, res: new ServerResponse(req) };
|
|
}
|
|
|
|
test("buildContext parses the URL, exposes query, and defaults to an anonymous user", () => {
|
|
const { req, res } = reqRes("/users?q=ann&page=2");
|
|
const ctx = buildContext(req, res);
|
|
assert.equal(ctx.req, req);
|
|
assert.equal(ctx.res, res);
|
|
assert.equal(ctx.url.pathname, "/users");
|
|
assert.equal(ctx.query, ctx.url.searchParams); // same instance, not a copy
|
|
assert.equal(ctx.query.get("q"), "ann");
|
|
assert.equal(ctx.query.get("page"), "2");
|
|
assert.equal(ctx.user, null);
|
|
assert.deepEqual(ctx.roles, []);
|
|
assert.deepEqual(ctx.params, {});
|
|
});
|
|
|
|
test("buildContext threads path params supplied by the router", () => {
|
|
const { req, res } = reqRes("/users/42");
|
|
const ctx = buildContext(req, res, { params: { id: "42" } });
|
|
assert.equal(ctx.params.id, "42");
|
|
});
|
|
|
|
test("buildContext threads the user and derives roles from it", () => {
|
|
const { req, res } = reqRes("/");
|
|
const user: User = { email: "a@b.c", id: "u1", roles: ["admin", "editor"] };
|
|
const ctx = buildContext(req, res, { user });
|
|
assert.equal(ctx.user, user);
|
|
assert.equal(ctx.roles, user.roles); // same reference, never a divergent copy — buildContext is the only writer
|
|
});
|
|
|
|
test("buildContext defaults a missing request URL to /", () => {
|
|
const { req, res } = reqRes();
|
|
assert.equal(buildContext(req, res).url.pathname, "/");
|
|
});
|
|
|
|
test("buildContext provides a logger: a silent default, or the host's request logger", () => {
|
|
const { req, res } = reqRes("/");
|
|
assert.equal(typeof buildContext(req, res).log.info, "function"); // always present (silent default)
|
|
const log = createLogger({ level: "none" });
|
|
assert.equal(buildContext(req, res, { log }).log, log); // host's request logger threads through
|
|
});
|