补齐报销待组批财务入口 [09-04-reimbursement-state-gap-finance-view][R1]
这个提交包含在:
@@ -45,6 +45,8 @@ type MockScenario = {
|
||||
businessDate: string | null;
|
||||
summary: string | null;
|
||||
}>;
|
||||
paymentCandidateTotal?: number;
|
||||
onCandidateQuery?: (query: URLSearchParams) => void;
|
||||
contracts?: SyntheticContract[];
|
||||
onCreatePaymentBatch?: (payload: unknown) => void;
|
||||
};
|
||||
@@ -156,7 +158,8 @@ function expectNoPageErrors(errors: string[]) {
|
||||
async function mockSyntheticApis(page: Page, actor: SyntheticActor, scenario: MockScenario = {}) {
|
||||
await page.route((url) => url.pathname.startsWith("/api/"), async (route) => {
|
||||
const request = route.request();
|
||||
const pathName = new URL(request.url()).pathname;
|
||||
const requestUrl = new URL(request.url());
|
||||
const pathName = requestUrl.pathname;
|
||||
|
||||
if (pathName === "/api/auth/capabilities") {
|
||||
await fulfillJson(route, {
|
||||
@@ -265,7 +268,13 @@ async function mockSyntheticApis(page: Page, actor: SyntheticActor, scenario: Mo
|
||||
}
|
||||
if (pathName === "/api/payment-batches/candidates") {
|
||||
const items = scenario.paymentCandidates ?? [];
|
||||
await fulfillJson(route, { items, page: 1, pageSize: 50, total: items.length });
|
||||
scenario.onCandidateQuery?.(requestUrl.searchParams);
|
||||
await fulfillJson(route, {
|
||||
items,
|
||||
page: Number(requestUrl.searchParams.get("page") ?? "1"),
|
||||
pageSize: Number(requestUrl.searchParams.get("pageSize") ?? "20"),
|
||||
total: scenario.paymentCandidateTotal ?? items.length,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (pathName === "/api/payment-batches" && request.method() === "POST") {
|
||||
@@ -342,13 +351,18 @@ test("只有付款复核职责的经理可看应付账款但看不到导出", as
|
||||
test("只有付款复核职责的经理看不到新建批次", async ({ page }) => {
|
||||
test.skip(process.env.E2E_MODE === "live", "只使用本地合成角色,不访问公网");
|
||||
const pageErrors = capturePageErrors(page);
|
||||
await mockSyntheticApis(page, REVIEWER_ACTOR);
|
||||
let candidateQueryCount = 0;
|
||||
await mockSyntheticApis(page, REVIEWER_ACTOR, {
|
||||
onCandidateQuery: () => { candidateQueryCount += 1; },
|
||||
});
|
||||
await login(page, REVIEWER_ACTOR);
|
||||
|
||||
await page.goto("/payment-batches");
|
||||
await expect(page).toHaveURL(/\/payment-batches$/);
|
||||
await page.goto("/payment-batches?view=pending");
|
||||
await expect(page).toHaveURL(/\/payment-batches\?view=batches$/);
|
||||
await expect(page.getByRole("heading", { level: 1, name: "付款", exact: true })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "新建批次", exact: true })).toHaveCount(0);
|
||||
await expect(page.getByRole("button", { name: /待组批/ })).toHaveCount(0);
|
||||
await expect(page.getByRole("button", { name: /付款批次/ })).toBeVisible();
|
||||
expect(candidateQueryCount).toBe(0);
|
||||
expectNoPageErrors(pageErrors);
|
||||
});
|
||||
|
||||
@@ -394,8 +408,11 @@ test("财务从业务候选选择报销并使用所选实体创建付款批次",
|
||||
test.skip(process.env.E2E_MODE === "live", "只使用本地合成角色,不访问公网");
|
||||
const pageErrors = capturePageErrors(page);
|
||||
let createPayload: unknown = null;
|
||||
const candidateQueries: string[] = [];
|
||||
await mockSyntheticApis(page, FINANCE_ACTOR, {
|
||||
paymentCandidates: [PAYMENT_CANDIDATE],
|
||||
paymentCandidateTotal: 21,
|
||||
onCandidateQuery: (query) => candidateQueries.push(query.toString()),
|
||||
onCreatePaymentBatch: (payload) => {
|
||||
createPayload = payload;
|
||||
},
|
||||
@@ -403,9 +420,15 @@ test("财务从业务候选选择报销并使用所选实体创建付款批次",
|
||||
await login(page, FINANCE_ACTOR);
|
||||
|
||||
await page.goto("/payment-batches");
|
||||
await expect(page).toHaveURL(/\/payment-batches$/);
|
||||
await expect(page).toHaveURL(/\/payment-batches\?view=pending$/);
|
||||
await expect(page.getByRole("heading", { level: 1, name: "付款", exact: true })).toBeVisible();
|
||||
await page.getByRole("button", { name: "新建批次", exact: true }).click();
|
||||
await expect(page.getByRole("button", { name: "待组批 21", exact: true })).toHaveAttribute("aria-current", "page");
|
||||
await expect(page.getByTestId("payment-batch-candidates")).toHaveCount(1);
|
||||
await expect.poll(() => page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth)).toBeLessThanOrEqual(2);
|
||||
await page.getByRole("button", { name: "下一页", exact: true }).click();
|
||||
await expect(page).toHaveURL(/view=pending&page=2/);
|
||||
await expect.poll(() => candidateQueries.some((query) => query.includes("page=2") && query.includes("pageSize=20"))).toBe(true);
|
||||
await page.getByRole("button", { name: "上一页", exact: true }).click();
|
||||
|
||||
const candidateRow = page.getByTestId("payment-batch-candidate-row");
|
||||
await expect(candidateRow).toContainText(PAYMENT_CANDIDATE.businessNo);
|
||||
@@ -413,13 +436,17 @@ test("财务从业务候选选择报销并使用所选实体创建付款批次",
|
||||
await expect(candidateRow).toContainText("¥1,280.50");
|
||||
await expect(page.getByText(PAYMENT_CANDIDATE_ENTITY_ID, { exact: true })).toHaveCount(0);
|
||||
await expect(page.locator('input[placeholder*="UUID"], input[placeholder*="uuid"], input[placeholder*="entityId"], input[placeholder*="内部 ID"], input[placeholder*="内部ID"]')).toHaveCount(0);
|
||||
await page.getByTestId("payment-batch-candidate-search").fill(PAYMENT_CANDIDATE.businessNo);
|
||||
await expect(page).toHaveURL(new RegExp(`view=pending&q=${PAYMENT_CANDIDATE.businessNo}`));
|
||||
await page.setViewportSize({ width: 375, height: 812 });
|
||||
await expect.poll(() => page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth)).toBeLessThanOrEqual(2);
|
||||
|
||||
await candidateRow.getByRole("checkbox").check();
|
||||
await page.getByTestId("payment-batch-default-channel").selectOption("cash");
|
||||
await expect(page.getByText("按现金提交负责人复核", { exact: false })).toBeVisible();
|
||||
await page.getByRole("button", { name: "创建并提交复核", exact: true }).click();
|
||||
|
||||
await expect(page).toHaveURL(new RegExp(`/payment-batches\\?id=${CREATED_PAYMENT_BATCH_ID}$`));
|
||||
await expect(page).toHaveURL(new RegExp(`/payment-batches\\?view=batches&id=${CREATED_PAYMENT_BATCH_ID}$`));
|
||||
await expect(page.getByRole("heading", { level: 1, name: "付款", exact: true })).toBeVisible();
|
||||
await expect(page.getByText("已提交付款复核,等待负责人处理", { exact: true })).toBeVisible();
|
||||
expect(createPayload).toEqual({
|
||||
|
||||
在新工单中引用
屏蔽一个用户