fix(downloads): GIF review round 1 — shape, HDR, caps, audio, copy
- A GIF squares its pixels before the size, so an anamorphic source keeps
its shown shape (a 720x480 DVD at 16:9 was 480x320).
- An editor GIF of an HDR upload is tonemapped, as a clip GIF is.
- The length caps are judged in whole milliseconds: a range exactly at a
cap is no longer refused for a float hair over it.
- A GIF is made of a video only: an audio file is refused with its reason
and the editor offers no GIF for it.
- A GIF clip keeps no audio track: the track neither splits its cache key
nor fails it.
- The editor's GIF notes keep their live region mounted; one size reads
as one ("about 1 MB"), none is shown with nothing kept; the size choices
show their unit; a shared picture that fails to load says so.
- Copy: the two-sentence GIF notes keep their last stop (a copy-rule test
now holds it); the English warns of "only a still picture".
This commit is contained in:
@@ -14,7 +14,11 @@ vi.mock("react-i18next", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("react-i18next")>();
|
||||
return {
|
||||
...actual,
|
||||
useTranslation: () => ({ t: (k: string) => k, i18n: { language: "en" } }),
|
||||
// A size option reads as its own words with its unit ("480 px"); every other text is its key.
|
||||
useTranslation: () => ({
|
||||
t: (k: string, o?: { n?: string }) => (k === "clip.gif.side" ? `${o?.n} px` : k),
|
||||
i18n: { language: "en" },
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -281,7 +285,7 @@ describe("ClipPanel GIF", () => {
|
||||
render(<Harness onClose={onClose} start={{ start: 100, end: 108 }} />);
|
||||
expect(screen.queryByRole("group", { name: "clip.gif.size" })).toBeNull();
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.formatGif" }));
|
||||
fireEvent.click(screen.getByRole("button", { name: "320" }));
|
||||
fireEvent.click(screen.getByRole("button", { name: "320 px" }));
|
||||
expect(enqueueClip).not.toHaveBeenCalled();
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.gif.make" }));
|
||||
await waitFor(() => expect(onClose).toHaveBeenCalled());
|
||||
@@ -298,7 +302,9 @@ describe("ClipPanel GIF", () => {
|
||||
it("starts at the default size, and a video again sends no GIF", async () => {
|
||||
render(<Harness start={{ start: 100, end: 108 }} />);
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.formatGif" }));
|
||||
expect(screen.getByRole("button", { name: "480" }).getAttribute("aria-pressed")).toBe("true");
|
||||
expect(screen.getByRole("button", { name: "480 px" }).getAttribute("aria-pressed")).toBe(
|
||||
"true",
|
||||
);
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.formatVideo" }));
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.cut" }));
|
||||
await waitFor(() => expect(enqueueClip).toHaveBeenCalled());
|
||||
@@ -333,7 +339,21 @@ describe("ClipPanel GIF", () => {
|
||||
expect(range()).toBe("100-120");
|
||||
expect(note()).toBe("clip.gif.noPreview");
|
||||
// 20 s at 640: up to about 32 MB, past the server's 30.
|
||||
fireEvent.click(screen.getByRole("button", { name: "640" }));
|
||||
fireEvent.click(screen.getByRole("button", { name: "640 px" }));
|
||||
expect(note()).toBe("clip.gif.mayFail");
|
||||
});
|
||||
|
||||
it("says one size, not a range of one, when both ends read the same", () => {
|
||||
// 1 s at 480: 0.4–1.0 MB, both shown as 1.
|
||||
render(<Harness start={{ start: 100, end: 101 }} />);
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.formatGif" }));
|
||||
expect(screen.getByText("clip.gif.estimateOne")).toBeTruthy();
|
||||
expect(screen.queryByText("clip.gif.estimate")).toBeNull();
|
||||
// 10 s: a range.
|
||||
fireEvent.change(screen.getByRole("textbox", { name: "clip.out" }), {
|
||||
target: { value: "1:50" },
|
||||
});
|
||||
fireEvent.keyDown(screen.getByRole("textbox", { name: "clip.out" }), { key: "Enter" });
|
||||
expect(screen.getByText("clip.gif.estimate")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user