import { mkdirSync } from "node:fs"; import { resolve } from "node:path"; import { expect, test } from "@playwright/test"; import { createServer, type ViteDevServer } from "vite"; let vite: ViteDevServer; let webUrl: string; test.use({ trace: "off" }); test.beforeAll(async () => { vite = await createServer({ configFile: resolve("apps/web/vite.config.ts"), root: resolve("apps/web"), server: { host: "127.0.0.1", port: 0 }, }); await vite.listen(); const address = vite.httpServer?.address(); if (!address || typeof address === "string") throw new Error("Vite did not expose a test port."); webUrl = `http://127.0.0.1:${address.port}`; }); test.afterAll(async () => vite.close()); test("TDD-WP1-NOTICE-001 expands DVPM8 only after successful code delivery", async ({ page }) => { await page.route("**/api/v1/auth/register/send", (route) => route.fulfill({ contentType: "application/json", status: 200, body: JSON.stringify({ challenge_expires_at: "2026-07-28T09:10:00.000Z", registration_id: "00000000-0000-4000-8000-000000000003", resend_available_at: "2026-07-28T09:01:00.000Z", status: "verification_sent", }), })); await page.goto(webUrl); await page.getByRole("tab", { name: "注册" }).click(); await page.getByRole("textbox", { name: "邀请码" }).fill("DADA-P0A-TEST-7K2"); await page.getByRole("textbox", { name: "邮箱" }).fill("registration@example.invalid"); await page.getByRole("button", { name: "获取验证码" }).click(); await expect(page.getByRole("heading", { name: "完善注册资料" })).toBeVisible(); await expect(page.getByText("邀请码 · 已验证")).toBeVisible(); await expect(page.getByText("邮箱 · 已验证")).toBeVisible(); await expect(page.getByRole("button", { name: "修改邀请码和邮箱" })).toBeVisible(); await expect(page.getByLabel("验证码")).toBeVisible(); await expect(page.getByLabel("创作署名")).toBeVisible(); await expect(page.getByLabel("社交 ID")).toBeVisible(); await expect(page.getByRole("checkbox", { name: /同意/ })).not.toBeChecked(); await expect(page.getByRole("button", { name: "注册并进入 Dada" })).toBeDisabled(); const panelBounds = await page.locator(".auth-panel").boundingBox(); const viewport = page.viewportSize(); expect(panelBounds).not.toBeNull(); expect(viewport).not.toBeNull(); expect(Math.abs((panelBounds!.x + panelBounds!.width / 2) - viewport!.width / 2)).toBeLessThanOrEqual(2); await page.getByRole("button", { name: "查看全文" }).click(); const dialog = page.getByRole("dialog", { name: "内测使用与隐私告知" }); const noticeClose = page.getByRole("button", { name: "我已阅读" }); await expect(noticeClose).toBeFocused(); await expect(dialog).toContainText("AI 网关"); await expect(dialog).toContainText("Resend"); await expect(dialog).toContainText("高德"); await expect(dialog).toContainText("DYN004"); await expect(dialog).toContainText("180 天"); await expect(dialog).toContainText("不会迁移到正式系统"); const evidenceDirectory = process.env.DADA_EVIDENCE_DIR_NOTICE; if (evidenceDirectory) { mkdirSync(resolve(evidenceDirectory, "screenshots"), { recursive: true }); await page.screenshot({ path: resolve(evidenceDirectory, "screenshots", "notice-expanded.png") }); } await page.keyboard.press("Tab"); await expect(noticeClose).toBeFocused(); await page.keyboard.press("Escape"); await expect(dialog).toHaveCount(0); await expect(page.getByRole("button", { name: "查看全文" })).toBeFocused(); await expect(page.getByRole("checkbox", { name: /同意/ })).not.toBeChecked(); }); test("TDD-WP1-SLOT-001 preserves profile fields when final capacity recheck fails", async ({ page }) => { await page.route("**/api/v1/auth/register/send", (route) => route.fulfill({ contentType: "application/json", status: 200, body: JSON.stringify({ challenge_expires_at: "2026-07-28T09:10:00.000Z", registration_id: "00000000-0000-4000-8000-000000000004", resend_available_at: "2026-07-28T09:01:00.000Z", status: "verification_sent", }), })); await page.route("**/api/v1/auth/register/complete", async (route) => { await new Promise((resolveDelay) => setTimeout(resolveDelay, 150)); await route.fulfill({ contentType: "application/json", status: 409, body: JSON.stringify({ error: { code: "REGISTRATION_REJECTED", correlation_id: "00000000-0000-4000-8000-000000000005", details: { field_errors: [{ field: "invite_code", message_key: "auth.registration.stage_limit_reached" }] }, message_key: "registration.rejected", }, }), }); }); await page.goto(webUrl); await page.getByRole("tab", { name: "注册" }).click(); await page.getByRole("textbox", { name: "邀请码" }).fill("DADA-P0A-TEST-9M4"); await page.getByRole("textbox", { name: "邮箱" }).fill("capacity@example.invalid"); await page.getByRole("button", { name: "获取验证码" }).click(); await page.getByLabel("验证码").fill("418205"); await page.getByLabel("创作署名").fill("Capacity User"); await page.getByLabel("社交 ID").fill("@capacity_user"); await page.getByRole("checkbox", { name: /同意/ }).check(); await page.getByRole("button", { name: "注册并进入 Dada" }).click(); await expect(page.getByRole("button", { name: "注册中" })).toBeDisabled(); await expect(page.getByRole("alert")).toContainText("本轮内测名额已满"); await expect(page.getByLabel("创作署名")).toHaveValue("Capacity User"); await expect(page.getByLabel("社交 ID")).toHaveValue("@capacity_user"); await expect(page.getByRole("checkbox", { name: /同意/ })).toBeChecked(); }); test("TDD-WP1-NOTICE-001 hands a successful registration to the workspace route", async ({ page }) => { await page.route("**/api/v1/auth/register/send", (route) => route.fulfill({ contentType: "application/json", status: 200, body: JSON.stringify({ challenge_expires_at: "2026-07-28T09:10:00.000Z", registration_id: "00000000-0000-4000-8000-000000000006", resend_available_at: "2026-07-28T09:01:00.000Z", status: "verification_sent", }), })); await page.route("**/api/v1/auth/register/complete", (route) => route.fulfill({ contentType: "application/json", status: 200, body: JSON.stringify({ status: "registered" }), })); await page.goto(webUrl); await page.getByRole("tab", { name: "注册" }).click(); await page.getByRole("textbox", { name: "邀请码" }).fill("DADA-P0A-TEST-4R8"); await page.getByRole("textbox", { name: "邮箱" }).fill("handoff@example.invalid"); await page.getByRole("button", { name: "获取验证码" }).click(); await page.getByLabel("验证码").fill("418205"); await page.getByLabel("创作署名").fill("Handoff User"); await page.getByLabel("社交 ID").fill("@handoff_user"); await page.getByRole("checkbox", { name: /同意/ }).check(); await page.getByRole("button", { name: "注册并进入 Dada" }).click(); await expect(page).toHaveURL(`${webUrl}/app`); });