mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
ensureDbCompatibility ran ALTER TABLE / CREATE TABLE IF NOT EXISTS on the login, register, token and session paths, mirroring columns every migration under prisma/migrations already creates. The entrypoint applies those migrations before the server listens and stops the boot when one fails, so the mirror never had work to do, and DDL on a request path needs the table's owner: a connection that may only read and write rows fails every login on it. Drop the module, its call sites and the mocks that stubbed it out.
101 lines
3.9 KiB
TypeScript
101 lines
3.9 KiB
TypeScript
import { afterEach, beforeEach, inject, vi } from "vitest";
|
|
|
|
import { quarantineEntryFor } from "../quarantine/quarantine";
|
|
import { watchSwallowedMockErrors } from "../support/swallowed-mock-errors";
|
|
import { prepareWorkerDatabase } from "./worker-database";
|
|
|
|
// Each worker runs against its own clone of the migrated template (see
|
|
// `worker-database.ts`). The URL is final before any application module is
|
|
// imported, so the Prisma singleton is built against the clone.
|
|
process.env.DATABASE_URL = await prepareWorkerDatabase(
|
|
inject("integrationDatabaseUrl"),
|
|
inject("integrationDatabasePlan"),
|
|
);
|
|
process.env.ENCRYPTION_KEY =
|
|
"0000000000000000000000000000000000000000000000000000000000000000";
|
|
delete process.env.ENCRYPTION_KEYS;
|
|
delete process.env.ENCRYPTION_ACTIVE_KEY_ID;
|
|
process.env.API_TOKEN_HMAC_KEY = "integration-test-hmac-key-32-bytes-minimum";
|
|
process.env.SESSION_SECRET = "integration-test-session-secret-32-bytes";
|
|
|
|
/**
|
|
* Leave no background work in flight when an integration test ends — the same
|
|
* contract the unit setup keeps, for the same reason: detached background work
|
|
* logs on its own handle, and a console write that reaches vitest after the
|
|
* worker has begun closing its RPC channel fails the run with
|
|
* `EnvironmentTeardownError: Closing rpc while "onUserConsoleLog" was pending`.
|
|
* This suite has its own config and its own setup file, so the unit hook does
|
|
* not cover it.
|
|
*
|
|
* The import is deferred: this file's whole job is to bridge DATABASE_URL into
|
|
* the worker BEFORE any application module reads it at import time, and a
|
|
* static import here would pull part of the application tree in first.
|
|
*/
|
|
/** A swallowed "missing mock export" error fails its test (see the module). */
|
|
const checkSwallowedMockErrors = watchSwallowedMockErrors();
|
|
|
|
afterEach(async () => {
|
|
const { settleBackgroundTasks } =
|
|
await import("@/lib/logging/background-tasks");
|
|
await settleBackgroundTasks();
|
|
checkSwallowedMockErrors();
|
|
});
|
|
|
|
/** The flaky-test quarantine, as in the unit setup (`vitest.setup.ts`). */
|
|
beforeEach((context) => {
|
|
const entry = quarantineEntryFor(context.task);
|
|
if (entry) {
|
|
context.skip(`quarantined until ${entry.expires} (${entry.issue})`);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Route handlers read cookies and headers through `next/headers`, which only
|
|
* works inside a Next.js request scope. Every file gets the same stand-in,
|
|
* backed by the shared jars in `mock-next-headers.ts`, and the same no-op for
|
|
* the boot-time compatibility probe. A file that needs different behaviour
|
|
* still declares its own `vi.mock`, which takes precedence over this one.
|
|
*/
|
|
vi.mock("next/headers", async () => {
|
|
const { cookieJar, headerJar } = await import("./mock-next-headers");
|
|
return {
|
|
headers: vi.fn(async () => ({
|
|
get: (name: string) => headerJar.get(name.toLowerCase()) ?? null,
|
|
has: (name: string) => headerJar.has(name.toLowerCase()),
|
|
})),
|
|
cookies: vi.fn(async () => ({
|
|
get: (name: string) => {
|
|
const value = cookieJar.get(name);
|
|
return value ? { name, value } : undefined;
|
|
},
|
|
set: (name: string, value: string) => {
|
|
cookieJar.set(name, value);
|
|
},
|
|
delete: (name: string) => {
|
|
cookieJar.delete(name);
|
|
},
|
|
})),
|
|
};
|
|
});
|
|
|
|
/**
|
|
* The same pin the unit setup applies (see `vitest.setup.ts`): the Fitbit
|
|
* suites run before the Web API turndown, whatever the real date, and a test
|
|
* about the turndown flips `isFitbitRetired` itself. The factory imports the
|
|
* module lazily, so nothing of the application loads before DATABASE_URL is
|
|
* bridged above.
|
|
*/
|
|
vi.mock("@/lib/fitbit/retirement", async (importOriginal) => {
|
|
const actual =
|
|
await importOriginal<typeof import("@/lib/fitbit/retirement")>();
|
|
const isFitbitRetired = vi.fn((_now?: Date) => false);
|
|
return {
|
|
...actual,
|
|
isFitbitRetired,
|
|
fitbitRetirement: vi.fn((now?: Date) => ({
|
|
...actual.fitbitRetirement(now),
|
|
ended: isFitbitRetired(now),
|
|
})),
|
|
};
|
|
});
|