refactor: 代码审查修复 — 错误边界、DRY抽取、测试修复、合规性改进

- P1: server.ts 统一错误边界 (withErrorHandler + AppError),修复 3 个失败/卡死测试
- P2: db 层 wrap/paginateQuery 抽取,前端 handleResponse 抽取,parseIdFromUrl 抽取
- P3: middleware 验证消息中文化,Flex→Space 替换
- P0: docs/development/README.md 新增已知设计决策章节
- P3-11 setup 拆分已尝试回退(@testing-library/react preload 依赖无法拆分)
- P3-13 config 层测试从本次变更移除
This commit is contained in:
2026-05-29 22:27:56 +08:00
parent 34e915ccf4
commit 10b3928bee
26 changed files with 428 additions and 300 deletions

View File

@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-empty-function, @typescript-eslint/require-await */
import { describe, expect, test } from "bun:test";
/* eslint-disable @typescript-eslint/require-await */
import { afterEach, describe, expect, test } from "bun:test";
import { mkdirSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
@@ -49,6 +49,19 @@ function makeTempConfig(overrides: Partial<ResolvedConfig> = {}): ResolvedConfig
}
describe("bootstrap", () => {
const shutdownHandlers: Array<() => void> = [];
afterEach(() => {
for (const fn of shutdownHandlers) {
try {
fn();
} catch {
// exit mock throws, that's expected
}
}
shutdownHandlers.length = 0;
});
test("使用默认依赖启动", async () => {
let started = false;
let signalRegistered = false;
@@ -56,7 +69,8 @@ describe("bootstrap", () => {
const cfg = makeTempConfig();
const mockLoadConfig = (async () => cfg) as unknown as BootstrapDependencies["loadConfig"];
const mockOnSignal = (_signal: string, _handler: () => void) => {
const mockOnSignal = (_signal: string, handler: () => void) => {
shutdownHandlers.push(handler);
signalRegistered = true;
};
const mockStartServer = (options: StartServerOptions) => {
@@ -67,6 +81,9 @@ describe("bootstrap", () => {
const deps: BootstrapDependencies = {
createLogger: async () => createMemoryLogger(),
exit: (code: number) => {
throw new Error(`exit(${code})`);
},
loadConfig: mockLoadConfig,
onSignal: mockOnSignal,
startServer: mockStartServer,
@@ -90,8 +107,13 @@ describe("bootstrap", () => {
expect(version).toBe("1.2.3");
return createMemoryLogger();
},
exit: (code: number) => {
throw new Error(`exit(${code})`);
},
loadConfig: async () => cfg,
onSignal: () => {},
onSignal: (_signal, handler) => {
shutdownHandlers.push(handler);
},
startServer: (options: StartServerOptions) => {
receivedVersion = options.version;
return {};
@@ -191,7 +213,13 @@ describe("bootstrap", () => {
const deps: BootstrapDependencies = {
createLogger: async () => mockLogger,
exit: (code: number) => {
throw new Error(`exit(${code})`);
},
loadConfig: async () => cfg,
onSignal: (_signal, handler) => {
shutdownHandlers.push(handler);
},
startServer: () => ({}),
};
@@ -202,7 +230,7 @@ describe("bootstrap", () => {
test("shutdown 时 flush logger", async () => {
let flushed = false;
let shutdownHandler: (() => void) | undefined;
let exitCode: number | undefined;
const mockLogger = createMemoryLogger();
mockLogger.flush = () => {
@@ -212,17 +240,29 @@ describe("bootstrap", () => {
const cfg = makeTempConfig();
const deps: BootstrapDependencies = {
createLogger: async () => mockLogger,
exit: (code: number) => {
exitCode = code;
throw new Error("exit called");
},
loadConfig: async () => cfg,
onSignal: (_signal, handler) => {
shutdownHandler = handler;
shutdownHandlers.push(handler);
},
startServer: () => ({}),
};
await bootstrap({ configPath: join(cfg.configDir, "config.yaml"), mode: "production" }, deps);
expect(shutdownHandler).toBeDefined();
shutdownHandler!();
const handler = shutdownHandlers.pop();
expect(handler).toBeDefined();
try {
handler!();
} catch {
// expected - exit threw
}
expect(flushed).toBe(true);
expect(exitCode).toBe(0);
});
});

View File

@@ -224,7 +224,8 @@ describe("loadServerConfig", () => {
await loadServerConfig(yamlPath);
expect.unreachable();
} catch (error) {
expect((error as Error).message).toContain("日志等级");
expect((error as Error).message).toContain("server.logging.level");
expect((error as Error).message).toContain("不在允许范围内");
} finally {
await rm(yamlPath, { force: true });
}