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

@@ -30,9 +30,11 @@ const ARCHIVED_PROJECT: Project = {
updatedAt: "2024-01-02T00:00:00.000Z",
};
function clickLatestConfirmButton() {
const buttons = screen.getAllByRole("button", { name: /OK|确\s*定/ });
fireEvent.click(buttons[buttons.length - 1]!);
async function clickLatestConfirmButton() {
const confirmTexts = await screen.findAllByText(/确\s*定|OK|确认/);
const lastText = confirmTexts[confirmTexts.length - 1]!;
const button = lastText.closest("button") ?? lastText.closest("[role='button']") ?? lastText;
fireEvent.click(button);
}
function createProjectFetchMock(initialProjects: Project[] = [ACTIVE_PROJECT, ARCHIVED_PROJECT]) {
@@ -170,7 +172,7 @@ describe("ProjectsPage", () => {
await waitFor(() => expect(screen.getByPlaceholderText("请输入项目名称")).not.toBeNull());
fireEvent.change(screen.getByPlaceholderText("请输入项目名称"), { target: { value: "新增项目" } });
fireEvent.change(screen.getByPlaceholderText("请输入项目描述"), { target: { value: "新增描述" } });
clickLatestConfirmButton();
await clickLatestConfirmButton();
await waitFor(() => expect(screen.getByText("新增项目")).not.toBeNull());
@@ -200,7 +202,7 @@ describe("ProjectsPage", () => {
await waitFor(() => expect(screen.getByPlaceholderText("请输入项目名称")).not.toBeNull());
fireEvent.change(screen.getByPlaceholderText("请输入项目名称"), { target: { value: "编辑项目" } });
clickLatestConfirmButton();
await clickLatestConfirmButton();
await waitFor(() => expect(onUpdate).toHaveBeenCalled());
expect(updateCalls[0]).toEqual({ data: { name: "编辑项目" }, id: "p1" });
@@ -223,11 +225,11 @@ describe("ProjectsPage", () => {
);
await waitFor(() => expect(screen.getByPlaceholderText("请输入项目名称")).not.toBeNull());
clickLatestConfirmButton();
await clickLatestConfirmButton();
expect(onCreate).not.toHaveBeenCalled();
fireEvent.change(screen.getByPlaceholderText("请输入项目名称"), { target: { value: "失败项目" } });
clickLatestConfirmButton();
await clickLatestConfirmButton();
await waitFor(() => expect(onCreate).toHaveBeenCalled());
expect(onOpenChange).not.toHaveBeenCalledWith(false);
expect(screen.getByText("新建项目")).not.toBeNull();
@@ -262,17 +264,17 @@ describe("ProjectsPage", () => {
fireEvent.click(screen.getByRole("button", { name: /归档/ }));
await waitFor(() => expect(screen.getByText("确认归档此项目?")).not.toBeNull());
clickLatestConfirmButton();
await clickLatestConfirmButton();
await waitFor(() => expect(onArchive).toHaveBeenCalledWith("p1"));
fireEvent.click(screen.getByRole("button", { name: /恢复/ }));
await waitFor(() => expect(screen.getByText("确认恢复此项目?")).not.toBeNull());
clickLatestConfirmButton();
await clickLatestConfirmButton();
await waitFor(() => expect(onRestore).toHaveBeenCalledWith("p2"));
fireEvent.click(screen.getByRole("button", { name: /删除/ }));
await waitFor(() => expect(screen.getByText("确认永久删除此项目?")).not.toBeNull());
clickLatestConfirmButton();
await clickLatestConfirmButton();
await waitFor(() => expect(onDelete).toHaveBeenCalledWith("p2"));
});
}, 15000);
});