eyrun-api/tests/account-context.test.ts
2026-02-08 13:39:33 +01:00

79 lines
2.1 KiB
TypeScript

import { describe, it, expect, beforeAll, afterAll, beforeEach } from "vitest";
import type { FastifyInstance } from "fastify";
import { buildApp } from "../src/app.js";
import { cleanDb, signupUser } from "./helpers.js";
let app: FastifyInstance;
beforeAll(async () => {
app = buildApp();
// Register a test-only account-scoped route as a plugin
// so it runs after authenticate + accountContext are ready
app.register(async (instance) => {
instance.get(
"/accounts/:accountId/test-account-route",
{ preHandler: [instance.authenticate, instance.requireAccount] },
async (request) => {
return { accountId: request.accountId, role: request.membership.role };
},
);
});
await app.ready();
});
afterAll(async () => {
await app.close();
});
beforeEach(async () => {
await cleanDb();
});
describe("requireAccount plugin", () => {
it("returns 403 if user is not a member of the account", async () => {
const signup = await signupUser(app, "user@example.com", "Org");
const { accessToken } = signup.json();
const res = await app.inject({
method: "GET",
url: "/accounts/00000000-0000-0000-0000-000000000000/test-account-route",
headers: {
authorization: `Bearer ${accessToken}`,
},
});
expect(res.statusCode).toBe(403);
expect(res.json().error).toMatch(/not a member/);
});
it("decorates request with accountId and role on success", async () => {
const signup = await signupUser(app, "user@example.com", "Org");
const { accessToken, accounts } = signup.json();
const res = await app.inject({
method: "GET",
url: `/accounts/${accounts[0].id}/test-account-route`,
headers: {
authorization: `Bearer ${accessToken}`,
},
});
expect(res.statusCode).toBe(200);
expect(res.json()).toEqual({
accountId: accounts[0].id,
role: "owner",
});
});
it("returns 401 without auth header", async () => {
const res = await app.inject({
method: "GET",
url: "/accounts/00000000-0000-0000-0000-000000000000/test-account-route",
});
expect(res.statusCode).toBe(401);
});
});