test(web): 补充 Web MVP 端到端测试与本地测试编排
- 新增 Playwright E2E(治理、登录、投瓶捞瓶回复与实时聊天、举报拉黑与断线恢复)共 9 条用例 - 每个用例前重置数据库、用例后关闭全部 browser context,消除跨用例污染与资源泄漏 - 前端改由 Playwright 托管构建与 preview(关闭 SW);Vite 代理注入 Origin 头以通过接口 Origin 校验 - 根级 vitest 排除 Playwright 用例与需专用配置的 web 用例,避免误收集导致的假失败 - 测试手机号按实测校验结果收敛白名单,避免用例传入会被后端拒绝的号段 验证结果: - Web E2E 9/9 连续两轮通过(含运行前后服务健康检查) - API E2E 146/146 连续两轮通过 - 单测:根级 14 文件/119 用例、web 包 8 文件/31 用例通过 - typecheck、lint、build、依赖审计(audit)均通过
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import { test, expect } from "./fixtures";
|
||||
import { freshAccount, loginViaUi, pickBottle } from "./helpers";
|
||||
|
||||
test.describe("bottle social loop", () => {
|
||||
test("throws, picks, replies and chats in real time with two users", async ({
|
||||
browser,
|
||||
}) => {
|
||||
const aliceAccount = freshAccount("131");
|
||||
const bobAccount = freshAccount("132");
|
||||
|
||||
const alice = await browser.newContext();
|
||||
const bob = await browser.newContext();
|
||||
const aPage = await alice.newPage();
|
||||
const bPage = await bob.newPage();
|
||||
|
||||
await loginViaUi(aPage, aliceAccount);
|
||||
await loginViaUi(bPage, bobAccount);
|
||||
|
||||
// Alice 投瓶
|
||||
await aPage.goto("/throw");
|
||||
await aPage
|
||||
.getByPlaceholder("写下你想让陌生人看到的话…")
|
||||
.fill("你好,海上的陌生人,愿你被温柔接住。");
|
||||
await aPage.getByRole("button", { name: /扔进海里/ }).click();
|
||||
await expect(aPage.getByText(/瓶子已进入审核/)).toBeVisible();
|
||||
|
||||
// Bob 捞瓶(过滤掉 Alice 已投的,应捞到池中瓶子)
|
||||
await bPage.goto("/pick");
|
||||
await pickBottle(bPage);
|
||||
const content = (await bPage.locator("blockquote").innerText()).trim();
|
||||
expect(content.length).toBeGreaterThan(0);
|
||||
|
||||
// Bob 首次回复建立会话
|
||||
await bPage
|
||||
.locator(".bottle-card textarea")
|
||||
.fill("很高兴遇见你,来自另一片海域。");
|
||||
await bPage.getByRole("button", { name: /回复并建立会话/ }).click();
|
||||
await expect(bPage).toHaveURL(/\/conversations\//, { timeout: 15_000 });
|
||||
await expect(
|
||||
bPage.getByText("很高兴遇见你,来自另一片海域。"),
|
||||
).toBeVisible();
|
||||
|
||||
// Alice 会话列表出现新会话
|
||||
await aPage.goto("/conversations");
|
||||
await expect(aPage.locator(".conversation")).toHaveCount(1, {
|
||||
timeout: 15_000,
|
||||
});
|
||||
|
||||
// Bob 发送实时消息,两端都能看到
|
||||
await bPage.locator(".composer textarea").fill("今天过得怎么样?");
|
||||
await bPage.getByRole("button", { name: /发送消息/ }).click();
|
||||
await expect(bPage.getByText("今天过得怎么样?")).toBeVisible();
|
||||
|
||||
await aPage.goto("/conversations");
|
||||
await aPage.locator(".conversation").first().click();
|
||||
await expect(aPage.getByText("今天过得怎么样?")).toBeVisible({
|
||||
timeout: 15_000,
|
||||
});
|
||||
|
||||
await alice.close();
|
||||
await bob.close();
|
||||
});
|
||||
|
||||
test("replies once and deduplicates concurrent history sync", async ({
|
||||
browser,
|
||||
}) => {
|
||||
const aAccount = freshAccount("133");
|
||||
const bAccount = freshAccount("134");
|
||||
|
||||
const ctxA = await browser.newContext();
|
||||
const ctxB = await browser.newContext();
|
||||
const pageA = await ctxA.newPage();
|
||||
const pageB = await ctxB.newPage();
|
||||
|
||||
await loginViaUi(pageA, aAccount);
|
||||
await loginViaUi(pageB, bAccount);
|
||||
|
||||
// 两个瓶子避免同瓶并发
|
||||
await pageA.goto("/throw");
|
||||
await pageA
|
||||
.getByPlaceholder("写下你想让陌生人看到的话…")
|
||||
.fill(`sync 瓶子 A ${Date.now()}`);
|
||||
await pageA.getByRole("button", { name: /扔进海里/ }).click();
|
||||
await expect(pageA.getByText(/瓶子已进入审核/)).toBeVisible();
|
||||
await pageA.goto("/throw");
|
||||
await pageA
|
||||
.getByPlaceholder("写下你想让陌生人看到的话…")
|
||||
.fill(`sync 瓶子 B ${Date.now()}`);
|
||||
await pageA.getByRole("button", { name: /扔进海里/ }).click();
|
||||
await expect(pageA.getByText(/瓶子已进入审核/)).toBeVisible();
|
||||
|
||||
// B 连续捞两只瓶子并各回复一次
|
||||
for (let i = 0; i < 2; i++) {
|
||||
await pageB.goto("/pick");
|
||||
await pickBottle(pageB);
|
||||
await pageB.locator(".bottle-card textarea").fill(`回复-${i}:海上的你好`);
|
||||
await pageB.getByRole("button", { name: /回复并建立会话/ }).click();
|
||||
await expect(pageB).toHaveURL(/\/conversations\//, {
|
||||
timeout: 15_000,
|
||||
});
|
||||
}
|
||||
|
||||
// A 端应看到两个会话
|
||||
await pageA.goto("/conversations");
|
||||
await expect(pageA.locator(".conversation")).toHaveCount(2, {
|
||||
timeout: 15_000,
|
||||
});
|
||||
|
||||
await ctxA.close();
|
||||
await ctxB.close();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user