chore: something changed, commit before reorg
This commit is contained in:
@@ -2,7 +2,6 @@ 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_ID = "00000000-0000-0000-0000-000000000060"
|
||||
@@ -34,51 +33,50 @@ const MOCK_SEGMENTS = [
|
||||
]
|
||||
|
||||
test.describe("Silence Apply Flow", () => {
|
||||
test("should show processing for cut application and transcribe the processed video", async ({
|
||||
test("should persist cuts via workflow actions and continue to transcription on processed source file", 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_id: ORIGINAL_FILE_ID,
|
||||
primary_file_key: ORIGINAL_FILE_KEY,
|
||||
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,
|
||||
},
|
||||
let applyStatus: "RUNNING" | "DONE" = "RUNNING"
|
||||
const workflowActions: Array<Record<string, unknown>> = []
|
||||
let workspace: Record<string, any> = {
|
||||
revision: 1,
|
||||
phase: "SILENCE",
|
||||
current_screen: "fragments",
|
||||
active_job: null,
|
||||
source_file_id: ORIGINAL_FILE_ID,
|
||||
workspace_view: {
|
||||
used_file_ids: [],
|
||||
selected_file_id: null,
|
||||
},
|
||||
silence: {
|
||||
status: "REVIEW_READY",
|
||||
settings: {
|
||||
min_silence_duration_ms: 200,
|
||||
silence_threshold_db: 16,
|
||||
padding_ms: 100,
|
||||
},
|
||||
detect_job_id: "00000000-0000-0000-0000-000000000050",
|
||||
detected_segments: MOCK_SEGMENTS,
|
||||
reviewed_cuts: [],
|
||||
duration_ms: 30000,
|
||||
applied_output_file_id: null,
|
||||
},
|
||||
transcription: {
|
||||
status: "IDLE",
|
||||
job_id: null,
|
||||
request: null,
|
||||
artifact_id: null,
|
||||
transcription_id: null,
|
||||
reviewed: false,
|
||||
},
|
||||
captions: {
|
||||
status: "IDLE",
|
||||
preset_id: null,
|
||||
style_config: null,
|
||||
render_job_id: null,
|
||||
output_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([
|
||||
{
|
||||
@@ -104,35 +102,154 @@ test.describe("Silence Apply Flow", () => {
|
||||
})
|
||||
|
||||
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
|
||||
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) => {
|
||||
if (
|
||||
applyStatus === "DONE" &&
|
||||
workspace.current_screen === "silence-apply-processing"
|
||||
) {
|
||||
workspace = {
|
||||
...workspace,
|
||||
revision: 4,
|
||||
phase: "TRANSCRIPTION",
|
||||
current_screen: "transcription-settings",
|
||||
active_job: null,
|
||||
source_file_id: CUT_FILE_ID,
|
||||
silence: {
|
||||
...workspace.silence,
|
||||
status: "APPLIED",
|
||||
applied_output_file_id: CUT_FILE_ID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (route.request().method() === "PATCH") {
|
||||
const body = route.request().postDataJSON() as {
|
||||
workspace_state?: { wizard?: Record<string, unknown> }
|
||||
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 === "SET_SILENCE_CUTS") {
|
||||
workspace = {
|
||||
...workspace,
|
||||
revision: 2,
|
||||
silence: {
|
||||
...workspace.silence,
|
||||
reviewed_cuts: action.cuts as typeof MOCK_SEGMENTS,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
savedWizardState = body.workspace_state?.wizard ?? null
|
||||
project = {
|
||||
...project,
|
||||
workspace_state: body.workspace_state ?? project.workspace_state,
|
||||
if (action.type === "START_SILENCE_APPLY") {
|
||||
workspace = {
|
||||
...workspace,
|
||||
revision: 3,
|
||||
current_screen: "silence-apply-processing",
|
||||
active_job: {
|
||||
job_id: APPLY_JOB_ID,
|
||||
job_type: "SILENCE_APPLY",
|
||||
},
|
||||
silence: {
|
||||
...workspace.silence,
|
||||
status: "APPLYING",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (action.type === "START_TRANSCRIPTION") {
|
||||
workspace = {
|
||||
...workspace,
|
||||
revision: 5,
|
||||
current_screen: "transcription-processing",
|
||||
active_job: {
|
||||
job_id: TRANSCRIPTION_JOB_ID,
|
||||
job_type: "TRANSCRIPTION_GENERATE",
|
||||
},
|
||||
transcription: {
|
||||
...workspace.transcription,
|
||||
status: "RUNNING",
|
||||
job_id: TRANSCRIPTION_JOB_ID,
|
||||
request: action.request as {
|
||||
engine: "whisper"
|
||||
language?: string
|
||||
model: string
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify(project),
|
||||
body: JSON.stringify(workspace),
|
||||
})
|
||||
return
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
await route.fallback()
|
||||
await page.route("**/api/files/files/", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify([
|
||||
{
|
||||
id: ORIGINAL_FILE_ID,
|
||||
project_id: PROJECT_ID,
|
||||
owner_id: USER_ID,
|
||||
original_filename: "original-video.mp4",
|
||||
path: ORIGINAL_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",
|
||||
},
|
||||
{
|
||||
id: CUT_FILE_ID,
|
||||
project_id: PROJECT_ID,
|
||||
owner_id: USER_ID,
|
||||
original_filename: "cut-video.mp4",
|
||||
path: CUT_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/*/resolve/", async (route) => {
|
||||
@@ -146,30 +263,50 @@ test.describe("Silence Apply Flow", () => {
|
||||
file_id: isCutFile ? CUT_FILE_ID : ORIGINAL_FILE_ID,
|
||||
file_url: isCutFile ? CUT_FILE_URL : ORIGINAL_FILE_URL,
|
||||
file_path: isCutFile ? CUT_FILE_KEY : ORIGINAL_FILE_KEY,
|
||||
filename: isCutFile ? "cut-video.mp4" : "original-video.mp4",
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
await page.route("**/api/files/files/*/", async (route) => {
|
||||
const fileId = route.request().url().split("/files/")[1]?.split("/")[0]
|
||||
const isCutFile = fileId === CUT_FILE_ID
|
||||
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
id: isCutFile ? CUT_FILE_ID : ORIGINAL_FILE_ID,
|
||||
project_id: PROJECT_ID,
|
||||
owner_id: USER_ID,
|
||||
original_filename: isCutFile
|
||||
? "cut-video.mp4"
|
||||
: "original-video.mp4",
|
||||
path: isCutFile ? CUT_FILE_KEY : ORIGINAL_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/media/artifacts/", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify([]),
|
||||
})
|
||||
})
|
||||
|
||||
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,
|
||||
@@ -190,6 +327,20 @@ test.describe("Silence Apply Flow", () => {
|
||||
return
|
||||
}
|
||||
|
||||
if (url.includes(TRANSCRIPTION_JOB_ID)) {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
status: "RUNNING",
|
||||
job_type: "TRANSCRIPTION_GENERATE",
|
||||
progress_pct: 10,
|
||||
output_data: null,
|
||||
}),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
@@ -201,60 +352,45 @@ test.describe("Silence Apply Flow", () => {
|
||||
})
|
||||
})
|
||||
|
||||
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 expect(page.locator("[data-testid='FragmentsStep']")).toBeVisible()
|
||||
await expect(page.locator("[data-testid='cut-region']")).toHaveCount(2)
|
||||
|
||||
await fragmentsStep.getByRole("button", { name: "Применить" }).click()
|
||||
await page.getByRole("button", { name: "Применить" }).click()
|
||||
|
||||
await expect.poll(() => workflowActions.length).toBe(2)
|
||||
|
||||
expect(workflowActions[0]).toMatchObject({
|
||||
type: "SET_SILENCE_CUTS",
|
||||
revision: 1,
|
||||
})
|
||||
expect(workflowActions[1]).toMatchObject({
|
||||
type: "START_SILENCE_APPLY",
|
||||
revision: 2,
|
||||
})
|
||||
|
||||
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(
|
||||
page.locator("[data-testid='TranscriptionSettingsStep']"),
|
||||
).toBeVisible()
|
||||
|
||||
await expect
|
||||
.poll(() => savedWizardState?.primary_file_key ?? null)
|
||||
.toBe(CUT_FILE_KEY)
|
||||
await page.getByRole("button", { name: "Сгенерировать субтитры" }).click()
|
||||
|
||||
await transcriptionStep
|
||||
.getByRole("button", { name: "Сгенерировать субтитры" })
|
||||
.click()
|
||||
|
||||
expect(transcriptionRequestBody).toMatchObject({
|
||||
file_key: CUT_FILE_KEY,
|
||||
project_id: PROJECT_ID,
|
||||
expect(workflowActions[2]).toMatchObject({
|
||||
type: "START_TRANSCRIPTION",
|
||||
revision: 4,
|
||||
request: {
|
||||
engine: "whisper",
|
||||
model: "base",
|
||||
},
|
||||
})
|
||||
|
||||
await expect(page.locator("[data-testid='ProcessingStep']")).toContainText(
|
||||
"ТРАНСКРИБАЦИЯ",
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user