This commit is contained in:
Daniil
2026-04-04 14:51:40 +03:00
parent 10a1d28f77
commit 0523ef3d72
191 changed files with 12065 additions and 2658 deletions
@@ -0,0 +1,246 @@
import { expect, test } from "@playwright/test"
const USER_ID = "00000000-0000-0000-0000-000000000001"
const PROJECT_ID = "65df675b-013b-4b1f-ab2d-075dadbcd0d9"
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 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 recover a missing transcription artifact from project data", async ({
page,
}) => {
let project: Record<string, unknown> = {
id: PROJECT_ID,
owner_id: USER_ID,
name: "Тестовый проект",
description: null,
language: "auto",
folder: null,
status: "DRAFT",
workspace_state: {
wizard: {
current_step: "caption-settings",
completed_steps: [
"upload",
"verify",
"silence-settings",
"processing",
"fragments",
"transcription-settings",
"transcription-processing",
"subtitle-revision",
],
primary_file_key: PRIMARY_FILE_KEY,
video_url: "http://localhost:9000/projects/test/video.mp4",
silence_settings: {
min_silence_duration_ms: 200,
silence_threshold_db: 16,
padding_ms: 100,
},
active_job_id: null,
active_job_type: null,
silence_job_id: null,
transcription_artifact_id: null,
caption_preset_id: CAPTION_PRESET_ID,
caption_style_config: null,
captioned_video_path: null,
},
},
is_active: true,
created_at: "2025-06-01T00:00:00Z",
updated_at: "2025-06-01T00:00:00Z",
}
let savedWizardState: Record<string, unknown> | null = null
let generateRequestBody: Record<string, unknown> | null = null
let generateRequestCount = 0
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) => {
if (route.request().method() === "GET") {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(project),
})
return
}
if (route.request().method() === "PATCH") {
const body = route.request().postDataJSON() as {
workspace_state?: { wizard?: Record<string, unknown> }
}
savedWizardState = body.workspace_state?.wizard ?? null
project = {
...project,
workspace_state: body.workspace_state ?? project.workspace_state,
}
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(project),
})
return
}
await route.fallback()
})
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/transcribe/transcriptions/by-artifact/${TRANSCRIPTION_ARTIFACT_ID}/`,
async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
id: TRANSCRIPTION_ID,
artifact_id: TRANSCRIPTION_ARTIFACT_ID,
}),
})
},
)
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/captions-generate/", async (route) => {
generateRequestCount += 1
generateRequestBody = route.request().postDataJSON() as Record<
string,
unknown
>
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ job_id: CAPTION_JOB_ID }),
})
})
await page.route("**/api/tasks/status/**", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
status: "RUNNING",
progress_pct: 0,
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 expect
.poll(() => savedWizardState?.transcription_artifact_id ?? null)
.toBe(TRANSCRIPTION_ARTIFACT_ID)
await generateButton.click()
expect(generateRequestBody).toMatchObject({
video_s3_path: PRIMARY_FILE_KEY,
transcription_id: TRANSCRIPTION_ID,
project_id: PROJECT_ID,
preset_id: CAPTION_PRESET_ID,
})
expect(generateRequestCount).toBe(1)
await expect
.poll(() => savedWizardState?.current_step ?? null)
.toBe("caption-processing")
await expect
.poll(() => savedWizardState?.active_job_id ?? null)
.toBe(CAPTION_JOB_ID)
await expect(page.locator("[data-testid='ProcessingStep']")).toBeVisible()
})
})
@@ -0,0 +1,125 @@
import { test, expect } from "#tests/e2e/fixtures/real-backend"
// These tests run against the real backend (localhost:8000).
// Each test gets a fresh user with real JWT tokens.
// Created projects are cleaned up automatically after each test.
test.describe("Create Project (Integration)", () => {
test("should create project and see it in the list", async ({
realProjectsPage,
}) => {
const { page, modal } = realProjectsPage
// Empty state
await expect(page.getByText("У вас пока нет проектов")).toBeVisible()
await realProjectsPage.openCreateModal()
await modal.locator("#project_name").fill("Интеграционный тест")
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal).toBeHidden()
await expect(page.getByText("Интеграционный тест")).toBeVisible()
})
test("should create project with description", async ({
realProjectsPage,
}) => {
const { page, modal } = realProjectsPage
await realProjectsPage.openCreateModal()
await modal.locator("#project_name").fill("Проект с описанием")
await modal
.locator("#project_description")
.fill("Описание для интеграционного теста")
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal).toBeHidden()
await expect(page.getByText("Проект с описанием")).toBeVisible()
// Verify via API that description was saved
const projects = await realProjectsPage.getProjects()
const created = projects.find(
(p: { name: string }) => p.name === "Проект с описанием",
)
expect(created).toBeTruthy()
})
test("should create project with Russian language", async ({
realProjectsPage,
}) => {
const { page, modal } = realProjectsPage
await realProjectsPage.openCreateModal()
await modal.locator("#project_name").fill("Русский проект")
await modal.locator("button").filter({ hasText: "Авто" }).click()
await page.locator("[role=option]", { hasText: "Русский" }).click()
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal).toBeHidden()
// Verify language via API
const projects = await realProjectsPage.getProjects()
const created = projects.find(
(p: { name: string }) => p.name === "Русский проект",
) as { language: string } | undefined
expect(created?.language).toBe("ru")
})
test("should create multiple projects", async ({ realProjectsPage }) => {
const { page, modal } = realProjectsPage
// Create first project
await realProjectsPage.openCreateModal()
await modal.locator("#project_name").fill("Первый проект")
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal).toBeHidden()
await expect(page.getByText("Первый проект")).toBeVisible()
// Create second project
await realProjectsPage.openCreateModal()
await modal.locator("#project_name").fill("Второй проект")
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal).toBeHidden()
await expect(page.getByText("Второй проект")).toBeVisible()
// Both visible
await expect(page.getByText("Первый проект")).toBeVisible()
await expect(page.getByText("Второй проект")).toBeVisible()
// Verify via API
const projects = await realProjectsPage.getProjects()
expect(projects.length).toBe(2)
})
test("should persist project after page reload", async ({
realProjectsPage,
}) => {
const { page, modal } = realProjectsPage
await realProjectsPage.openCreateModal()
await modal.locator("#project_name").fill("Персистентный проект")
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal).toBeHidden()
await expect(page.getByText("Персистентный проект")).toBeVisible()
// Reload and verify project is still there
await page.reload()
await page.getByRole("heading", { name: "Мои проекты" }).waitFor()
await expect(page.getByText("Персистентный проект")).toBeVisible()
})
test("should show validation error for empty name (client-side)", async ({
realProjectsPage,
}) => {
const { modal } = realProjectsPage
await realProjectsPage.openCreateModal()
await modal.locator("button", { hasText: "Создать" }).click()
await expect(
modal.getByText("Введите название проекта"),
).toBeVisible()
await expect(modal).toBeVisible()
})
})
@@ -0,0 +1,327 @@
import { expect, test } from "#tests/e2e/fixtures/projects"
interface CreateProjectRequestBody {
description?: string
language?: string
name?: string
}
function requirePostBody(
postBody: CreateProjectRequestBody | null,
): CreateProjectRequestBody {
if (!postBody) {
throw new Error("Expected create project request body to be captured")
}
return postBody
}
// Note: ReactModal sets aria-modal="true" on the dialog, which makes
// Playwright's getByRole() unable to find elements inside or outside the modal.
// All modal content is accessed via CSS locators scoped through `modal`.
test.describe("Create Project Modal", () => {
test.describe("Rendering & UI", () => {
test("should display create project modal with all fields", async ({
projectsPage,
}) => {
const { modal } = projectsPage
await projectsPage.openCreateModal()
await expect(modal.locator("h2")).toHaveText("Создать проект")
await expect(modal.locator("p").first()).toHaveText(
"Заполните основные поля проекта",
)
await expect(modal.locator("#project_name")).toHaveValue("")
await expect(modal.locator("#project_description")).toHaveValue("")
await expect(modal.locator("button", { hasText: "Отмена" })).toBeVisible()
await expect(
modal.locator("button", { hasText: "Создать" }),
).toBeVisible()
})
test("should show default language as Авто", async ({ projectsPage }) => {
const { modal } = projectsPage
await projectsPage.openCreateModal()
const selectTrigger = modal.locator("button").filter({ hasText: "Авто" })
await expect(selectTrigger).toBeVisible()
})
})
test.describe("Happy Path", () => {
test("should create project with name only", async ({ projectsPage }) => {
const { page, modal } = projectsPage
let postBody: CreateProjectRequestBody | null = null
await projectsPage.mockCreateSuccess({ name: "Мой проект" })
page.on("request", (req) => {
if (req.url().includes("/api/projects/") && req.method() === "POST") {
postBody = req.postDataJSON()
}
})
await projectsPage.openCreateModal()
await modal.locator("#project_name").fill("Мой проект")
await modal.locator("button", { hasText: "Создать" }).click()
// Modal should close
await expect(modal).toBeHidden()
const requestBody = requirePostBody(postBody)
expect(requestBody.name).toBe("Мой проект")
expect(requestBody.language).toBe("auto")
})
test("should create project with name and description", async ({
projectsPage,
}) => {
const { page, modal } = projectsPage
let postBody: CreateProjectRequestBody | null = null
await projectsPage.mockCreateSuccess({
name: "Мой проект",
description: "Описание проекта",
})
page.on("request", (req) => {
if (req.url().includes("/api/projects/") && req.method() === "POST") {
postBody = req.postDataJSON()
}
})
await projectsPage.openCreateModal()
await modal.locator("#project_name").fill("Мой проект")
await modal.locator("#project_description").fill("Описание проекта")
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal).toBeHidden()
const requestBody = requirePostBody(postBody)
expect(requestBody.description).toBe("Описание проекта")
})
test("should create project with different language", async ({
projectsPage,
}) => {
const { page, modal } = projectsPage
let postBody: CreateProjectRequestBody | null = null
await projectsPage.mockCreateSuccess({
name: "Мой проект",
language: "ru",
})
page.on("request", (req) => {
if (req.url().includes("/api/projects/") && req.method() === "POST") {
postBody = req.postDataJSON()
}
})
await projectsPage.openCreateModal()
await modal.locator("#project_name").fill("Мой проект")
// Open language select and pick Russian
await modal.locator("button").filter({ hasText: "Авто" }).click()
await page.locator("[role=option]", { hasText: "Русский" }).click()
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal).toBeHidden()
const requestBody = requirePostBody(postBody)
expect(requestBody.language).toBe("ru")
})
test("should refresh projects list after creation", async ({
projectsPage,
}) => {
const { page, modal } = projectsPage
// Verify empty state
await expect(page.getByText("У вас пока нет проектов")).toBeVisible()
await projectsPage.mockCreateSuccess({ name: "Новый проект" })
await projectsPage.openCreateModal()
await modal.locator("#project_name").fill("Новый проект")
await modal.locator("button", { hasText: "Создать" }).click()
// Modal closes and project appears in list
await expect(modal).toBeHidden()
await expect(page.getByText("У вас пока нет проектов")).toBeHidden()
await expect(page.getByText("Новый проект")).toBeVisible()
})
})
test.describe("Validation", () => {
test("should show validation error for empty name", async ({
projectsPage,
}) => {
const { page, modal } = projectsPage
let postFired = false
page.on("request", (req) => {
if (req.url().includes("/api/projects/") && req.method() === "POST") {
postFired = true
}
})
await projectsPage.openCreateModal()
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal.getByText("Введите название проекта")).toBeVisible()
expect(postFired).toBe(false)
// Modal stays open
await expect(modal).toBeVisible()
})
test("should show validation error for whitespace-only name", async ({
projectsPage,
}) => {
const { modal } = projectsPage
await projectsPage.openCreateModal()
await modal.locator("#project_name").fill(" ")
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal.getByText("Введите название проекта")).toBeVisible()
})
test("should clear validation error after correcting name", async ({
projectsPage,
}) => {
const { modal } = projectsPage
await projectsPage.mockCreateSuccess({ name: "Проект" })
await projectsPage.openCreateModal()
// Trigger validation error
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal.getByText("Введите название проекта")).toBeVisible()
// Fix and resubmit
await modal.locator("#project_name").fill("Проект")
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal).toBeHidden()
})
})
test.describe("Error States", () => {
test("should keep modal open on server error (500)", async ({
projectsPage,
}) => {
const { page, modal } = projectsPage
const consoleErrors: string[] = []
page.on("console", (msg) => {
if (msg.type() === "error") {
consoleErrors.push(msg.text())
}
})
await projectsPage.mockCreateError(500)
await projectsPage.openCreateModal()
await modal.locator("#project_name").fill("Проект")
await modal.locator("button", { hasText: "Создать" }).click()
// Wait for error to be processed
await page.waitForTimeout(1000)
// Modal stays open, buttons re-enable
await expect(modal).toBeVisible()
await expect(
modal.locator("button", { hasText: "Создать" }),
).toBeEnabled()
await expect(modal.locator("button", { hasText: "Отмена" })).toBeEnabled()
expect(
consoleErrors.some((e) => e.includes("Create project failed")),
).toBe(true)
})
test("should keep modal open on network error", async ({
projectsPage,
}) => {
const { page, modal } = projectsPage
await projectsPage.mockCreateNetworkError()
await projectsPage.openCreateModal()
await modal.locator("#project_name").fill("Проект")
await modal.locator("button", { hasText: "Создать" }).click()
await page.waitForTimeout(1000)
await expect(modal).toBeVisible()
await expect(
modal.locator("button", { hasText: "Создать" }),
).toBeEnabled()
await expect(modal.locator("button", { hasText: "Отмена" })).toBeEnabled()
})
test("should allow retry after failure", async ({ projectsPage }) => {
const { page, modal } = projectsPage
// First attempt: 500 error
await projectsPage.mockCreateError(500)
await projectsPage.openCreateModal()
await modal.locator("#project_name").fill("Проект")
await modal.locator("button", { hasText: "Создать" }).click()
await page.waitForTimeout(1000)
await expect(
modal.locator("button", { hasText: "Создать" }),
).toBeEnabled()
// Second attempt: success (re-mock the route)
await projectsPage.mockCreateSuccess({ name: "Проект" })
await modal.locator("button", { hasText: "Создать" }).click()
await expect(modal).toBeHidden()
})
})
test.describe("Form Behavior", () => {
test("should reset form when modal is closed and reopened", async ({
projectsPage,
}) => {
const { modal } = projectsPage
await projectsPage.openCreateModal()
await modal.locator("#project_name").fill("Черновик")
await modal.locator("#project_description").fill("Описание черновика")
// Close with Cancel
await modal.locator("button", { hasText: "Отмена" }).click()
await expect(modal).toBeHidden()
// Reopen
await projectsPage.openCreateModal()
await expect(modal.locator("#project_name")).toHaveValue("")
await expect(modal.locator("#project_description")).toHaveValue("")
await expect(
modal.locator("button").filter({ hasText: "Авто" }),
).toBeVisible()
})
test("should disable buttons while request is pending", async ({
projectsPage,
}) => {
const { modal } = projectsPage
await projectsPage.mockCreateDelayed(2000)
await projectsPage.openCreateModal()
await modal.locator("#project_name").fill("Проект")
await modal.locator("button", { hasText: "Создать" }).click()
await expect(
modal.locator("button", { hasText: "Создать" }),
).toBeDisabled()
await expect(
modal.locator("button", { hasText: "Отмена" }),
).toBeDisabled()
})
})
})
@@ -0,0 +1,260 @@
import { expect, test } from "@playwright/test"
const USER_ID = "00000000-0000-0000-0000-000000000001"
const PROJECT_ID = "75df675b-013b-4b1f-ab2d-075dadbcd0d9"
const DETECT_JOB_ID = "00000000-0000-0000-0000-000000000050"
const APPLY_JOB_ID = "00000000-0000-0000-0000-000000000051"
const TRANSCRIPTION_JOB_ID = "00000000-0000-0000-0000-000000000052"
const ORIGINAL_FILE_KEY = "projects/test/original-video.mp4"
const ORIGINAL_FILE_URL = "http://localhost:4444/files/original-video.mp4"
const CUT_FILE_KEY = "projects/test/cut-video.mp4"
const CUT_FILE_URL = "http://localhost:4444/files/cut-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",
}
const MOCK_SEGMENTS = [
{ start_ms: 5000, end_ms: 8000 },
{ start_ms: 15000, end_ms: 19000 },
]
test.describe("Silence Apply Flow", () => {
test("should show processing for cut application and transcribe the processed video", async ({
page,
}) => {
let project: Record<string, unknown> = {
id: PROJECT_ID,
owner_id: USER_ID,
name: "Тестовый проект",
description: null,
language: "auto",
folder: null,
status: "DRAFT",
workspace_state: {
wizard: {
current_step: "fragments",
completed_steps: [
"upload",
"verify",
"silence-settings",
"processing",
],
primary_file_key: ORIGINAL_FILE_KEY,
video_url: ORIGINAL_FILE_URL,
original_file_name: "original-video.mp4",
silence_settings: {
min_silence_duration_ms: 200,
silence_threshold_db: 16,
padding_ms: 100,
},
active_job_id: null,
active_job_type: null,
silence_job_id: DETECT_JOB_ID,
transcription_artifact_id: null,
caption_preset_id: null,
caption_style_config: null,
captioned_video_path: null,
captioned_video_file_id: null,
},
},
is_active: true,
created_at: "2025-06-01T00:00:00Z",
updated_at: "2025-06-01T00:00:00Z",
}
let savedWizardState: Record<string, unknown> | null = null
let applyStatus = "RUNNING"
let transcriptionRequestBody: Record<string, unknown> | null = 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) => {
if (route.request().method() === "GET") {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(project),
})
return
}
if (route.request().method() === "PATCH") {
const body = route.request().postDataJSON() as {
workspace_state?: { wizard?: Record<string, unknown> }
}
savedWizardState = body.workspace_state?.wizard ?? null
project = {
...project,
workspace_state: body.workspace_state ?? project.workspace_state,
}
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(project),
})
return
}
await route.fallback()
})
await page.route("**/api/files/get_file/**", async (route) => {
const url = new URL(route.request().url())
const filePath = url.searchParams.get("file_path")
const fileUrl =
filePath === CUT_FILE_KEY ? CUT_FILE_URL : ORIGINAL_FILE_URL
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
file_url: fileUrl,
file_path: filePath,
}),
})
})
await page.route("**/api/tasks/status/**", async (route) => {
const url = route.request().url()
if (url.includes(DETECT_JOB_ID)) {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
status: "DONE",
job_type: "SILENCE_DETECT",
progress_pct: 100,
output_data: {
silent_segments: MOCK_SEGMENTS,
duration_ms: 30000,
},
}),
})
return
}
if (url.includes(APPLY_JOB_ID)) {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
status: applyStatus,
job_type: "SILENCE_APPLY",
progress_pct: applyStatus === "DONE" ? 100 : 30,
output_data:
applyStatus === "DONE"
? {
file_path: CUT_FILE_KEY,
file_url: CUT_FILE_URL,
}
: null,
}),
})
return
}
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
status: "RUNNING",
progress_pct: 0,
output_data: null,
}),
})
})
await page.route("**/api/tasks/silence-apply/", async (route) => {
await route.fulfill({
status: 202,
contentType: "application/json",
body: JSON.stringify({ job_id: APPLY_JOB_ID }),
})
})
await page.route("**/api/tasks/transcription-generate/", async (route) => {
transcriptionRequestBody = route.request().postDataJSON() as Record<
string,
unknown
>
await route.fulfill({
status: 202,
contentType: "application/json",
body: JSON.stringify({ job_id: TRANSCRIPTION_JOB_ID }),
})
})
await page.goto(`/projects/${PROJECT_ID}`)
const fragmentsStep = page.locator("[data-testid='FragmentsStep']")
await expect(fragmentsStep).toBeVisible()
await fragmentsStep.getByRole("button", { name: "Применить" }).click()
await expect(page.locator("[data-testid='ProcessingStep']")).toBeVisible()
await expect
.poll(() => savedWizardState?.active_job_type ?? null)
.toBe("SILENCE_APPLY")
await expect
.poll(() => savedWizardState?.current_step ?? null)
.toBe("processing")
applyStatus = "DONE"
const transcriptionStep = page.locator(
"[data-testid='TranscriptionSettingsStep']",
)
await expect(transcriptionStep).toBeVisible({ timeout: 10_000 })
await expect
.poll(() => savedWizardState?.primary_file_key ?? null)
.toBe(CUT_FILE_KEY)
await transcriptionStep
.getByRole("button", { name: "Сгенерировать субтитры" })
.click()
expect(transcriptionRequestBody).toMatchObject({
file_key: CUT_FILE_KEY,
project_id: PROJECT_ID,
})
})
})