fix: 统一报销付款状态与进度(09-04-reimbursement-state-gap-finance-view)

这个提交包含在:
2026-09-11 09:43:36 +08:00
父节点 fe025e65cf
当前提交 f9aee4c932
共修改 19 个文件,包含 549 行新增和 32 行删除
+32
查看文件
@@ -278,6 +278,38 @@ async function main() {
assert.ok(task, `pending task for ${role}`);
if (role === "manager") assert.equal(task.assignee_id, manager.id);
else { assert.equal(task.assignee_id, null); assert.equal(task.assignee_role, role); }
if (role === "finance" && browser && preview) {
await prisma.workflowHistory.updateMany({ where: { instance_id: newWorkflowId, action: "approve" }, data: { comment: "synthetic historical comment ".repeat(12) } });
const clientRequire = createRequire(path.join(root, "client/package.json"));
const { expect } = clientRequire("@playwright/test");
const uiOrigin = `http://127.0.0.1:${preview.httpServer.address().port}`;
for (const mobile of [false, true]) {
const context = await browser.newContext({ serviceWorkers: "block", viewport: mobile ? { width: 390, height: 844 } : { width: 1440, height: 960 } });
try {
const fingerprint = `synthetic-approval-layout-${mobile}`;
await context.addCookies([{ name: "hyb_oa_device_fingerprint", value: fingerprint, url: uiOrigin }]);
const login = await context.request.post(`${uiOrigin}/api/auth/login`, { headers: { "x-device-fingerprint": fingerprint }, data: { identifier: approvers.finance.email, password: loginPassword } });
assert.equal(login.status(), 200);
const page = await context.newPage();
await page.goto(`${uiOrigin}${mobile ? "/mobile/approvals" : "/workflow/tasks"}/${task.id}`);
const progress = page.getByTestId("reimbursement-approval-processing-progress");
await expect(progress).toHaveCount(1);
await expect(page.getByTestId("reimbursement-workflow-history")).toContainText("synthetic historical comment");
if (!mobile) {
const actions = page.getByTestId("workflow-task-action-panel");
const actionBounds = await actions.boundingBox();
const progressBounds = await progress.boundingBox();
assert.ok(progressBounds.y > actionBounds.y + actionBounds.height);
assert.ok(Math.abs(progressBounds.x - actionBounds.x) < 35);
assert.notEqual(await actions.locator("..").evaluate((element) => getComputedStyle(element).position), "sticky");
} else {
await expect(page.getByTestId("mobile-approvals-sticky-actions")).toBeVisible();
}
assert.equal(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 2), true);
} finally { await context.close(); }
}
passed.push("approval: real finance desktop/mobile evidence, current progress and synthetic long-history fixture; non-overlapping aside and safe-area action");
}
const approval = await post(`/workflow/tasks/${task.id}/approve`, {}, approvers[role].id);
assert.equal(approval.status, 200, `${role} approval: ${approval.status} ${approval.body.error?.code ?? ""}`);
assert.equal((await post(`/workflow/tasks/${task.id}/approve`, {}, approvers[role].id)).status, 409);