完成五人团队正式内用最小收口(07-18-small-team-internal-readiness)

这个提交包含在:
2026-07-18 15:46:14 +08:00
父节点 58c8decef9
当前提交 5d0a5f9a38
共修改 134 个文件,包含 10790 行新增和 1413 行删除
@@ -7,6 +7,10 @@ import { expect, test } from "./helpers/fixtures";
test.use({ serviceWorkers: "block" });
const outputDir = path.resolve(process.cwd(), "../output/playwright/pc-detail-mobile-visual-wave3");
const taskOutputDir = path.resolve(
process.cwd(),
"../output/playwright/07-18-small-team-internal-readiness",
);
const visualUser = {
identifier: "[email protected]",
@@ -400,6 +404,18 @@ const contractRegistryItem = {
project: { id: projectDetail.id, projectNo: projectDetail.projectNo, name: projectDetail.name },
};
const secondContractRegistryItem = {
...contractRegistryItem,
id: "contract-wave3-second",
contractNo: "HT-2026-W3-02",
counterpartyName: "上海合成技术服务有限公司",
summary: "用于验证合同记录切换保护的第二条合成台账",
amount: "18000.00",
expiryDate: "2026-07-20",
archiveLocation: "离线档案柜 A-02",
offlineArchiveNo: "OFF-2026-W3-02",
};
const purchaseDetail = {
id: "purchase-wave3",
requestNo: "CG20260527001",
@@ -510,6 +526,11 @@ function screenshotPath(fileName: string) {
return path.join(outputDir, fileName);
}
function taskScreenshotPath(fileName: string) {
mkdirSync(taskOutputDir, { recursive: true });
return path.join(taskOutputDir, fileName);
}
function navigationItem(key: string, href: string, label: string, icon: string, placement = "main") {
return { key, href, label, icon, placement, permissionCodes: [], featureFlagKey: null };
}
@@ -901,7 +922,7 @@ async function mockWave3Apis(page: Page) {
}
if (pathName === "/api/contracts-registry") {
await fulfillJson(route, { items: [contractRegistryItem] });
await fulfillJson(route, { items: [contractRegistryItem, secondContractRegistryItem] });
return;
}
@@ -1055,6 +1076,7 @@ test.beforeEach(async ({ page }) => {
});
test("Wave3 PC 详情和通知中心视觉截图", async ({ page }) => {
test.setTimeout(300_000);
await page.setViewportSize({ width: 1440, height: 960 });
await page.goto("/reimbursements/reim-wave3");
@@ -1099,7 +1121,9 @@ test("Wave3 PC 详情和通知中心视觉截图", async ({ page }) => {
await page.goto("/contracts-registry?projectId=project-wave3");
await expect(page.getByRole("heading", { name: "合同", exact: true })).toBeVisible();
await expect(page.getByTestId("contracts-registry-table").getByTestId("contracts-registry-row")).toBeVisible();
const contractRows = page.getByTestId("contracts-registry-table").getByTestId("contracts-registry-row");
await expect(contractRows).toHaveCount(2);
await expect(contractRows.first()).toBeVisible();
await page.locator(".ops-command-bar__actions").getByRole("button", { name: "更多" }).click();
await expect(page.getByRole("menuitem", { name: "导出 CSV" })).toBeVisible();
await page.keyboard.press("Escape");
@@ -1108,7 +1132,7 @@ test("Wave3 PC 详情和通知中心视觉截图", async ({ page }) => {
await page.getByRole("button", { name: "新增合同" }).click();
await expect(page.getByTestId("contracts-editor-panel")).toBeVisible();
await page.getByRole("button", { name: "关闭" }).click();
await expect(page.getByTestId("contracts-registry-table").getByTestId("contracts-registry-row")).toBeVisible();
await expect(contractRows).toHaveCount(2);
await page.getByTestId("contracts-registry-table").getByRole("button", { name: "更多" }).first().click();
await page.getByRole("menuitem", { name: "归档" }).click();
await expect(page.getByTestId("action-confirm-dialog")).toContainText("确认归档");
@@ -1117,6 +1141,59 @@ test("Wave3 PC 详情和通知中心视觉截图", async ({ page }) => {
await page.screenshot({ path: screenshotPath("04-pc-contracts-registry.png"), fullPage: true });
});
test("/contracts-registry 在 768x1024 与 1024x768 下操作列可达", async ({ page }) => {
for (const viewport of [
{ width: 768, height: 1024 },
{ width: 1024, height: 768 },
]) {
await page.setViewportSize(viewport);
await page.goto("/contracts-registry");
await expect(page.getByRole("heading", { name: "合同", exact: true })).toBeVisible();
const table = page.getByTestId("contracts-registry-table");
await expect(table).toBeVisible();
const scrollRegion = table.locator("xpath=ancestor::*[@data-testid='business-table-scroll']").first();
const metrics = await scrollRegion.evaluate((element) => {
element.scrollLeft = element.scrollWidth;
return {
overflowX: window.getComputedStyle(element).overflowX,
clientWidth: element.clientWidth,
scrollWidth: element.scrollWidth,
documentOverflow: document.documentElement.scrollWidth - document.documentElement.clientWidth,
};
});
expect(["auto", "scroll"]).toContain(metrics.overflowX);
expect(metrics.scrollWidth).toBeGreaterThanOrEqual(metrics.clientWidth);
expect(metrics.documentOverflow).toBeLessThanOrEqual(2);
const operation = table.getByRole("button", { name: "更多" }).first();
await expect(operation).toBeVisible();
await operation.click({ trial: true });
await page.screenshot({
path: taskScreenshotPath(`contracts-registry-${viewport.width}x${viewport.height}.png`),
fullPage: true,
});
}
});
test("合同长表单从记录 A 切换到记录 B 时支持取消保持与确认放弃", async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 900 });
await page.goto("/contracts-registry");
const table = page.getByTestId("contracts-registry-table");
const editButtons = table.getByRole("button", { name: "编辑", exact: true });
await editButtons.first().click();
const counterparty = page.getByPlaceholder("合同对方名称");
await counterparty.fill("合成未保存合同相对方");
await editButtons.nth(1).click();
await expect(page.getByTestId("unsaved-changes-dialog")).toContainText("合同表单尚未保存");
await page.getByTestId("unsaved-changes-continue").click();
await expect(page).toHaveURL(/\/contracts-registry$/);
await expect(counterparty).toHaveValue("合成未保存合同相对方");
await editButtons.nth(1).click();
await page.getByTestId("unsaved-changes-discard").click();
await expect(counterparty).toHaveValue(secondContractRegistryItem.counterpartyName);
});
test("Wave3 移动关键页视觉截图", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });