import { mkdirSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { expect, test } from "@playwright/test"; const webUrl = "http://127.0.0.1:4173"; const userId = "00000000-0000-4000-8000-000000000701"; const taskId = "00000000-0000-4000-8000-000000000702"; const projectId = "00000000-0000-4000-8000-000000000703"; test.use({ trace: "off" }); const session = { audience: "user", authenticated: true, credits: { available_balance: 9, reserved_balance: 1 }, csrf_token: "csrf-generation-fixture-000000000000000000000000000000", local_data: { capacity_status: "critical", hard_limit_bytes: 5368709120, managed_content_bytes: 4831838208 }, user: { creator_name: "Generation User", role: "user", social_id: "@generation", status: "active", user_id: userId }, }; test("TDD-WP2-GEN-001-submit-snapshot renders queued truth, frozen credits and critical capacity without fake progress", async ({ page }) => { await page.route("**/api/v1/auth/session", (route) => route.fulfill({ contentType: "application/json", json: session })); await page.route("**/api/v1/projects?status=active", (route) => route.fulfill({ contentType: "application/json", json: { active_count: 1, active_limit: 20, projects: [] } })); await page.route("**/api/v1/models", (route) => route.fulfill({ contentType: "application/json", json: { config_set_version: 1, configured_default_model_id: "gemini-3.1-flash-image-preview", models: [], recommended_model_id: "gemini-3.1-flash-image-preview" } })); await page.route("**/api/v1/generations/current", (route) => route.fulfill({ contentType: "application/json", json: { confirmed_credit_cost: 1, created_at: "2026-08-02T13:00:00.000Z", generation_id: taskId, model_config_version: 1, model_id: "gemini-3.1-flash-image-preview", project_id: projectId, prompt: "生成中的海报", ratio: "3:4", reference_count: 1, reserved_credits: 1, status: "queued", updated_at: "2026-08-02T13:00:00.000Z", } })); await page.goto(`${webUrl}/app`); await expect(page.getByRole("heading", { name: "当前任务" })).toBeVisible(); await expect(page.getByText("排队中", { exact: true })).toBeVisible(); await expect(page.getByText("已冻结 1 点", { exact: true })).toBeVisible(); await expect(page.getByText(/存储空间已超过 90%/)).toBeVisible(); await expect(page.getByRole("button", { name: "生成一张图片" })).toBeDisabled(); await expect(page.locator(".current-task").getByText(/\d+%/)).toHaveCount(0); const directory = resolve(process.env.DADA_EVIDENCE_DIR_GENERATION ?? "artifacts/tdd/manual", "TDD-WP2-GEN-001-submit-snapshot", "screenshots"); mkdirSync(directory, { recursive: true }); await page.screenshot({ fullPage: true, path: resolve(directory, "queued-workspace.png") }); await page.setViewportSize({ height: 844, width: 390 }); await expect(page.getByText("已冻结 1 点", { exact: true })).toBeVisible(); await page.screenshot({ fullPage: true, path: resolve(directory, "queued-workspace-mobile.png") }); }); test("TDD-WP2-GEN-003-stale-config requires explicit confirmation before a second submit", async ({ page, context }) => { const evidenceRoot = process.env.DADA_EVIDENCE_DIR_GENERATION; const tracePath = evidenceRoot ? resolve(evidenceRoot, "TDD-WP2-GEN-003-stale-config", "trace.zip") : undefined; if (tracePath) { mkdirSync(dirname(tracePath), { recursive: true }); await context.tracing.start({ screenshots: true, snapshots: true }); } await page.route("**/api/v1/auth/session", (route) => route.fulfill({ contentType: "application/json", json: { ...session, credits: { available_balance: 10, reserved_balance: 0 }, local_data: { ...session.local_data, capacity_status: "normal", managed_content_bytes: 0 } } })); await page.route("**/api/v1/projects?status=active", (route) => route.fulfill({ contentType: "application/json", json: { active_count: 0, active_limit: 20, projects: [] } })); await page.route("**/api/v1/generations/current", (route) => route.fulfill({ body: "null", contentType: "application/json", status: 404 })); await page.route("**/api/v1/models", (route) => route.fulfill({ contentType: "application/json", json: { config_set_version: 1, configured_default_model_id: "gemini-3.1-flash-image-preview", recommended_model_id: "gemini-3.1-flash-image-preview", models: [{ config_version: 1, contract_validation_status: "verified", credit_cost: 1, enabled: true, is_default: true, model_id: "gemini-3.1-flash-image-preview", prompt_max_length: 1000, recommendation_priority: 1, reference_limits: { max_file_bytes: 1024, max_files: 2, max_total_bytes: 2048 }, runtime_availability: { available_for_new_jobs: true, checked_at: "2026-08-02T13:00:00.000Z", reason: null }, supported_ratios: ["3:4"] }], } })); await page.route("**/api/v1/generations", (route) => route.fulfill({ contentType: "application/json", status: 412, json: { error: { code: "MODEL_CONFIG_VERSION_CONFLICT", correlation_id: "00000000-0000-4000-8000-000000000704", details: { latest_version: 2 }, message_key: "MODEL_CONFIG_VERSION_CONFLICT" } } })); await page.goto(`${webUrl}/app`); await page.getByLabel("描述你想生成的画面").fill("旧配置提交"); await page.getByRole("button", { name: "生成一张图片" }).click(); await expect(page.getByText(/模型配置已更新/)).toBeVisible(); await expect(page.getByRole("button", { name: "确认最新配置" })).toBeVisible(); if (tracePath) await context.tracing.stop({ path: tracePath }); });