iter 2
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
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"
|
||||
Reference in New Issue
Block a user