import { test as base, type Locator, type Page, type Route } from "@playwright/test" const DEFAULT_USER = { id: "00000000-0000-0000-0000-000000000001", username: "testuser", email: "test@example.com", first_name: "Test", last_name: "User", phone_number: null, avatar: null, email_verified: true, phone_verified: false, is_active: true, is_staff: false, is_superuser: false, date_joined: "2025-01-01T00:00:00Z", } const DEFAULT_PROJECT = { id: "00000000-0000-0000-0000-000000000002", owner_id: "00000000-0000-0000-0000-000000000001", name: "Тестовый проект", description: null, language: "auto", folder: null, status: "DRAFT", workspace_state: null, is_active: true, created_at: "2025-06-01T00:00:00Z", updated_at: "2025-06-01T00:00:00Z", } interface ProjectsPage { page: Page /** Locator for the modal dialog (aria-modal prevents getByRole from working) */ modal: Locator openCreateModal(): Promise mockCreateSuccess(overrides?: Record): Promise mockCreateError(status: number, body?: Record): Promise mockCreateNetworkError(): Promise mockCreateDelayed(ms?: number): Promise } export const test = base.extend<{ projectsPage: ProjectsPage }>({ projectsPage: async ({ page }, use) => { let projectsList: Record[] = [] // Set auth cookies await page.context().addCookies([ { name: "access_token", value: "fake-access-jwt", domain: "localhost", path: "/", }, { name: "refresh_token", value: "fake-refresh-jwt", domain: "localhost", path: "/", }, ]) // Mock GET /api/users/me/ await page.route("**/api/users/me/", async (route: Route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(DEFAULT_USER), }) }) // Mock GET /api/projects/ (stateful) await page.route("**/api/projects/*", async (route: Route) => { if (route.request().method() === "GET") { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(projectsList), }) } else { await route.fallback() } }) await page.route("**/api/projects/", async (route: Route) => { if (route.request().method() === "GET") { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(projectsList), }) } else { await route.fallback() } }) await page.goto("/projects") await page.getByRole("heading", { name: "Мои проекты" }).waitFor() const modal = page.locator("[role=dialog]") const projectsPage: ProjectsPage = { page, modal, async openCreateModal() { await page.getByRole("button", { name: /Создать проект/ }).click() await modal.waitFor({ state: "visible" }) }, async mockCreateSuccess(overrides?: Record) { const project = { ...DEFAULT_PROJECT, ...overrides } await page.route("**/api/projects/", async (route: Route) => { if (route.request().method() === "POST") { projectsList.push(project) await route.fulfill({ status: 201, contentType: "application/json", body: JSON.stringify(project), }) } else { await route.fallback() } }) }, async mockCreateError( status: number, body?: Record, ) { await page.route("**/api/projects/", async (route: Route) => { if (route.request().method() === "POST") { await route.fulfill({ status, contentType: "application/json", body: JSON.stringify(body ?? { detail: "Server error" }), }) } else { await route.fallback() } }) }, async mockCreateNetworkError() { await page.route("**/api/projects/", async (route: Route) => { if (route.request().method() === "POST") { await route.abort() } else { await route.fallback() } }) }, async mockCreateDelayed(ms = 2000) { const project = { ...DEFAULT_PROJECT } await page.route("**/api/projects/", async (route: Route) => { if (route.request().method() === "POST") { await new Promise((r) => setTimeout(r, ms)) projectsList.push(project) await route.fulfill({ status: 201, contentType: "application/json", body: JSON.stringify(project), }) } else { await route.fallback() } }) }, } await use(projectsPage) }, }) export { expect } from "@playwright/test"