R31-1 R31-4: 收口详情页工作台化与 E2E 契约
这个提交包含在:
@@ -1,8 +1,8 @@
|
||||
import { expect, test, type Locator, type Page } from "@playwright/test";
|
||||
|
||||
import { test, expect } from "./helpers/fixtures";
|
||||
import { EMPLOYEE, MANAGER, apiPostData, createAuthenticatedApiClient, login, logout } from "./helpers/auth";
|
||||
import { openNavLink } from "./helpers/navigation";
|
||||
import { TEST_IDS } from "./helpers/testIds";
|
||||
import type { Locator, Page } from "@playwright/test";
|
||||
|
||||
function formatDate(offsetDays: number) {
|
||||
const value = new Date();
|
||||
@@ -69,7 +69,7 @@ async function withdrawLeave(api: Awaited<ReturnType<typeof createAuthenticatedA
|
||||
return apiPostData<{ leaveRequestId: string; leaveStatus: string }>(api, `/api/leave-requests/${leaveRequestId}/withdraw`, {});
|
||||
}
|
||||
|
||||
test("E2E 请假主链路:草稿 → 提交 → 撤回 + 提交 → 审批", async ({ page }) => {
|
||||
test("E2E 请假主链路:草稿 → 提交 → 撤回 + 提交 → 审批", async ({ page, workflowDetail }) => {
|
||||
const employeeClient = await createAuthenticatedApiClient(EMPLOYEE);
|
||||
const baseOffset = 30 + Number(String(Date.now()).slice(-2));
|
||||
const firstDate = formatDate(baseOffset);
|
||||
@@ -77,42 +77,43 @@ test("E2E 请假主链路:草稿 → 提交 → 撤回 + 提交 → 审批", a
|
||||
|
||||
try {
|
||||
await login(page, EMPLOYEE);
|
||||
await (await openNavLink(page, "请假")).click();
|
||||
await expect(page.getByRole("heading", { name: "请假申请" })).toBeVisible();
|
||||
await (await openNavLink(page, "请假")).click();
|
||||
await expect(page.getByRole("heading", { name: "请假申请" })).toBeVisible();
|
||||
|
||||
const firstLeaveId = await createLeaveDraft(page, firstDate, firstDate, `Playwright 撤回请假 ${Date.now()}`);
|
||||
await submitLeave(employeeClient.api, firstLeaveId);
|
||||
await page.goto("/leave-requests");
|
||||
const firstRow = page.getByRole("row").filter({ hasText: firstDate }).first();
|
||||
await expect(firstRow).toContainText("审批中", { timeout: 30_000 });
|
||||
const firstLeaveId = await createLeaveDraft(page, firstDate, firstDate, `Playwright 撤回请假 ${Date.now()}`);
|
||||
await submitLeave(employeeClient.api, firstLeaveId);
|
||||
await page.goto("/leave-requests");
|
||||
const firstRow = page.getByRole("row").filter({ hasText: firstDate }).first();
|
||||
await expect(firstRow).toContainText("审批中", { timeout: 30_000 });
|
||||
|
||||
await withdrawLeave(employeeClient.api, firstLeaveId);
|
||||
await page.goto("/leave-requests");
|
||||
await expect(firstRow).toContainText("草稿", { timeout: 30_000 });
|
||||
await withdrawLeave(employeeClient.api, firstLeaveId);
|
||||
await page.goto("/leave-requests");
|
||||
await expect(firstRow).toContainText("草稿", { timeout: 30_000 });
|
||||
|
||||
const secondLeaveId = await createLeaveDraft(page, secondDate, secondDate, `Playwright 审批请假 ${Date.now()}`);
|
||||
const secondSubmit = await submitLeave(employeeClient.api, secondLeaveId);
|
||||
await page.goto("/leave-requests");
|
||||
const secondRow = page.getByRole("row").filter({ hasText: secondDate }).first();
|
||||
await expect(secondRow).toContainText("审批中", { timeout: 30_000 });
|
||||
const secondLeaveId = await createLeaveDraft(page, secondDate, secondDate, `Playwright 审批请假 ${Date.now()}`);
|
||||
const secondSubmit = await submitLeave(employeeClient.api, secondLeaveId);
|
||||
await page.goto("/leave-requests");
|
||||
const secondRow = page.getByRole("row").filter({ hasText: secondDate }).first();
|
||||
await expect(secondRow).toContainText("审批中", { timeout: 30_000 });
|
||||
|
||||
await logout(page, EMPLOYEE.name);
|
||||
await logout(page, EMPLOYEE.name);
|
||||
|
||||
await login(page, MANAGER);
|
||||
await (await openNavLink(page, "待我处理")).click();
|
||||
await expect(page.getByTestId(TEST_IDS.workflow.tasksTable)).toBeVisible();
|
||||
const taskRow = page.getByTestId(TEST_IDS.workflow.taskRow).filter({ hasText: secondSubmit.currentTaskId }).first();
|
||||
await expect(taskRow).toBeVisible({ timeout: 30_000 });
|
||||
await taskRow.getByTestId(TEST_IDS.workflow.detailLink).click();
|
||||
await page.getByTestId(TEST_IDS.workflow.approve).click();
|
||||
await expect(page.getByTestId(TEST_IDS.workflow.summary)).toContainText(/状态:(completed|已完成)/);
|
||||
await login(page, MANAGER);
|
||||
await (await openNavLink(page, "待我处理")).click();
|
||||
await expect(page.getByTestId(TEST_IDS.workflow.tasksTable)).toBeVisible();
|
||||
const taskRow = page.getByTestId(TEST_IDS.workflow.taskRow).filter({ hasText: secondSubmit.currentTaskId }).first();
|
||||
await expect(taskRow).toBeVisible({ timeout: 30_000 });
|
||||
await taskRow.getByTestId(TEST_IDS.workflow.detailLink).click();
|
||||
await workflowDetail.assertLoaded();
|
||||
await workflowDetail.approve();
|
||||
await expect(workflowDetail.summary).toContainText(/状态:(completed|已完成)/);
|
||||
|
||||
await logout(page, MANAGER.name);
|
||||
await logout(page, MANAGER.name);
|
||||
|
||||
await login(page, EMPLOYEE);
|
||||
await page.goto("/leave-requests");
|
||||
await expect(page.getByRole("row").filter({ hasText: secondDate }).first()).toContainText("已通过", { timeout: 30_000 });
|
||||
await expect(page.getByRole("row").filter({ hasText: firstDate }).first()).toContainText("草稿", { timeout: 30_000 });
|
||||
await login(page, EMPLOYEE);
|
||||
await page.goto("/leave-requests");
|
||||
await expect(page.getByRole("row").filter({ hasText: secondDate }).first()).toContainText("已通过", { timeout: 30_000 });
|
||||
await expect(page.getByRole("row").filter({ hasText: firstDate }).first()).toContainText("草稿", { timeout: 30_000 });
|
||||
} finally {
|
||||
await employeeClient.dispose();
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户