增加移动报销查看范围(07-27-yang-jun-reimbursement-readiness)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-07-31 20:43:33 +08:00
父节点 20b20b100e
当前提交 8b376f4135
共修改 4 个文件,包含 139 行新增和 5 行删除
@@ -371,15 +371,105 @@ test.describe("R102 reimbursement main flow", () => {
test("移动报销卡片显示业务编号", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });
await page.goto("/mobile/reimbursements");
const listRequest = page.waitForRequest((request) => {
const url = new URL(request.url());
return request.method() === "GET" && url.pathname === "/api/reimbursements";
});
await page.goto("/mobile/reimbursements?scope=all");
const requestedUrl = new URL((await listRequest).url());
expect(requestedUrl.searchParams.get("scope")).toBe("own");
await expect(page.getByRole("heading", { name: "移动报销", exact: true })).toBeVisible();
await expect(page.getByTestId("mobile-reimbursements-scope-own")).toHaveCount(0);
await expect(page.getByTestId("mobile-reimbursements-scope-all")).toHaveCount(0);
await expect(page.getByTestId("mobile-reimbursement-card")).toBeVisible();
await expect(page.getByText(formNumber)).toBeVisible();
await expect(page.getByText(reimbursementId)).toHaveCount(0);
await expect(page.locator("table:visible")).toHaveCount(0);
});
test("移动管理员默认查看本人并可切换全部报销", async ({ page }) => {
const adminMe = {
...me,
id: "admin-r102",
employeeNo: "A102",
name: "测试管理员",
roleCodes: ["admin"],
};
const otherReimbursementId = "44444444-4444-4444-8444-444444444444";
const requestedScopes: Array<string | null> = [];
await page.route("**/api/me", async (route) => {
await fulfillJson(route, adminMe);
});
await page.route((url) => url.pathname === "/api/reimbursements", async (route) => {
const request = route.request();
if (request.method() !== "GET") {
await route.fallback();
return;
}
const url = new URL(request.url());
const scope = url.searchParams.get("scope");
requestedScopes.push(scope);
const ownItem = {
...reimbursementListItem(),
status: "reviewing",
owner: { id: adminMe.id, employeeNo: adminMe.employeeNo, name: adminMe.name },
submitter: { id: adminMe.id, employeeNo: adminMe.employeeNo, name: adminMe.name },
};
const otherItem = {
...ownItem,
id: otherReimbursementId,
formNumber: "BX-20260731-0002",
owner: { id: "employee-other-r102", employeeNo: "E103", name: "其他员工" },
submitter: { id: "employee-other-r102", employeeNo: "E103", name: "其他员工" },
};
const items = scope === "all" ? [ownItem, otherItem] : [ownItem];
await fulfillJson(route, { page: 1, pageSize: 20, total: items.length, scope: scope ?? "own", items });
});
await page.reload();
await expect(page).toHaveURL(/\/portal/);
await page.setViewportSize({ width: 375, height: 812 });
await page.goto("/mobile/reimbursements?status=reviewing");
await expect(page.getByTestId("mobile-reimbursements-scope-own")).toHaveAttribute("data-state", "active");
await expect(page.getByText("其他员工")).toHaveCount(0);
expect(requestedScopes.at(-1)).toBe("own");
const ownBounds = await page.getByTestId("mobile-reimbursements-scope-own").boundingBox();
const allBounds = await page.getByTestId("mobile-reimbursements-scope-all").boundingBox();
expect(ownBounds?.height ?? 0).toBeGreaterThanOrEqual(44);
expect(allBounds?.height ?? 0).toBeGreaterThanOrEqual(44);
const allResponse = page.waitForResponse((response) => {
const url = new URL(response.url());
return response.ok() && url.pathname === "/api/reimbursements" && url.searchParams.get("scope") === "all";
});
await page.getByTestId("mobile-reimbursements-scope-all").click();
await allResponse;
await expect(page).toHaveURL(/scope=all/);
await expect(page.getByTestId("mobile-reimbursements-scope-all")).toHaveAttribute("data-state", "active");
await expect(page.getByText("其他员工")).toBeVisible();
expect(requestedScopes.at(-1)).toBe("all");
await expect(page.getByTestId("mobile-reimbursement-delete")).toHaveCount(0);
await page.getByText("其他员工").click();
await expect(page).toHaveURL(new RegExp(`/mobile/reimbursements/${otherReimbursementId}$`));
const routeState = await page.evaluate(() => window.history.state?.usr ?? null);
expect(routeState?.from).toContain("status=reviewing");
expect(routeState?.from).toContain("scope=all");
await page.goBack();
await page.setViewportSize({ width: 667, height: 375 });
await expect(page.getByTestId("mobile-reimbursements-scope-all")).toBeVisible();
const horizontalOverflow = await page.evaluate(
() => document.documentElement.scrollWidth - document.documentElement.clientWidth,
);
expect(horizontalOverflow).toBeLessThanOrEqual(2);
});
test("报销明细记录切换时支持取消保持与确认放弃", async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 900 });
await page.goto(`/reimbursements/${reimbursementId}`);