From 760bc49d54335e0b22a84e7576811f01a65237cc Mon Sep 17 00:00:00 2001 From: Tarulata Priya Date: Sun, 18 Oct 2026 20:50:17 +0530 Subject: [PATCH] fix(upload): accept valid videos with generic or empty MIME types (#1475) --- src/components/FileUpload.tsx | 13 ++++++++++-- src/hooks/tests/useVideoEditor.test.ts | 29 ++++++++++++++++++++++++++ src/hooks/useVideoEditor.ts | 17 ++++++++++----- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/components/FileUpload.tsx b/src/components/FileUpload.tsx index 8b931a221..864c9d3c1 100644 --- a/src/components/FileUpload.tsx +++ b/src/components/FileUpload.tsx @@ -278,7 +278,16 @@ export default function FileUpload({ setError(""); setWarning(""); - if (!file.type.startsWith("video/")) { + const validExtensions = [".mp4", ".mov", ".avi", ".webm", ".mkv"]; + const filename = file.name.toLowerCase(); + const hasValidExtension = validExtensions.some((ext) => filename.endsWith(ext)); + const isVideoMime = file.type.startsWith("video/"); + const isGenericMime = + !file.type || + file.type === "application/octet-stream" || + file.type === "application/x-matroska"; + + if (!isVideoMime && (!hasValidExtension || !isGenericMime)) { setError("Please drop a valid video file (MP4, MOV, AVI, WebM, etc.)"); return; } @@ -429,7 +438,7 @@ export default function FileUpload({ { const f = e.target.files?.[0]; diff --git a/src/hooks/tests/useVideoEditor.test.ts b/src/hooks/tests/useVideoEditor.test.ts index a99157ec0..c9350ba03 100644 --- a/src/hooks/tests/useVideoEditor.test.ts +++ b/src/hooks/tests/useVideoEditor.test.ts @@ -39,6 +39,7 @@ describe("useVideoEditor core controller", () => { beforeEach(() => { vi.clearAllMocks(); localStorageMock.clear(); + window.history.replaceState(null, "", "/"); }); it("should initialize with the default recipe", () => { @@ -62,6 +63,7 @@ describe("useVideoEditor core controller", () => { it("should ignore invalid patch values via isValidValue check", () => { const { result } = renderHook(() => useVideoEditor()); + expect(result.current.recipe.speed).toBe(DEFAULT_RECIPE.speed); act(() => { // 9999 is invalid for speed, -50 is invalid for quality result.current.updateRecipe({ speed: 9999, quality: -50 } as any); @@ -83,4 +85,31 @@ describe("useVideoEditor core controller", () => { }); expect(result.current.recipe.speed).toBe(DEFAULT_RECIPE.speed); }); + + it("should accept video file with empty or generic MIME type if extension is valid", () => { + const { result } = renderHook(() => useVideoEditor()); + const validFileWithGenericMime = new File(["dummy content"], "test.mp4", { + type: "", + }); + + act(() => { + result.current.handleFileSelect(validFileWithGenericMime); + }); + + expect(result.current.fileError).toBe(""); + expect(result.current.error).toBeNull(); + }); + + it("should reject non-video files even if MIME type is empty or generic", () => { + const { result } = renderHook(() => useVideoEditor()); + const invalidFile = new File(["dummy content"], "document.pdf", { + type: "", + }); + + act(() => { + result.current.handleFileSelect(invalidFile); + }); + + expect(result.current.fileError).toBe("Please upload a video file only."); + }); }); diff --git a/src/hooks/useVideoEditor.ts b/src/hooks/useVideoEditor.ts index 2833bd853..90396194b 100644 --- a/src/hooks/useVideoEditor.ts +++ b/src/hooks/useVideoEditor.ts @@ -424,7 +424,17 @@ export function useVideoEditor() { return; } - if (!selectedFile.type.startsWith("video/")) { + const validExtensions = [".mp4", ".mov", ".avi", ".webm", ".mkv"]; + const filename = selectedFile.name.toLowerCase(); + const hasValidExtension = validExtensions.some((ext) => filename.endsWith(ext)); + + const isVideoMime = selectedFile.type.startsWith("video/"); + const isGenericMime = + !selectedFile.type || + selectedFile.type === "application/octet-stream" || + selectedFile.type === "application/x-matroska"; + + if (!isVideoMime && (!hasValidExtension || !isGenericMime)) { setFileError("Please upload a video file only."); return; } @@ -438,9 +448,6 @@ export function useVideoEditor() { return; } - const validExtensions = [".mp4", ".mov", ".avi", ".webm", ".mkv"]; - const filename = selectedFile.name.toLowerCase(); - const hasValidExtension = validExtensions.some((ext) => filename.endsWith(ext)); if (!hasValidExtension) { setError( `Layer 1 Validation Failed: Invalid file extension. Expected one of: ${validExtensions.join(", ")}` @@ -449,7 +456,7 @@ export function useVideoEditor() { return; } - if (!selectedFile.type.startsWith("video/")) { + if (!isVideoMime && !isGenericMime) { setError( `Layer 2 Validation Failed: Invalid MIME type. Expected video/*, got ${selectedFile.type || "unknown"}` );