import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { buildApp } from "../../src/app.js"; describe("Module API routes", () => { let app: ReturnType; let cookie = ""; const stamp = Date.now().toString(36); async function api(method: string, url: string, body?: unknown) { const response = await app.inject({ method, url, headers: { ...(cookie ? { cookie } : {}), ...(body ? { "content-type": "application/json" } : {}), }, payload: body ? JSON.stringify(body) : undefined, }); const setCookie = response.headers["set-cookie"]; if (setCookie) cookie = String(Array.isArray(setCookie) ? setCookie[0] : setCookie).split(";")[0]!; return { statusCode: response.statusCode, body: JSON.parse(response.body), }; } beforeAll(async () => { app = buildApp(); await app.ready(); const login = await api("POST", "/api/auth/login", { email: "owner@example.com", password: "correct-password", }); expect(login.statusCode).toBe(200); }); afterAll(async () => { await app.prisma.database.deleteMany({ where: { name: { startsWith: `module_${stamp}` } }, }); await app.prisma.notification.deleteMany({ where: { title: { startsWith: `Module notification ${stamp}` } }, }); await app.prisma.user.deleteMany({ where: { email: `module-${stamp}@example.com` } }); await app.close(); }); it("supports database create, detail, update, user grant, and delete", async () => { const create = await api("POST", "/api/databases", { name: `module_${stamp}` }); expect(create.statusCode).toBe(201); const id = create.body.data.id as string; const detail = await api("GET", `/api/databases/${id}`); expect(detail.statusCode).toBe(200); expect(detail.body.data.name).toBe(`module_${stamp}`); const update = await api("PUT", `/api/databases/${id}`, { tables: 7, connections: 2 }); expect(update.statusCode).toBe(200); expect(update.body.data.tables).toBe(7); const grant = await api("POST", `/api/databases/${id}/users`, { username: `module_user_${stamp}`, }); expect(grant.statusCode).toBe(200); expect(grant.body.data.users).toContain(`module_user_${stamp}`); const deleted = await api("DELETE", `/api/databases/${id}`); expect(deleted.statusCode).toBe(200); expect(deleted.body.data.deleted).toBe(id); }); it("supports notification create, mark read, read all, and delete", async () => { const create = await api("POST", "/api/notifications", { title: `Module notification ${stamp}`, body: "Created by integration test.", category: "system", }); expect(create.statusCode).toBe(201); const id = create.body.data.id as string; const update = await api("PUT", `/api/notifications/${id}`, { read: true }); expect(update.statusCode).toBe(200); expect(update.body.data.read).toBe(true); const readAll = await api("POST", "/api/notifications/read-all"); expect(readAll.statusCode).toBe(200); expect(readAll.body.data.updated).toBeGreaterThanOrEqual(0); const deleted = await api("DELETE", `/api/notifications/${id}`); expect(deleted.statusCode).toBe(200); }); it("supports account settings update and safe security jobs", async () => { const settings = await api("PUT", "/api/settings", { theme: "dark", sessionTimeout: 60, locale: "en-US", timezone: "Etc/UTC", }); expect(settings.statusCode).toBe(200); expect(settings.body.data.theme).toBe("dark"); const scan = await api("POST", "/api/security/scan"); expect(scan.statusCode).toBe(200); expect(scan.body.data.status).toBe("running"); }); it("supports user create, update, roles list, and delete", async () => { const create = await api("POST", "/api/users", { name: `Module User ${stamp}`, email: `module-${stamp}@example.com`, role: "developer", permissions: ["dashboard_read", "tools_read"], }); expect(create.statusCode).toBe(201); const id = create.body.data.id as string; const update = await api("PUT", `/api/users/${id}`, { role: "auditor", twoFactorEnabled: true, permissions: ["dashboard_read", "audit_read"], }); expect(update.statusCode).toBe(200); expect(update.body.data.role).toBe("auditor"); expect(update.body.data.twoFactorEnabled).toBe(true); const roles = await api("GET", "/api/roles"); expect(roles.statusCode).toBe(200); expect(roles.body.data.length).toBeGreaterThan(0); const deleted = await api("DELETE", `/api/users/${id}`); expect(deleted.statusCode).toBe(200); expect(deleted.body.data.deleted).toBe(id); }); });