B1-B8 建立项目级流程与QA门禁

这个提交包含在:
2026-05-09 01:57:05 +08:00
父节点 555e7b7e29
当前提交 485328426a
共修改 29 个文件,包含 1633 行新增和 102 行删除
+12 -11
查看文件
@@ -2,16 +2,8 @@ import { expect, test } from "@playwright/test";
import { createAuthenticatedApiClient, EMPLOYEE, FINANCE_MGR, login, logout, MANAGER } from "./helpers/auth";
import { createAndSubmitTravelRequestViaUi, importTravelPaymentSeed } from "./helpers/travel";
function extractId(text: string, label: string) {
const match = text.match(new RegExp(`${label}:([0-9a-f-]{36})`));
if (!match?.[1]) {
throw new Error(`Failed to parse ${label} from text: ${text}`);
}
return match[1];
}
function extractInvoiceCode(text: string) {
const match = text.match(/发票号:([A-Z0-9]+)-/);
const match = text.match(/发票(?:号|号码):([A-Z0-9]+)-/);
if (!match?.[1]) {
throw new Error(`Failed to parse invoice code from text: ${text}`);
}
@@ -61,16 +53,25 @@ test("E2E 差旅支付主链路:申请→审批→支付→绑票", async ({ p
await page.goto("/invoice-pool");
const invoiceFileName = `travel-payment-${Date.now()}.png`;
const uploadResponsePromise = page.waitForResponse((response) => {
const url = new URL(response.url());
return response.request().method() === "POST" && url.pathname === "/api/invoice-pool/upload" && response.ok();
});
await page.getByTestId("invoice-upload-file").setInputFiles({
name: invoiceFileName,
mimeType: "image/png",
buffer: Buffer.from(`TRAVEL_PAYMENT_${Date.now()}`, "utf8"),
});
await page.getByTestId("invoice-upload-submit").click();
const uploadPayload = (await (await uploadResponsePromise).json()) as { data?: { invoicePoolId?: string | null } };
const invoiceId = uploadPayload.data?.invoicePoolId;
if (!invoiceId) {
throw new Error(`上传发票后未返回票据 ID: ${JSON.stringify(uploadPayload)}`);
}
await expect(page.getByTestId("invoice-detail-panel")).toBeVisible();
await expect(page.getByTestId("invoice-detail-panel")).toContainText("状态:available", { timeout: 90_000 });
await expect(page.getByTestId("invoice-detail-panel")).toContainText("状态:可用", { timeout: 90_000 });
const invoiceDetailText = await page.getByTestId("invoice-detail-panel").innerText();
const invoiceId = extractId(invoiceDetailText, "票据ID");
const invoiceCode = extractInvoiceCode(invoiceDetailText);
await page.reload();