Files
GearBox/tests/helpers/db.ts
2026-04-18 16:15:40 +02:00

78 lines
1.9 KiB
TypeScript

import { PGlite } from "@electric-sql/pglite";
import { sql } from "drizzle-orm";
import { drizzle } from "drizzle-orm/pglite";
import { migrate } from "drizzle-orm/pglite/migrator";
import * as schema from "../../src/db/schema.ts";
type Db = ReturnType<typeof drizzle<typeof schema>>;
// Cache: one PGlite instance per test file (per worker)
let cachedClient: PGlite | null = null;
let cachedDb: Db | null = null;
async function getOrCreateDb(): Promise<Db> {
if (cachedDb) return cachedDb;
cachedClient = new PGlite();
cachedDb = drizzle(cachedClient, { schema });
await migrate(cachedDb, { migrationsFolder: "./drizzle-pg" });
return cachedDb;
}
// Truncation order respects foreign keys (children first)
const TRUNCATE_TABLES = [
"shares",
"setup_items",
"setups",
"thread_candidates",
"threads",
"community_prices",
"market_prices",
"items",
"global_item_tags",
"global_items",
"tags",
"oauth_tokens",
"oauth_codes",
"oauth_clients",
"api_keys",
"settings",
"categories",
"manufacturers",
"users",
];
export async function createTestDb() {
const db = await getOrCreateDb();
// Truncate all tables and reset sequences (fast reset, no PGlite restart)
for (const t of TRUNCATE_TABLES) {
await db.execute(sql.raw(`TRUNCATE TABLE "${t}" RESTART IDENTITY CASCADE`));
}
// Seed a test user
const [user] = await db
.insert(schema.users)
.values({ logtoSub: "test-user-sub" })
.returning();
// Seed per-user Uncategorized category
await db
.insert(schema.categories)
.values({ name: "Uncategorized", icon: "package", userId: user.id });
return { db, userId: user.id };
}
export async function createSecondTestUser(db: Db) {
const [user] = await db
.insert(schema.users)
.values({ logtoSub: "test-user-2-sub" })
.returning();
await db
.insert(schema.categories)
.values({ name: "Uncategorized", icon: "package", userId: user.id });
return user.id;
}