Files
siftlode/frontend/src/lib/gif.test.ts
T
peter fe6af1445f fix(downloads): GIF review round 2 — cap as sent, shown length, retry, Join reason
The panels judge a GIF's length in whole milliseconds between the ends as sent, the server's own rule, and a refused length reads rounded up. A shared picture says it failed only once its retry failed too. Join's reason shows on a key's focus; the editor's failure toasts name GIFs. The edit route's cap is test-held, and DESIGN.md records the GIF UI.
2026-11-13 00:19:53 +01:00

94 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from "vitest";
import {
estimateGif,
gifEstimateText,
GIF_MAX_BYTES,
GIF_PREVIEW_MAX_BYTES,
gifShownLength,
gifVerdict,
} from "./gif";
import { formatTimecode } from "./timecode";
const MB = 1024 * 1024;
describe("estimateGif", () => {
it("gives the measured range for a 16:9 picture", () => {
const e = estimateGif(30, 480, 16 / 9);
expect(e.lo / MB).toBeCloseTo(12, 5);
expect(e.hi / MB).toBeCloseTo(30, 5);
});
it("grows with the length and the size", () => {
expect(estimateGif(20, 480, 16 / 9).hi).toBeGreaterThan(estimateGif(10, 480, 16 / 9).hi);
expect(estimateGif(10, 640, 16 / 9).hi).toBeGreaterThan(estimateGif(10, 480, 16 / 9).hi);
});
it("counts the pixels of the shape: a square holds more than 16:9, a tall one as many", () => {
const wide = estimateGif(10, 480, 16 / 9).hi;
expect(estimateGif(10, 480, 1).hi).toBeCloseTo(wide * (16 / 9), 3);
expect(estimateGif(10, 480, 9 / 16).hi).toBeCloseTo(wide, 3);
});
it("falls back to 16:9 for a shape it cannot read", () => {
expect(estimateGif(10, 480, 0).hi).toBe(estimateGif(10, 480, 16 / 9).hi);
expect(estimateGif(10, 480, Number.NaN).hi).toBe(estimateGif(10, 480, 16 / 9).hi);
});
});
describe("gifEstimateText", () => {
it("says whether both ends read the same, so a panel says one size", () => {
expect(gifEstimateText(estimateGif(1, 480, 16 / 9), "en")).toEqual({
lo: "1",
hi: "1",
single: true,
});
expect(gifEstimateText(estimateGif(10, 480, 16 / 9), "en")).toEqual({
lo: "4",
hi: "10",
single: false,
});
});
});
describe("gifVerdict", () => {
it("refuses past the length cap, whatever the size", () => {
expect(gifVerdict(0, 30.2, { hi: 1 })).toBe("too_long");
expect(gifVerdict(0, 30, { hi: 1 })).toBe("ok");
});
it("judges the length the server judges: whole milliseconds between the ends as sent", () => {
// A float difference a hair over 30 s is exactly 30 s once the ends are sent.
expect(60.529 - 30.529).toBeGreaterThan(30);
expect(gifVerdict(30.529, 60.529, { hi: 1 })).toBe("ok");
expect(gifVerdict(0, 30.001, { hi: 1 })).toBe("too_long");
// Each end is sent rounded on its own: 10.0004–40.0008 goes as 10–40.001, 30001 ms, refused…
expect(gifVerdict(10.0004, 40.0008, { hi: 1 })).toBe("too_long");
// …and 10.0006–40.0012 as 10.001–40.001, exactly 30 s, made.
expect(gifVerdict(10.0006, 40.0012, { hi: 1 })).toBe("ok");
});
it("warns past the server's cap, then past the link preview's", () => {
expect(gifVerdict(0, 10, { hi: GIF_MAX_BYTES + 0.6 * MB })).toBe("may_fail");
expect(gifVerdict(0, 10, { hi: GIF_MAX_BYTES })).toBe("no_preview");
expect(gifVerdict(0, 10, { hi: GIF_PREVIEW_MAX_BYTES + 0.6 * MB })).toBe("no_preview");
expect(gifVerdict(0, 10, { hi: GIF_PREVIEW_MAX_BYTES })).toBe("ok");
});
it("judges the size the reader is shown: a high end shown as 30 MB is not past 30 MB", () => {
// 30 s at 480 lands a hair over 30 MiB, and reads "about 12–30 MB".
const hi = GIF_MAX_BYTES + 0.4 * MB;
expect(gifEstimateText({ lo: 12 * MB, hi }, "en").hi).toBe("30");
expect(gifVerdict(0, 30, { hi })).toBe("no_preview");
expect(gifVerdict(0, 10, { hi: GIF_PREVIEW_MAX_BYTES + 0.4 * MB })).toBe("ok");
});
});
describe("gifShownLength", () => {
it("never shows a refused range as one the cap allows", () => {
expect(formatTimecode(gifShownLength(0, 30.03))).toBe("0:30.1");
expect(formatTimecode(gifShownLength(0, 30.001))).toBe("0:30.1");
expect(gifShownLength(30.529, 60.529)).toBe(30);
expect(gifShownLength(0, 12.34)).toBe(12.34);
});
});