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( "/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 400 if X-Account-Id header is missing", async () => { const signup = await signupUser(app, "user@example.com", "Org"); const { accessToken } = signup.json(); const res = await app.inject({ method: "GET", url: "/test-account-route", headers: { authorization: `Bearer ${accessToken}` }, }); expect(res.statusCode).toBe(400); expect(res.json().error).toMatch(/X-Account-Id/); }); 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: "/test-account-route", headers: { authorization: `Bearer ${accessToken}`, "x-account-id": "00000000-0000-0000-0000-000000000000", }, }); 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: "/test-account-route", headers: { authorization: `Bearer ${accessToken}`, "x-account-id": accounts[0].id, }, }); 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: "/test-account-route", }); expect(res.statusCode).toBe(401); }); });