import { expect, test } from "@playwright/test" const USER_ID = "00000000-0000-0000-0000-000000000001" const PROJECT_ID = "65df675b-013b-4b1f-ab2d-075dadbcd0d9" const SOURCE_FILE_ID = "00000000-0000-0000-0000-000000000011" const CAPTION_PRESET_ID = "00000000-0000-0000-0000-000000000010" const TRANSCRIPTION_ARTIFACT_ID = "00000000-0000-0000-0000-000000000020" const TRANSCRIPTION_ID = "00000000-0000-0000-0000-000000000030" const CAPTION_JOB_ID = "00000000-0000-0000-0000-000000000040" const PRIMARY_FILE_KEY = "projects/test/video.mp4" const PRIMARY_FILE_URL = "http://localhost:4444/files/video.mp4" const DEFAULT_USER = { id: USER_ID, 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", } test.describe("Caption Settings Step", () => { test("should render from typed workspace and start caption render via workflow action", async ({ page, }) => { let workflowActions: Array> = [] let workspace: Record = { revision: 1, phase: "CAPTIONS", current_screen: "caption-settings", active_job: null, source_file_id: SOURCE_FILE_ID, workspace_view: { used_file_ids: [], selected_file_id: null, }, silence: { status: "SKIPPED", settings: { min_silence_duration_ms: 200, silence_threshold_db: 16, padding_ms: 100, }, detect_job_id: null, detected_segments: [], reviewed_cuts: [], duration_ms: null, applied_output_file_id: null, }, transcription: { status: "REVIEW_READY", job_id: null, request: null, artifact_id: TRANSCRIPTION_ARTIFACT_ID, transcription_id: TRANSCRIPTION_ID, reviewed: true, }, captions: { status: "CONFIG_READY", preset_id: CAPTION_PRESET_ID, style_config: null, render_job_id: null, output_file_id: null, }, } await page.context().addCookies([ { name: "access_token", value: "fake-access-jwt", domain: "localhost", path: "/", }, { name: "refresh_token", value: "fake-refresh-jwt", domain: "localhost", path: "/", }, ]) await page.route("**/api/users/me/", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(DEFAULT_USER), }) }) await page.route(`**/api/projects/${PROJECT_ID}/`, async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ id: PROJECT_ID, owner_id: USER_ID, 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", }), }) }) await page.route(`**/api/projects/${PROJECT_ID}/workspace*`, async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(workspace), }) }) await page.route( `**/api/projects/${PROJECT_ID}/workflow/actions*`, async (route) => { const action = route.request().postDataJSON() as Record workflowActions.push(action) if (action.type === "START_CAPTION_RENDER") { workspace = { ...workspace, revision: 2, current_screen: "caption-processing", active_job: { job_id: CAPTION_JOB_ID, job_type: "CAPTIONS_GENERATE", }, captions: { ...workspace.captions, status: "RUNNING", render_job_id: CAPTION_JOB_ID, }, } } await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(workspace), }) }, ) await page.route("**/api/files/files/", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify([ { id: SOURCE_FILE_ID, project_id: PROJECT_ID, owner_id: USER_ID, original_filename: "video.mp4", path: PRIMARY_FILE_KEY, storage_backend: "S3", mime_type: "video/mp4", size_bytes: 1024, checksum: null, file_format: "mp4", is_uploaded: true, is_deleted: false, is_active: true, created_at: "2025-06-01T00:00:00Z", }, ]), }) }) await page.route(`**/api/files/files/${SOURCE_FILE_ID}/`, async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ id: SOURCE_FILE_ID, project_id: PROJECT_ID, owner_id: USER_ID, original_filename: "video.mp4", path: PRIMARY_FILE_KEY, storage_backend: "S3", mime_type: "video/mp4", size_bytes: 1024, checksum: null, file_format: "mp4", is_uploaded: true, is_deleted: false, is_active: true, created_at: "2025-06-01T00:00:00Z", }), }) }) await page.route( `**/api/files/files/${SOURCE_FILE_ID}/resolve/`, async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ file_id: SOURCE_FILE_ID, file_url: PRIMARY_FILE_URL, file_path: PRIMARY_FILE_KEY, filename: "video.mp4", }), }) }, ) await page.route("**/api/media/artifacts/", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify([ { id: TRANSCRIPTION_ARTIFACT_ID, project_id: PROJECT_ID, file_id: null, media_file_id: null, artifact_type: "TRANSCRIPTION_JSON", is_deleted: false, is_active: true, created_at: "2025-06-01T00:00:00Z", updated_at: "2025-06-01T00:00:00Z", }, ]), }) }) await page.route("**/api/captions/presets/", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify([ { id: CAPTION_PRESET_ID, user_id: null, name: "Системный пресет", description: null, is_system: true, style_config: {}, preview_url: null, created_at: "2025-06-01T00:00:00Z", updated_at: "2025-06-01T00:00:00Z", }, ]), }) }) await page.route("**/api/tasks/status/**", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ status: "RUNNING", progress_pct: 25, output_data: null, }), }) }) await page.goto(`/projects/${PROJECT_ID}`) const captionStep = page.locator("[data-testid='CaptionSettingsStep']") const generateButton = captionStep.getByRole("button", { name: "Генерировать", }) await expect(captionStep).toBeVisible() await expect(captionStep.getByText("Системный пресет")).toBeVisible() await expect(generateButton).toBeEnabled() await generateButton.click() expect(workflowActions).toHaveLength(1) expect(workflowActions[0]).toMatchObject({ type: "START_CAPTION_RENDER", revision: 1, }) await expect(page.locator("[data-testid='ProcessingStep']")).toBeVisible() }) })