import { describe, it, expect, beforeAll, afterAll } from "vitest"; import Fastify from "fastify"; import jwt from "jsonwebtoken"; import companySettingsRoutes from "../routes/admin/company-settings"; import prisma from "../config/database"; import { config } from "../config/env"; // Fixture prefix so cleanup never touches real data. const N = "settings_numbering_test_"; let app: ReturnType; let token: string; // Snapshot the prior values of the four numbering fields we mutate so we can // restore them in afterAll — other tests read company_settings and must not be // poisoned by our writes. let priorValues: { issued_order_number_pattern: string | null; issued_order_type_code: string | null; project_number_pattern: string | null; project_type_code: string | null; } | null = null; let settingsId: number | null = null; beforeAll(async () => { app = Fastify({ logger: false }); await app.register(companySettingsRoutes, { prefix: "/api/admin/company-settings", }); // Clean up any leftover fixture from a previous failed run. await prisma.users .deleteMany({ where: { username: { startsWith: N } } }) .catch(() => {}); // Attach the fixture user to the admin role so the PUT/GET permission guards // (settings.company / settings.system) pass. const adminRole = await prisma.roles.findFirst({ where: { name: "admin" } }); if (!adminRole) throw new Error("Test setup: no admin role found — seed the database"); const user = await prisma.users.create({ data: { username: `${N}user`, email: `${N}user@test.local`, password_hash: "x", first_name: "Settings", last_name: "Test", is_active: true, totp_enabled: false, role_id: adminRole.id, }, }); token = jwt.sign( { sub: user.id, username: user.username, role: "admin" }, config.jwt.secret, { expiresIn: config.jwt.accessTokenExpiry }, ); // Snapshot existing settings so we can restore after the suite. const existing = await prisma.company_settings.findFirst({ select: { id: true, issued_order_number_pattern: true, issued_order_type_code: true, project_number_pattern: true, project_type_code: true, }, }); if (existing) { settingsId = existing.id; priorValues = { issued_order_number_pattern: existing.issued_order_number_pattern, issued_order_type_code: existing.issued_order_type_code, project_number_pattern: existing.project_number_pattern, project_type_code: existing.project_type_code, }; } }); afterAll(async () => { // Restore the four numbering fields to their pre-test values. if (settingsId !== null && priorValues !== null) { await prisma.company_settings .update({ where: { id: settingsId }, data: priorValues }) .catch(() => {}); } await prisma.users .deleteMany({ where: { username: { startsWith: N } } }) .catch(() => {}); await app.close(); }); describe("company-settings numbering — issued orders + projects round-trip", () => { it("persists and returns issued_order_* and project_* numbering fields", async () => { const payload = { issued_order_number_pattern: "{YY}V{NNNN}", issued_order_type_code: "72", project_number_pattern: "{YY}P{NNNN}", project_type_code: "73", }; const put = await app.inject({ method: "PUT", url: "/api/admin/company-settings/", headers: { authorization: `Bearer ${token}` }, payload, }); expect(put.statusCode).toBe(200); expect(put.json().success).toBe(true); const get = await app.inject({ method: "GET", url: "/api/admin/company-settings/", headers: { authorization: `Bearer ${token}` }, }); expect(get.statusCode).toBe(200); const data = get.json().data; expect(data.issued_order_number_pattern).toBe("{YY}V{NNNN}"); expect(data.issued_order_type_code).toBe("72"); expect(data.project_number_pattern).toBe("{YY}P{NNNN}"); expect(data.project_type_code).toBe("73"); }); it("requires authentication", async () => { const res = await app.inject({ method: "GET", url: "/api/admin/company-settings/", }); expect(res.statusCode).toBe(401); }); });