import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { Elysia } from "elysia"; import { Kysely, SqliteDialect } from "kysely"; import SqliteDatabase from "better-sqlite3"; import type { db } from "dbtype"; import { createSettingsRouter } from "../src/route/settings.ts"; import { error_handler } from "../src/route/error_handler.ts"; import { get_setting, refreshSetting } from "../src/SettingConfig.ts"; import { Permission } from "../src/permission/permission.ts"; const normalizeError = (error: unknown): Error => { if (error instanceof Error) { return error; } if (typeof error === "string") { return new Error(error); } try { return new Error(JSON.stringify(error)); } catch (_err) { return new Error("Unknown error"); } }; describe("settings router", () => { let sqlite: InstanceType; let database: Kysely; beforeAll(async () => { process.env.SERVER_HOST = "127.0.0.1"; process.env.SERVER_PORT = "3000"; process.env.SERVER_MODE = "development"; process.env.JWT_SECRET_KEY = "test-secret"; sqlite = new SqliteDatabase(":memory:"); const dialect = new SqliteDialect({ database: sqlite }); database = new Kysely({ dialect }); await database.schema .createTable("app_config") .addColumn("key", "text", (col) => col.primaryKey()) .addColumn("value", "text") .execute(); await refreshSetting(database); }); afterAll(async () => { await database.destroy(); sqlite.close(); }); beforeEach(async () => { await database.deleteFrom("app_config").execute(); await refreshSetting(database); }); const createTestApp = (username: string) => { const user = { username, permission: [] as string[] }; return new Elysia({ name: `settings-test-${username}` }) .state("user", user) .derive(() => ({ user })) .onError((context) => error_handler({ code: typeof context.code === "number" ? String(context.code) : context.code, error: normalizeError(context.error), set: context.set, }), ) .use(createSettingsRouter(database)); }; it("rejects access for non-admin users", async () => { const app = createTestApp("guest"); try { const response = await app.handle(new Request("http://localhost/settings")); expect(response.status).toBe(403); } finally { if (app.server) { await app.stop(); } } }); it("returns current configuration for admin", async () => { const app = createTestApp("admin"); try { const response = await app.handle(new Request("http://localhost/settings")); expect(response.status).toBe(200); const payload = await response.json(); const expected = get_setting(); expect(payload).toMatchObject({ persisted: { secure: expected.secure, cli: expected.cli, forbid_remote_admin_login: expected.forbid_remote_admin_login, guest: expected.guest, }, env: { hostname: expected.hostname, port: expected.port, mode: expected.mode, }, }); expect(Array.isArray(payload.permissions)).toBe(true); expect(new Set(payload.permissions)).toEqual(new Set(Object.values(Permission))); } finally { if (app.server) { await app.stop(); } } }); it("updates persisted settings and returns the new state", async () => { const app = createTestApp("admin"); try { const request = new Request("http://localhost/settings", { method: "PATCH", headers: { "content-type": "application/json" }, body: JSON.stringify({ secure: false, cli: true, guest: ["QueryContent"], forbid_remote_admin_login: false, }), }); const response = await app.handle(request); expect(response.status).toBe(200); const payload = await response.json(); expect(payload.persisted).toEqual({ secure: false, cli: true, forbid_remote_admin_login: false, guest: ["QueryContent"], }); // A follow-up GET should reflect the updated values const followUp = await app.handle(new Request("http://localhost/settings")); expect(followUp.status).toBe(200); const followUpPayload = await followUp.json(); expect(followUpPayload.persisted).toEqual({ secure: false, cli: true, forbid_remote_admin_login: false, guest: ["QueryContent"], }); } finally { if (app.server) { await app.stop(); } } }); });