|
|
import { test, expect } from "@playwright/test";
|
|
|
|
|
|
/**
|
|
|
* RPA Worker E2E(task-088)
|
|
|
* 通过 mock API 模拟 RPA 正常/超时/失败场景
|
|
|
*/
|
|
|
test.describe("RPA 链路 E2E mock", () => {
|
|
|
test("TC-601:正常流程返回 4 档报价(items.length===4)", async ({ page }) => {
|
|
|
let quoteItemCount = 0;
|
|
|
|
|
|
await page.route("**/api/quotes", async (route) => {
|
|
|
if (route.request().method() === "POST") {
|
|
|
await route.fulfill({
|
|
|
status: 200,
|
|
|
contentType: "application/json",
|
|
|
body: JSON.stringify({
|
|
|
code: 0,
|
|
|
message: "ok",
|
|
|
data: {
|
|
|
quote_id: "QTE_RPA_001",
|
|
|
status: "processing",
|
|
|
source_type: "rpa",
|
|
|
},
|
|
|
}),
|
|
|
});
|
|
|
return;
|
|
|
}
|
|
|
await route.continue();
|
|
|
});
|
|
|
|
|
|
await page.route("**/api/quotes/QTE_RPA_001", async (route) => {
|
|
|
const payload = {
|
|
|
code: 0,
|
|
|
message: "ok",
|
|
|
data: {
|
|
|
quote_id: "QTE_RPA_001",
|
|
|
request_id: "req-rpa",
|
|
|
status: "done",
|
|
|
source_type: "rpa",
|
|
|
is_realtime: true,
|
|
|
currency: "USD",
|
|
|
valid_until: new Date(Date.now() + 180_000).toISOString(),
|
|
|
quotes: [
|
|
|
{
|
|
|
service_level: "standard",
|
|
|
rate_option: "lowest",
|
|
|
carrier: "M",
|
|
|
transit_days: "5",
|
|
|
transit_description: "最低",
|
|
|
raw_freight: 320,
|
|
|
surcharges: 0,
|
|
|
raw_total: 320,
|
|
|
markup_percent: 0,
|
|
|
markup_amount: 0,
|
|
|
final_total: 320,
|
|
|
breakdown: [],
|
|
|
},
|
|
|
{
|
|
|
service_level: "standard",
|
|
|
rate_option: "fastest",
|
|
|
carrier: "M",
|
|
|
transit_days: "3",
|
|
|
transit_description: "最快",
|
|
|
raw_freight: 365,
|
|
|
surcharges: 0,
|
|
|
raw_total: 365,
|
|
|
markup_percent: 0,
|
|
|
markup_amount: 0,
|
|
|
final_total: 365,
|
|
|
breakdown: [],
|
|
|
},
|
|
|
{
|
|
|
service_level: "guaranteed",
|
|
|
rate_option: "lowest",
|
|
|
carrier: "M",
|
|
|
transit_days: "4",
|
|
|
transit_description: "保价最低",
|
|
|
raw_freight: 380,
|
|
|
surcharges: 0,
|
|
|
raw_total: 380,
|
|
|
markup_percent: 0,
|
|
|
markup_amount: 0,
|
|
|
final_total: 380,
|
|
|
breakdown: [],
|
|
|
},
|
|
|
{
|
|
|
service_level: "guaranteed",
|
|
|
rate_option: "fastest",
|
|
|
carrier: "M",
|
|
|
transit_days: "2",
|
|
|
transit_description: "保价最快",
|
|
|
raw_freight: 410,
|
|
|
surcharges: 0,
|
|
|
raw_total: 410,
|
|
|
markup_percent: 0,
|
|
|
markup_amount: 0,
|
|
|
final_total: 410,
|
|
|
breakdown: [],
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
};
|
|
|
quoteItemCount = payload.data.quotes.length;
|
|
|
|
|
|
await route.fulfill({
|
|
|
status: 200,
|
|
|
contentType: "application/json",
|
|
|
body: JSON.stringify(payload),
|
|
|
});
|
|
|
});
|
|
|
|
|
|
await page.goto("/embed-demo");
|
|
|
await expect(
|
|
|
page.getByRole("heading", { name: "卡派查价" }),
|
|
|
).toBeVisible({ timeout: 30_000 });
|
|
|
await page.locator('input[name="p_street"]').fill("1234 Warehouse Blvd");
|
|
|
await page.locator('input[name="p_city"]').fill("Los Angeles");
|
|
|
await page.locator('select[name="p_state"]').selectOption("CA");
|
|
|
await page.locator('input[name="p_zip"]').fill("90001");
|
|
|
await page.getByRole("button").filter({ hasText: "Los Angeles" }).first().click();
|
|
|
|
|
|
await page.locator('input[name="d_street"]').fill("5678 Distribution Dr");
|
|
|
await page.locator('input[name="d_city"]').fill("Dallas");
|
|
|
await page.locator('select[name="d_state"]').selectOption("TX");
|
|
|
await page.locator('input[name="d_zip"]').fill("75201");
|
|
|
await page.getByRole("button").filter({ hasText: "Dallas" }).first().click();
|
|
|
|
|
|
await page.locator('input[name="weight"]').fill("500");
|
|
|
await page.locator('input[name="pallet_count"]').fill("2");
|
|
|
await page.getByRole("button", { name: "获取报价" }).click();
|
|
|
|
|
|
await expect(page.getByRole("button", { name: "标准" })).toBeVisible({
|
|
|
timeout: 20_000,
|
|
|
});
|
|
|
await expect(page.getByRole("button", { name: "保证送达" })).toBeVisible();
|
|
|
expect(quoteItemCount).toBe(4);
|
|
|
});
|
|
|
|
|
|
test("TC-602:RPA 失败 → 错误提示", async ({ page }) => {
|
|
|
await page.route("**/api/quotes", async (route) => {
|
|
|
await route.fulfill({
|
|
|
status: 200,
|
|
|
contentType: "application/json",
|
|
|
body: JSON.stringify({
|
|
|
code: 0,
|
|
|
message: "ok",
|
|
|
data: { quote_id: "QTE_FAIL", status: "processing" },
|
|
|
}),
|
|
|
});
|
|
|
});
|
|
|
|
|
|
await page.route("**/api/quotes/QTE_FAIL", async (route) => {
|
|
|
await route.fulfill({
|
|
|
status: 200,
|
|
|
contentType: "application/json",
|
|
|
body: JSON.stringify({
|
|
|
code: 0,
|
|
|
message: "ok",
|
|
|
data: {
|
|
|
quote_id: "QTE_FAIL",
|
|
|
request_id: "req-fail",
|
|
|
status: "failed",
|
|
|
error_code: "RPA_FAILED",
|
|
|
currency: "USD",
|
|
|
},
|
|
|
}),
|
|
|
});
|
|
|
});
|
|
|
|
|
|
await page.goto("/embed-demo");
|
|
|
await expect(
|
|
|
page.getByRole("heading", { name: "卡派查价" }),
|
|
|
).toBeVisible({ timeout: 30_000 });
|
|
|
await page.locator('input[name="p_street"]').fill("1234 Warehouse Blvd");
|
|
|
await page.locator('input[name="p_city"]').fill("Los Angeles");
|
|
|
await page.locator('select[name="p_state"]').selectOption("CA");
|
|
|
await page.locator('input[name="p_zip"]').fill("90001");
|
|
|
await page.getByRole("button").filter({ hasText: "Los Angeles" }).first().click();
|
|
|
await page.locator('input[name="d_street"]').fill("5678 Distribution Dr");
|
|
|
await page.locator('input[name="d_city"]').fill("Dallas");
|
|
|
await page.locator('select[name="d_state"]').selectOption("TX");
|
|
|
await page.locator('input[name="d_zip"]').fill("75201");
|
|
|
await page.getByRole("button").filter({ hasText: "Dallas" }).first().click();
|
|
|
await page.locator('input[name="weight"]').fill("500");
|
|
|
await page.locator('input[name="pallet_count"]').fill("2");
|
|
|
await page.getByRole("button", { name: "获取报价" }).click();
|
|
|
|
|
|
await expect(
|
|
|
page.getByText("暂时无法获取报价"),
|
|
|
).toBeVisible({ timeout: 20_000 });
|
|
|
});
|
|
|
});
|