import { MySqlContainer } from '@testcontainers/mysql'; import type { StartedTestContainer } from 'testcontainers'; import { execSync } from 'node:child_process'; import { getPrisma, disconnectPrisma } from '../src/lib/prisma.js'; import { createApp } from '../src/app.js'; import { bootstrapAdmin } from '../src/services/auth.service.js'; // 注:MySqlContainer 默认 user=root password=test let container: StartedTestContainer | null = null; export async function setupApp() { if (!container) { container = await new MySqlContainer('mysql:8').withDatabase('t').start(); process.env.DATABASE_URL = `mysql://root:test@${container.getHost()}:${container.getMappedPort(3306)}/t`; process.env.INGEST_TOKEN = 'dev-ingest-token-1234'; process.env.JWT_SECRET = 'dev-jwt-secret-1234'; process.env.ADMIN_USERNAME = 'admin'; process.env.ADMIN_PASSWORD = 'admin-password-1234'; execSync('npx prisma migrate deploy', { stdio: 'inherit', env: process.env }); } const prisma = getPrisma(); await bootstrapAdmin(); // 确保 admin 存在(auth 测试需要) const app = createApp(); return { app, prisma }; } export async function resetDb() { const prisma = getPrisma(); await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS=0'); for (const t of ['chat_messages', 'inquiries', 'customers', 'users']) { await prisma.$executeRawUnsafe(`DELETE FROM ${t}`); } await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS=1'); await bootstrapAdmin(); // resetDb 清了 users,重新 seed admin } export async function teardown() { await disconnectPrisma(); await container?.stop(); container = null; }