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.
94 lines
3.6 KiB
TypeScript
94 lines
3.6 KiB
TypeScript
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);
|
||
});
|
||
});
|