2026-08-28 22:09:40 +08:00

68 lines
2.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { existsSync, mkdtempSync, readdirSync, realpathSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { basename, dirname, join, resolve, sep } from 'node:path'
import { spawnSync } from 'node:child_process'
import { fileURLToPath } from 'node:url'
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..')
const testPrefix = 'yyd-notification-center-test-'
const testRoot = mkdtempSync(join(tmpdir(), testPrefix))
const databasePath = join(testRoot, 'notifications.db')
// Prisma 的 SQLite file URL 必须使用正斜杠;Windows 原生反斜杠会让 schema-engine 无细节退出。
const databaseUrl = `file:${databasePath.split(sep).join('/')}`
const childEnv = { ...process.env, DATABASE_URL: databaseUrl }
// Prisma 5.22 的 Windows schema-engine 在部分主机未初始化 Rust 日志时会无细节提前退出。
// 只在 Windows 测试子进程中启用;Linux/Docker 不受影响,也不会记录数据库内容或密钥。
if (process.platform === 'win32') childEnv.RUST_LOG = 'trace'
const runNode = (args) => {
const result = spawnSync(process.execPath, args, {
cwd: repoRoot,
env: childEnv,
stdio: 'inherit',
})
if (result.error) throw result.error
return result.status ?? 1
}
const removeTestRoot = () => {
const resolvedTemp = realpathSync(tmpdir())
const resolvedTestRoot = realpathSync(testRoot)
const isTempChild = resolvedTestRoot.startsWith(`${resolvedTemp}${sep}`)
if (!isTempChild || !basename(resolvedTestRoot).startsWith(testPrefix)) {
throw new Error(`拒绝清理非测试临时目录: ${resolvedTestRoot}`)
}
rmSync(resolvedTestRoot, { recursive: true, force: true })
if (existsSync(resolvedTestRoot)) throw new Error('测试临时目录清理失败')
}
let exitCode = 0
try {
const prismaCli = resolve(repoRoot, 'node_modules', 'prisma', 'build', 'index.js')
// cwd 已固定为 repoRoot;避免 Windows schema-engine 处理含空格的绝对 schema 路径失败。
const schema = 'prisma/schema.prisma'
exitCode = runNode([prismaCli, 'migrate', 'deploy', '--schema', schema])
if (exitCode === 0) {
const tsxCli = resolve(repoRoot, 'node_modules', 'tsx', 'dist', 'cli.mjs')
const testsDirectory = resolve(repoRoot, 'src', '__tests__')
const testFiles = readdirSync(testsDirectory)
.filter((name) => name.endsWith('.test.ts'))
.sort()
.map((name) => resolve(testsDirectory, name))
if (testFiles.length === 0) throw new Error('未找到测试文件')
exitCode = runNode([tsxCli, '--test', '--test-concurrency=1', ...testFiles])
}
} catch (error) {
console.error('[test-runner]', error instanceof Error ? error.message : String(error))
exitCode = 1
} finally {
try {
removeTestRoot()
} catch (error) {
console.error('[test-runner-cleanup]', error instanceof Error ? error.message : String(error))
exitCode = 1
}
}
process.exitCode = exitCode