import { test, expect } from "#tests/e2e/fixtures/upload" test.describe("File Type and Extension Validation (Integration)", () => { test.describe("Input Accept Attribute", () => { test("should restrict file input to video/* MIME types", async ({ uploadPage, }) => { await expect(uploadPage.fileInput).toHaveAttribute( "accept", "video/*", ) }) }) test.describe("Valid Video Files", () => { test("should accept and upload an MP4 file", async ({ uploadPage }) => { const { page, testVideoPath } = uploadPage await uploadPage.uploadFile(testVideoPath) await expect( page.locator("[data-testid='VerifyStep']"), ).toBeVisible({ timeout: 30_000 }) await expect( page .locator("[data-testid='VerifyStep']") .getByText("Готово к обработке"), ).toBeVisible({ timeout: 10_000 }) }) test("should attempt upload for a WebM file", async ({ uploadPage }) => { const { page, dropZone } = uploadPage // Create a minimal buffer pretending to be WebM const webmBuffer = Buffer.from([ 0x1a, 0x45, 0xdf, 0xa3, // EBML header magic 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, ]) await uploadPage.uploadBuffer("test.webm", "video/webm", webmBuffer) // Upload should begin (progress or error — both prove the file was sent) const uploadStarted = await Promise.race([ dropZone .getByText("Загрузка файла...") .waitFor({ timeout: 5_000 }) .then(() => true) .catch(() => false), dropZone .getByText("Не удалось загрузить файл") .waitFor({ timeout: 5_000 }) .then(() => true) .catch(() => false), page .locator("[data-testid='VerifyStep']") .waitFor({ timeout: 5_000 }) .then(() => true) .catch(() => false), ]) expect(uploadStarted).toBe(true) }) test("should attempt upload for an MOV file", async ({ uploadPage }) => { const { page, dropZone } = uploadPage // Minimal ftyp atom for MOV const movBuffer = Buffer.from([ 0x00, 0x00, 0x00, 0x14, // size: 20 0x66, 0x74, 0x79, 0x70, // ftyp 0x71, 0x74, 0x20, 0x20, // qt (QuickTime) 0x00, 0x00, 0x00, 0x00, // minor version 0x71, 0x74, 0x20, 0x20, // compatible brand ]) await uploadPage.uploadBuffer( "test.mov", "video/quicktime", movBuffer, ) const uploadStarted = await Promise.race([ dropZone .getByText("Загрузка файла...") .waitFor({ timeout: 5_000 }) .then(() => true) .catch(() => false), dropZone .getByText("Не удалось загрузить файл") .waitFor({ timeout: 5_000 }) .then(() => true) .catch(() => false), page .locator("[data-testid='VerifyStep']") .waitFor({ timeout: 5_000 }) .then(() => true) .catch(() => false), ]) expect(uploadStarted).toBe(true) }) }) test.describe("Non-Video Files (Bypass via setInputFiles)", () => { test("should attempt to upload a non-video file (no client-side validation)", async ({ uploadPage, }) => { const { page, dropZone } = uploadPage // setInputFiles bypasses the accept attribute — proves no JS validation const txtBuffer = Buffer.from("Hello, this is a text file") await uploadPage.uploadBuffer( "document.txt", "text/plain", txtBuffer, ) // Upload should begin regardless — component has no file type check const uploadStarted = await Promise.race([ dropZone .getByText("Загрузка файла...") .waitFor({ timeout: 5_000 }) .then(() => true) .catch(() => false), dropZone .getByText("Не удалось загрузить файл") .waitFor({ timeout: 10_000 }) .then(() => true) .catch(() => false), page .locator("[data-testid='VerifyStep']") .waitFor({ timeout: 10_000 }) .then(() => true) .catch(() => false), ]) expect(uploadStarted).toBe(true) }) test("should attempt to upload a PDF file", async ({ uploadPage }) => { const { page, dropZone } = uploadPage const pdfBuffer = Buffer.from("%PDF-1.4 fake content") await uploadPage.uploadBuffer( "document.pdf", "application/pdf", pdfBuffer, ) const uploadStarted = await Promise.race([ dropZone .getByText("Загрузка файла...") .waitFor({ timeout: 5_000 }) .then(() => true) .catch(() => false), dropZone .getByText("Не удалось загрузить файл") .waitFor({ timeout: 10_000 }) .then(() => true) .catch(() => false), page .locator("[data-testid='VerifyStep']") .waitFor({ timeout: 10_000 }) .then(() => true) .catch(() => false), ]) expect(uploadStarted).toBe(true) }) }) test.describe("Edge Cases — File Names", () => { test("should handle a file with Unicode characters in the name", async ({ uploadPage, }) => { const { page, dropZone, testVideoPath } = uploadPage const fs = await import("node:fs") const videoContent = fs.readFileSync(testVideoPath) await uploadPage.uploadBuffer( "видео_тест_2026.mp4", "video/mp4", videoContent, ) // Should upload successfully const result = await Promise.race([ page .locator("[data-testid='VerifyStep']") .waitFor({ timeout: 30_000 }) .then(() => "verify" as const), dropZone .getByText("Не удалось загрузить файл") .waitFor({ timeout: 30_000 }) .then(() => "error" as const), ]) // Both outcomes are valid — we verify no crash expect(["verify", "error"]).toContain(result) }) test("should handle a file with special characters in the name", async ({ uploadPage, }) => { const { page, dropZone, testVideoPath } = uploadPage const fs = await import("node:fs") const videoContent = fs.readFileSync(testVideoPath) await uploadPage.uploadBuffer( "test file (1) [final].mp4", "video/mp4", videoContent, ) const result = await Promise.race([ page .locator("[data-testid='VerifyStep']") .waitFor({ timeout: 30_000 }) .then(() => "verify" as const), dropZone .getByText("Не удалось загрузить файл") .waitFor({ timeout: 30_000 }) .then(() => "error" as const), ]) expect(["verify", "error"]).toContain(result) }) test("should handle a zero-byte video file", async ({ uploadPage }) => { const { page, dropZone } = uploadPage const emptyBuffer = Buffer.alloc(0) await uploadPage.uploadBuffer("empty.mp4", "video/mp4", emptyBuffer) // Should attempt upload, likely fail server-side const result = await Promise.race([ dropZone .getByText("Не удалось загрузить файл") .waitFor({ timeout: 15_000 }) .then(() => "error" as const), page .locator("[data-testid='VerifyStep']") .waitFor({ timeout: 15_000 }) .then(() => "verify" as const), ]) expect(["error", "verify"]).toContain(result) }) test("should handle a file with no extension", async ({ uploadPage, }) => { const { page, dropZone, testVideoPath } = uploadPage const fs = await import("node:fs") const videoContent = fs.readFileSync(testVideoPath) await uploadPage.uploadBuffer( "videofile", "video/mp4", videoContent, ) const result = await Promise.race([ page .locator("[data-testid='VerifyStep']") .waitFor({ timeout: 30_000 }) .then(() => "verify" as const), dropZone .getByText("Не удалось загрузить файл") .waitFor({ timeout: 30_000 }) .then(() => "error" as const), ]) expect(["verify", "error"]).toContain(result) }) test("should handle a file with double extension", async ({ uploadPage, }) => { const { page, dropZone, testVideoPath } = uploadPage const fs = await import("node:fs") const videoContent = fs.readFileSync(testVideoPath) await uploadPage.uploadBuffer( "video.mp4.mp4", "video/mp4", videoContent, ) const result = await Promise.race([ page .locator("[data-testid='VerifyStep']") .waitFor({ timeout: 30_000 }) .then(() => "verify" as const), dropZone .getByText("Не удалось загрузить файл") .waitFor({ timeout: 30_000 }) .then(() => "error" as const), ]) expect(["verify", "error"]).toContain(result) }) }) test.describe("FormData Payload Verification", () => { test("should send file in FormData and include correct folder path", async ({ uploadPage, }) => { const { page, projectId, testVideoPath } = uploadPage let requestFired = false let hasAuthHeader = false let requestUrl = "" page.on("request", (req) => { if (req.url().includes("/api/files/upload")) { requestFired = true requestUrl = req.url() hasAuthHeader = !!req.headers()["authorization"] } }) await uploadPage.uploadFile(testVideoPath) // Wait for the request to fire await expect(async () => { expect(requestFired).toBe(true) }).toPass({ timeout: 10_000 }) expect(requestUrl).toContain("/api/files/upload") expect(hasAuthHeader).toBe(true) // Wait for upload to complete (verify or error) await Promise.race([ page .locator("[data-testid='VerifyStep']") .waitFor({ timeout: 30_000 }), uploadPage.dropZone .getByText("Не удалось загрузить файл") .waitFor({ timeout: 30_000 }), ]) }) }) })