You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.7 KiB
129 lines
4.7 KiB
import { test, expect, type APIRequestContext } from "@playwright/test";
|
|
|
|
async function login(page: import("@playwright/test").Page) {
|
|
const res = await page.request.post("/api/auth/login", {
|
|
data: { username: "admin", password: "admin123" },
|
|
});
|
|
expect(res.ok(), await res.text()).toBeTruthy();
|
|
await page.goto("/mails");
|
|
await expect(page).toHaveURL(/\/mails/, { timeout: 20_000 });
|
|
}
|
|
|
|
async function injectFixture(request: APIRequestContext, fixtureId: string) {
|
|
const res = await request.post("/api/test/inject", {
|
|
data: { fixture_id: fixtureId },
|
|
});
|
|
if (res.status() === 404) {
|
|
test.skip(true, "Server is not in TEST_MODE");
|
|
}
|
|
expect(res.ok(), await res.text()).toBeTruthy();
|
|
return res.json() as Promise<{
|
|
ok: true;
|
|
data: {
|
|
mail_id: string;
|
|
status: string;
|
|
mail_type: string;
|
|
last_error: string | null;
|
|
version: number;
|
|
subject: string;
|
|
};
|
|
}>;
|
|
}
|
|
|
|
test.describe("TEST_MODE pipeline e2e", () => {
|
|
test("inject forecast → UI 待确认 → submit → MockTargetAPI 收到柜号", async ({
|
|
page,
|
|
}) => {
|
|
const api = page.request;
|
|
await login(page);
|
|
await api.post("/api/test/reset");
|
|
const injected = await injectFixture(api, "01-normal-forecast");
|
|
const mailId = injected.data.mail_id;
|
|
|
|
await page.goto(`/mails/${mailId}`);
|
|
await expect(page.getByText(/待确认/).first()).toBeVisible({ timeout: 15_000 });
|
|
await expect(page.getByText(/WHSU8127240/).first()).toBeVisible();
|
|
|
|
const detail = await api.get(`/api/mails/${mailId}`);
|
|
const body = await detail.json();
|
|
const shipments = body.data?.parse_result?.shipments || [];
|
|
const indexes = shipments
|
|
.filter((s: { row_status?: string; row_index: number }) => s.row_status === "VALID")
|
|
.map((s: { row_index: number }) => s.row_index);
|
|
|
|
const imported = await api.post(`/api/mails/${mailId}/import`, {
|
|
data: {
|
|
version: body.data.version,
|
|
idempotency_key: `e2e-${Date.now()}`,
|
|
F_TransMode: 0,
|
|
F_OperationType: 0,
|
|
container_header: { F_ContainerNo: `TPZU${String(Date.now()).slice(-7)}` },
|
|
selected_row_indexes: indexes,
|
|
ack_unmapped_channels: true,
|
|
force_skip_conflict: true,
|
|
},
|
|
});
|
|
const importedJson = await imported.json();
|
|
expect(importedJson.ok, JSON.stringify(importedJson)).toBe(true);
|
|
expect(importedJson.data?.mail_status).toBe("SUCCESS");
|
|
|
|
const rec = await api.get("/api/test/target-requests");
|
|
const recBody = await rec.json();
|
|
const saves = (recBody.data?.requests || []).filter(
|
|
(r: { path: string }) => r.path === "/Container/SaveContainer",
|
|
);
|
|
expect(saves.length).toBeGreaterThan(0);
|
|
expect(JSON.stringify(saves[0].body)).toMatch(/LAS1|WHSU8127240|TPZU/);
|
|
|
|
await page.reload();
|
|
await expect(page.getByText(/导入成功/).first()).toBeVisible({ timeout: 15_000 });
|
|
});
|
|
|
|
test("fault: missing attachment shows parse failure on detail", async ({ page }) => {
|
|
await login(page);
|
|
const injected = await injectFixture(page.request, "09-no-attachment");
|
|
await page.goto(`/mails/${injected.data.mail_id}`);
|
|
await expect(page.getByText(/校验拒绝|未解析到货件/).first()).toBeVisible({
|
|
timeout: 15_000,
|
|
});
|
|
});
|
|
|
|
test("fault: target 401 keeps mail failed with visible error", async ({ page }) => {
|
|
const api = page.request;
|
|
await login(page);
|
|
await api.post("/api/test/reset");
|
|
const injected = await injectFixture(api, "01-normal-forecast");
|
|
const mailId = injected.data.mail_id;
|
|
await api.post("/api/test/faults", {
|
|
data: { target: "401", target_path: "/Container/SaveContainer" },
|
|
});
|
|
|
|
const detail = await api.get(`/api/mails/${mailId}`);
|
|
const body = await detail.json();
|
|
const shipments = body.data?.parse_result?.shipments || [];
|
|
const indexes = shipments
|
|
.filter((s: { row_status?: string; row_index: number }) => s.row_status === "VALID")
|
|
.map((s: { row_index: number }) => s.row_index);
|
|
|
|
const imported = await api.post(`/api/mails/${mailId}/import`, {
|
|
data: {
|
|
version: body.data.version,
|
|
idempotency_key: `e2e-401-${Date.now()}`,
|
|
F_TransMode: 0,
|
|
F_OperationType: 0,
|
|
container_header: { F_ContainerNo: `TPZU${String(Date.now()).slice(-7)}` },
|
|
selected_row_indexes: indexes,
|
|
ack_unmapped_channels: true,
|
|
force_skip_conflict: true,
|
|
},
|
|
});
|
|
const importedJson = await imported.json();
|
|
expect(importedJson.data?.mail_status || importedJson.error).toBeTruthy();
|
|
|
|
await page.goto(`/mails/${mailId}`);
|
|
await expect(page.getByText(/导入失败|登录失败|权限|CarrierCentral/i).first()).toBeVisible({
|
|
timeout: 15_000,
|
|
});
|
|
});
|
|
});
|