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

160 lines
3.9 KiB
TypeScript

import path from "node:path"
import { test as base, type Locator, type Page } from "@playwright/test"
import {
createProjectViaApi,
deleteProjectViaApi,
loginAsAdmin,
} from "#tests/e2e/support/auth-api"
export const MOCK_SEGMENTS = [
{ start_ms: 5000, end_ms: 8000 },
{ start_ms: 15000, end_ms: 19000 },
{ start_ms: 32000, end_ms: 35000 },
{ start_ms: 45000, end_ms: 50000 },
]
export const MOCK_DURATION_MS = 60000
export const MOCK_TOTAL_REMOVED_MS = MOCK_SEGMENTS.reduce(
(sum, s) => sum + (s.end_ms - s.start_ms),
0,
)
interface FragmentsPage {
page: Page
projectId: string
fragmentsStep: Locator
jobId: string
}
export const test = base.extend<{ fragmentsPage: FragmentsPage }>({
fragmentsPage: async ({ page }, use) => {
const tokens = await loginAsAdmin()
await page.context().addCookies([
{
name: "access_token",
value: tokens.accessToken,
domain: "localhost",
path: "/",
},
{
name: "refresh_token",
value: tokens.refreshToken,
domain: "localhost",
path: "/",
},
])
const suffix = Date.now().toString(36)
const projectId = await createProjectViaApi(
tokens.accessToken,
`fragments-test-${suffix}`,
)
// Navigate to project wizard
await page.goto(`/projects/${projectId}`)
await page.locator("[data-testid='ProjectWizard']").waitFor()
// Upload test video file
const testVideoPath = path.resolve(
__dirname,
"../assets/test-video.mp4",
)
const fileInput = page
.locator("[data-testid='UploadStep']")
.locator("input[type='file']")
await fileInput.setInputFiles(testVideoPath)
// Wait for wizard to advance to Verify step
await page
.locator("[data-testid='VerifyStep']")
.waitFor({ timeout: 30_000 })
// Wait for file processing to complete
await page
.locator("[data-testid='VerifyStep']")
.getByText("Готово к обработке")
.waitFor({ timeout: 10_000 })
// Advance to Silence Settings step
await page
.getByRole("button", { name: "Далее: Настройки тишины" })
.click()
const silenceStep = page.locator("[data-testid='SilenceSettingsStep']")
await silenceStep.waitFor({ timeout: 10_000 })
// Intercept task status polling — initially return RUNNING
let taskStatusResponse = {
status: "RUNNING",
progress_pct: 0,
output_data: null as Record<string, unknown> | null,
}
await page.route("**/api/tasks/status/**", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(taskStatusResponse),
})
})
// Capture job_id from the silence-detect submission
let capturedJobId = ""
page.on("response", async (res) => {
if (
res.url().includes("/api/tasks/silence-detect/") &&
res.request().method() === "POST" &&
res.status() === 200
) {
try {
const body = await res.json()
if (body?.job_id) capturedJobId = body.job_id
} catch {
// ignore
}
}
})
// Click "Далее" to submit silence detection
await silenceStep.getByRole("button", { name: "Далее" }).click()
// Wait for ProcessingStep to appear
await page
.locator("[data-testid='ProcessingStep']")
.waitFor({ timeout: 10_000 })
// Now switch the task status to DONE with mock data to trigger auto-advance
taskStatusResponse = {
status: "DONE",
progress_pct: 100,
output_data: {
silent_segments: MOCK_SEGMENTS,
duration_ms: MOCK_DURATION_MS,
},
}
// Wait for auto-advance to FragmentsStep (polls every 2s)
const fragmentsStep = page.locator("[data-testid='FragmentsStep']")
await fragmentsStep.waitFor({ timeout: 15_000 })
const fragmentsPage: FragmentsPage = {
page,
projectId,
fragmentsStep,
jobId: capturedJobId,
}
await use(fragmentsPage)
// Cleanup: delete project
try {
await deleteProjectViaApi(tokens.accessToken, projectId)
} catch {
// Best-effort cleanup
}
},
})
export { expect } from "@playwright/test"