|
| 1 | +// Cases recovered from the deleted `video-editor/backgroundImageUpload.test.ts`, whose |
| 2 | +// module was dropped as dead code in the 2026-07-26 reorg — correctly, since only its own |
| 3 | +// test imported it, but the empty-MIME fallback it encoded had never been wired into the |
| 4 | +// pane that actually handles the upload. These pin the behaviour to the live code path. |
| 5 | +import { cleanup, fireEvent, render } from "@testing-library/react"; |
| 6 | +import { afterEach, describe, expect, it, vi } from "vitest"; |
| 7 | +import { I18nProvider } from "@/contexts/I18nContext"; |
| 8 | +import { BackgroundPane, isSupportedBackgroundImage } from "./RightPanes"; |
| 9 | + |
| 10 | +const toastError = vi.hoisted(() => vi.fn()); |
| 11 | +vi.mock("sonner", () => ({ toast: { error: toastError, success: vi.fn(), info: vi.fn() } })); |
| 12 | + |
| 13 | +afterEach(() => { |
| 14 | + cleanup(); |
| 15 | + toastError.mockClear(); |
| 16 | +}); |
| 17 | + |
| 18 | +describe("background image upload validation", () => { |
| 19 | + it("accepts PNG images for custom backgrounds", () => { |
| 20 | + expect(isSupportedBackgroundImage("image/png", "生成画像1.png")).toBe(true); |
| 21 | + }); |
| 22 | + |
| 23 | + it("accepts PNG images by extension when the browser does not provide a MIME type", () => { |
| 24 | + // The regression this guards: Windows reports no MIME type for some files and |
| 25 | + // locales, and the pane used to drop them silently. |
| 26 | + expect(isSupportedBackgroundImage("", "生成画像1.png")).toBe(true); |
| 27 | + }); |
| 28 | + |
| 29 | + it("keeps rejecting non-image uploads", () => { |
| 30 | + expect(isSupportedBackgroundImage("text/plain", "notes.txt")).toBe(false); |
| 31 | + }); |
| 32 | + |
| 33 | + it("does not allow extension fallback for explicit unsupported MIME types", () => { |
| 34 | + expect(isSupportedBackgroundImage("text/plain", "notes.png")).toBe(false); |
| 35 | + }); |
| 36 | + |
| 37 | + it("accepts jpeg and the non-standard image/jpg some systems emit", () => { |
| 38 | + expect(isSupportedBackgroundImage("image/jpeg", "shot.jpeg")).toBe(true); |
| 39 | + expect(isSupportedBackgroundImage("image/jpg", "shot.jpg")).toBe(true); |
| 40 | + }); |
| 41 | + |
| 42 | + it("ignores case and stray whitespace in either field", () => { |
| 43 | + expect(isSupportedBackgroundImage(" IMAGE/PNG ", "shot.png")).toBe(true); |
| 44 | + expect(isSupportedBackgroundImage("", " SHOT.PNG ")).toBe(true); |
| 45 | + }); |
| 46 | + |
| 47 | + it("rejects a blank type with an extension we do not support", () => { |
| 48 | + expect(isSupportedBackgroundImage("", "clip.webp")).toBe(false); |
| 49 | + expect(isSupportedBackgroundImage("", "noextension")).toBe(false); |
| 50 | + }); |
| 51 | +}); |
| 52 | + |
| 53 | +describe("a rejected upload tells the user", () => { |
| 54 | + function pick(file: File) { |
| 55 | + const { container } = render( |
| 56 | + <I18nProvider> |
| 57 | + <BackgroundPane /> |
| 58 | + </I18nProvider>, |
| 59 | + ); |
| 60 | + const input = container.querySelector('input[type="file"]'); |
| 61 | + if (!(input instanceof HTMLInputElement)) throw new Error("no file input rendered"); |
| 62 | + // jsdom leaves `files` unwritable, so define it the way a real pick would. |
| 63 | + Object.defineProperty(input, "files", { value: [file], configurable: true }); |
| 64 | + fireEvent.change(input); |
| 65 | + } |
| 66 | + |
| 67 | + it("surfaces an error instead of silently dropping the file", () => { |
| 68 | + // The whole point: this used to `return` with no feedback at all. |
| 69 | + pick(new File(["nope"], "notes.txt", { type: "text/plain" })); |
| 70 | + |
| 71 | + expect(toastError).toHaveBeenCalledTimes(1); |
| 72 | + expect(toastError.mock.calls[0]?.[0]).toBe("Unsupported image. Use a JPG or PNG file."); |
| 73 | + }); |
| 74 | + |
| 75 | + it("stays quiet for a file it accepts", () => { |
| 76 | + pick(new File(["x"], "生成画像1.png", { type: "" })); |
| 77 | + |
| 78 | + expect(toastError).not.toHaveBeenCalled(); |
| 79 | + }); |
| 80 | +}); |
0 commit comments