76 lines
3.0 KiB
TypeScript
76 lines
3.0 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const poolConstructor = vi.hoisted(() => vi.fn());
|
|
const betterAuthMock = vi.hoisted(() => vi.fn());
|
|
const drizzleAdapterMock = vi.hoisted(() => vi.fn());
|
|
const serveMock = vi.hoisted(() => vi.fn());
|
|
const processOnSpy = vi.hoisted(() => vi.fn());
|
|
|
|
vi.mock("pg", () => ({ Pool: poolConstructor }));
|
|
vi.mock("better-auth", () => ({ betterAuth: betterAuthMock }));
|
|
vi.mock("better-auth/adapters/drizzle", () => ({ drizzleAdapter: drizzleAdapterMock }));
|
|
vi.mock("@hono/node-server", () => ({ serve: serveMock }));
|
|
|
|
describe("Ekklesia API import safety", () => {
|
|
const originalEnv = { ...process.env };
|
|
const originalProcessOn = process.on.bind(process);
|
|
|
|
beforeEach(() => {
|
|
poolConstructor.mockClear();
|
|
betterAuthMock.mockClear();
|
|
drizzleAdapterMock.mockClear();
|
|
serveMock.mockClear();
|
|
processOnSpy.mockClear();
|
|
for (const key of Object.keys(process.env)) {
|
|
if (!(key in originalEnv)) {
|
|
delete process.env[key];
|
|
}
|
|
}
|
|
process.env = { ...originalEnv };
|
|
process.on = originalProcessOn;
|
|
});
|
|
|
|
it("does not construct a database pool, Better Auth, or an HTTP server merely by importing the app factory", async () => {
|
|
await import("../src/app.js");
|
|
|
|
expect(poolConstructor).not.toHaveBeenCalled();
|
|
expect(betterAuthMock).not.toHaveBeenCalled();
|
|
expect(serveMock).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("does not construct a database pool, Better Auth, or an HTTP server merely by importing configuration", async () => {
|
|
await import("../src/config.js");
|
|
|
|
expect(poolConstructor).not.toHaveBeenCalled();
|
|
expect(betterAuthMock).not.toHaveBeenCalled();
|
|
expect(serveMock).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("does not read environment variables, connect to PostgreSQL, construct Better Auth, start a server, or install signal handlers merely by importing the executable server module", async () => {
|
|
// Deliberately leave every runtime-required environment variable unset. If importing this
|
|
// module performed any runtime composition, missing configuration would throw here.
|
|
delete process.env.DATABASE_URL;
|
|
delete process.env.EKKLESIA_IDENTITY_SECRET;
|
|
delete process.env.EKKLESIA_IDENTITY_BASE_URL;
|
|
delete process.env.EKKLESIA_IDENTITY_TRUSTED_ORIGINS;
|
|
const onSpy = vi.spyOn(process, "on").mockImplementation(processOnSpy);
|
|
|
|
await expect(import("../src/server.js")).resolves.toBeDefined();
|
|
|
|
expect(poolConstructor).not.toHaveBeenCalled();
|
|
expect(betterAuthMock).not.toHaveBeenCalled();
|
|
expect(drizzleAdapterMock).not.toHaveBeenCalled();
|
|
expect(serveMock).not.toHaveBeenCalled();
|
|
expect(processOnSpy).not.toHaveBeenCalled();
|
|
onSpy.mockRestore();
|
|
});
|
|
|
|
it("exposes startApi and main as explicit functions without invoking them at import time", async () => {
|
|
const module = await import("../src/server.js");
|
|
|
|
expect(typeof module.startApi).toBe("function");
|
|
expect(typeof module.main).toBe("function");
|
|
expect(serveMock).not.toHaveBeenCalled();
|
|
});
|
|
});
|