feat(downloads): make a GIF in the clip panel and the editor, and show a shared one as itself
The clip panel and the editor get a Video / GIF choice with the GIF's size, the size it is expected to come out at, and what that size means (no moving link preview over 15 MB, refused over 30 MB). A range longer than a GIF may be leaves Make unavailable with its reason. The editor makes one GIF per kept segment; Join says why it is unavailable instead of going dead. The share page shows a picture as itself with its Download, and a picture in a folder opens above the list.
This commit is contained in:
@@ -12,7 +12,10 @@ import type { ClipRange } from "../../lib/clipRange";
|
||||
|
||||
vi.mock("react-i18next", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("react-i18next")>();
|
||||
return { ...actual, useTranslation: () => ({ t: (k: string) => k }) };
|
||||
return {
|
||||
...actual,
|
||||
useTranslation: () => ({ t: (k: string) => k, i18n: { language: "en" } }),
|
||||
};
|
||||
});
|
||||
|
||||
const enqueueClip = vi.fn<(body: ClipRequest) => Promise<unknown>>();
|
||||
@@ -271,3 +274,66 @@ describe("ClipPanel", () => {
|
||||
expect(screen.getByTestId("crop").textContent).toBe("none");
|
||||
});
|
||||
});
|
||||
|
||||
describe("ClipPanel GIF", () => {
|
||||
it("makes a GIF at the size picked, and says a GIF is being made", async () => {
|
||||
const onClose = vi.fn();
|
||||
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" }));
|
||||
expect(enqueueClip).not.toHaveBeenCalled();
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.gif.make" }));
|
||||
await waitFor(() => expect(onClose).toHaveBeenCalled());
|
||||
expect(enqueueClip.mock.calls[0]![0]).toMatchObject({
|
||||
start_s: 100,
|
||||
end_s: 108,
|
||||
gif_side: 320,
|
||||
});
|
||||
expect(notify).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ level: "success", message: msg("clip.gif.queued") }),
|
||||
);
|
||||
});
|
||||
|
||||
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");
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.formatVideo" }));
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.cut" }));
|
||||
await waitFor(() => expect(enqueueClip).toHaveBeenCalled());
|
||||
expect(enqueueClip.mock.calls[0]![0]).not.toHaveProperty("gif_side");
|
||||
});
|
||||
|
||||
it("a range longer than a GIF may be leaves Make unavailable, with its reason", () => {
|
||||
render(<Harness start={{ start: 100, end: 131 }} />);
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.formatGif" }));
|
||||
const make = screen.getByRole("button", { name: "clip.gif.make" });
|
||||
expect(make.getAttribute("aria-disabled")).toBe("true");
|
||||
const note = document.getElementById(make.getAttribute("aria-describedby")!)!;
|
||||
expect(note.textContent).toBe("clip.gif.tooLong");
|
||||
fireEvent.click(make);
|
||||
expect(enqueueClip).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("says what the expected size means: fine, no moving preview, or past the cap", () => {
|
||||
render(<Harness start={{ start: 100, end: 110 }} />);
|
||||
fireEvent.click(screen.getByRole("button", { name: "clip.formatGif" }));
|
||||
const note = () =>
|
||||
document.getElementById(
|
||||
screen.getByRole("button", { name: "clip.gif.make" }).getAttribute("aria-describedby")!,
|
||||
)!.textContent;
|
||||
// 10 s at 480: about 4–10 MB.
|
||||
expect(note()).toBe("clip.gif.hint");
|
||||
// 20 s at 480: up to about 20 MB, past a link preview's 15.
|
||||
fireEvent.change(screen.getByRole("textbox", { name: "clip.out" }), {
|
||||
target: { value: "2:00" },
|
||||
});
|
||||
fireEvent.keyDown(screen.getByRole("textbox", { name: "clip.out" }), { key: "Enter" });
|
||||
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" }));
|
||||
expect(note()).toBe("clip.gif.mayFail");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user