Files
main_frontend/tests/e2e/fixtures/projects.ts
T
2026-04-04 14:51:40 +03:00

180 lines
4.5 KiB
TypeScript

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<void>
mockCreateSuccess(overrides?: Record<string, unknown>): Promise<void>
mockCreateError(status: number, body?: Record<string, unknown>): Promise<void>
mockCreateNetworkError(): Promise<void>
mockCreateDelayed(ms?: number): Promise<void>
}
export const test = base.extend<{ projectsPage: ProjectsPage }>({
projectsPage: async ({ page }, use) => {
let projectsList: Record<string, unknown>[] = []
// 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<string, unknown>) {
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<string, unknown>,
) {
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"