295 lines
7.2 KiB
TypeScript
295 lines
7.2 KiB
TypeScript
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<Record<string, unknown>> = []
|
|
let workspace: Record<string, any> = {
|
|
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<string, unknown>
|
|
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()
|
|
})
|
|
})
|