test: 测试体系全面优化,修复 Windows SQLite EBUSY 和前端产品缺陷
测试基础设施 - 统一 SQLite 测试 DB/临时目录 helper(tests/helpers.ts),支持 Windows EBUSY 重试清理 - 测试库使用 PRAGMA journal_mode=DELETE 避免 WAL 句柄延迟 - 路由 handler 测试改用 createMigratedMemoryTestDatabase 避免 File DB 锁 - SQLite 聚焦 --rerun-each=20 全部通过(720 pass) 后端测试补强 - 新增 tests/server/app.test.ts 真实 startServer 集成测试 - 覆盖 /api/meta、项目 CRUD、错误路径、静态 fallback、安全 header - bootstrap/logger 测试捕获预期输出,消除测试噪音 前端测试补强 - 移除 .ant-* 内部类名依赖,改为角色/文本/导航/请求契约断言 - 项目页补充搜索、Tab 切换、表单、表格操作、错误反馈行为测试 - 新增 hooks(use-theme-preference、use-sidebar-collapsed、use-projects)纯逻辑测试 - 新增 ErrorBoundary 错误展示和刷新按钮测试 - 新增搜索清空行为测试 - 测试 setup 过滤 antd/rc-trigger NaN height warning 产品修复(测试暴露) - 修复 ProjectToolbar 搜索框无法输入(新增 draftKeyword 状态) - 加固 ProjectFormModal 表单字段同步(useEffect 替代不可靠的 afterOpenChange) - 清理 ProjectFormModal 冗余 afterOpenChange 同步逻辑 重构与合规 - ProjectContext 拆分为三文件满足 React Fast Refresh 规则 - use-projects.ts 导出内部 helper 函数供测试验证 - scripts/build.ts 提取纯生成函数供测试使用,修复构建步骤日志编号 - 修复 build 测试覆盖真实生成逻辑 文档同步 - 更新后端/前端/开发文档测试规范、质量门禁和 helper 使用说明
This commit is contained in:
114
scripts/build.ts
114
scripts/build.ts
@@ -11,6 +11,67 @@ const buildDir = join(projectRoot, ".build");
|
||||
const executablePath = join(projectRoot, `dist/${APP.name}`);
|
||||
const packageJsonPath = join(projectRoot, "package.json");
|
||||
|
||||
export function createMigrationsDataSource(records: Array<{ checksum: string; id: string; sql: string }>): string {
|
||||
return [
|
||||
`import type { MigrationRecord } from "../src/server/db/load-migrations";`,
|
||||
``,
|
||||
`export const MIGRATIONS: MigrationRecord[] = [`,
|
||||
...records.map(
|
||||
(r) =>
|
||||
` { id: ${JSON.stringify(r.id)}, sql: ${JSON.stringify(r.sql)}, checksum: ${JSON.stringify(r.checksum)} },`,
|
||||
),
|
||||
`];`,
|
||||
``,
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
export function createServerEntrySource(version: string): string {
|
||||
return [
|
||||
`import { bootstrap } from "../src/server/bootstrap";`,
|
||||
`import { parseRuntimeArgs } from "../src/server/config";`,
|
||||
`import { createConsoleFallback } from "../src/server/logger";`,
|
||||
`import { MIGRATIONS } from "./migrations-data";`,
|
||||
`import { staticAssets } from "./static-assets";`,
|
||||
"",
|
||||
`const APP_VERSION = "${version}" as const;`,
|
||||
"",
|
||||
`async function main() {`,
|
||||
` const { configPath } = parseRuntimeArgs();`,
|
||||
` await bootstrap({ configPath, migrations: MIGRATIONS, mode: "production", staticAssets, version: APP_VERSION });`,
|
||||
`}`,
|
||||
"",
|
||||
`void main().catch((error) => {`,
|
||||
` createConsoleFallback().fatal(\`启动失败: \${error instanceof Error ? error.message : String(error)}\`);`,
|
||||
` process.exit(1);`,
|
||||
`});`,
|
||||
"",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
export function createStaticAssetsSource({
|
||||
fileEntries,
|
||||
importLines,
|
||||
indexHtmlVar,
|
||||
}: {
|
||||
fileEntries: string[];
|
||||
importLines: string[];
|
||||
indexHtmlVar: string;
|
||||
}): string {
|
||||
return [
|
||||
`import type { StaticAssets } from "../src/server/static";`,
|
||||
"",
|
||||
...importLines,
|
||||
"",
|
||||
`export const staticAssets: StaticAssets = {`,
|
||||
` files: {`,
|
||||
...fileEntries,
|
||||
` },`,
|
||||
` indexHtml: Bun.file(${indexHtmlVar}),`,
|
||||
`};`,
|
||||
"",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
async function build() {
|
||||
try {
|
||||
await viteBuild();
|
||||
@@ -98,42 +159,11 @@ async function codeGeneration() {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const staticAssetsTs = [
|
||||
`import type { StaticAssets } from "../src/server/static";`,
|
||||
"",
|
||||
...importLines,
|
||||
"",
|
||||
`export const staticAssets: StaticAssets = {`,
|
||||
` files: {`,
|
||||
...fileEntries,
|
||||
` },`,
|
||||
` indexHtml: Bun.file(${indexHtmlVar}),`,
|
||||
`};`,
|
||||
"",
|
||||
].join("\n");
|
||||
const staticAssetsTs = createStaticAssetsSource({ fileEntries, importLines, indexHtmlVar });
|
||||
|
||||
await writeFile(join(buildDir, "static-assets.ts"), staticAssetsTs);
|
||||
|
||||
const serverEntryTs = [
|
||||
`import { bootstrap } from "../src/server/bootstrap";`,
|
||||
`import { parseRuntimeArgs } from "../src/server/config";`,
|
||||
`import { createConsoleFallback } from "../src/server/logger";`,
|
||||
`import { MIGRATIONS } from "./migrations-data";`,
|
||||
`import { staticAssets } from "./static-assets";`,
|
||||
"",
|
||||
`const APP_VERSION = "${version}" as const;`,
|
||||
"",
|
||||
`async function main() {`,
|
||||
` const { configPath } = parseRuntimeArgs();`,
|
||||
` await bootstrap({ configPath, migrations: MIGRATIONS, mode: "production", staticAssets, version: APP_VERSION });`,
|
||||
`}`,
|
||||
"",
|
||||
`void main().catch((error) => {`,
|
||||
` createConsoleFallback().fatal(\`启动失败: \${error instanceof Error ? error.message : String(error)}\`);`,
|
||||
` process.exit(1);`,
|
||||
`});`,
|
||||
"",
|
||||
].join("\n");
|
||||
const serverEntryTs = createServerEntrySource(version);
|
||||
|
||||
await writeFile(join(buildDir, "server-entry.ts"), serverEntryTs);
|
||||
}
|
||||
@@ -159,17 +189,7 @@ async function generateMigrationsData() {
|
||||
return { checksum, id, sql: sql.trim() };
|
||||
});
|
||||
|
||||
const lines = [
|
||||
`import type { MigrationRecord } from "../src/server/db/load-migrations";`,
|
||||
``,
|
||||
`export const MIGRATIONS: MigrationRecord[] = [`,
|
||||
...records.map(
|
||||
(r) =>
|
||||
` { id: ${JSON.stringify(r.id)}, sql: ${JSON.stringify(r.sql)}, checksum: ${JSON.stringify(r.checksum)} },`,
|
||||
),
|
||||
`];`,
|
||||
``,
|
||||
].join("\n");
|
||||
const lines = createMigrationsDataSource(records);
|
||||
|
||||
await writeFile(join(buildDir, "migrations-data.ts"), lines);
|
||||
console.log(`Embedded ${records.length} migration(s)`);
|
||||
@@ -195,7 +215,7 @@ function toImportSpecifier(fromDir: string, targetPath: string) {
|
||||
}
|
||||
|
||||
async function viteBuild() {
|
||||
console.log("Step 1/3: Vite build...");
|
||||
console.log("Step 1/4: Vite build...");
|
||||
const proc = Bun.spawn(["bunx", "--bun", "vite", "build"], {
|
||||
cwd: projectRoot,
|
||||
stderr: "inherit",
|
||||
@@ -208,4 +228,6 @@ async function viteBuild() {
|
||||
}
|
||||
}
|
||||
|
||||
await build();
|
||||
if (import.meta.main) {
|
||||
await build();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user