57 lines
2.4 KiB
TypeScript
57 lines
2.4 KiB
TypeScript
import { afterEach, expect, test } from "bun:test";
|
|
import { holdDecision, reducedMotion, viewTransition } from "../src/motion";
|
|
|
|
const g = globalThis as Record<string, unknown>;
|
|
afterEach(() => { delete g.document; delete g.window; });
|
|
|
|
function env({ reduce = false, vt = true, hidden = false } = {}) {
|
|
const calls: string[] = [];
|
|
g.window = { matchMedia: (q: string) => ({ matches: q.includes("prefers-reduced-motion: reduce") && reduce }) };
|
|
g.document = {
|
|
visibilityState: hidden ? "hidden" : "visible",
|
|
...(vt ? { startViewTransition: (cb: () => void) => { calls.push("vt"); cb(); return { finished: Promise.resolve() }; } } : {}),
|
|
};
|
|
return calls;
|
|
}
|
|
|
|
test("reducedMotion follows the media query and is false without a window", () => {
|
|
expect(reducedMotion()).toBe(false);
|
|
env({ reduce: true });
|
|
expect(reducedMotion()).toBe(true);
|
|
env({ reduce: false });
|
|
expect(reducedMotion()).toBe(false);
|
|
});
|
|
|
|
test("viewTransition runs the update inside startViewTransition when it can", () => {
|
|
const calls = env();
|
|
viewTransition(() => calls.push("update"));
|
|
expect(calls).toEqual(["vt", "update"]);
|
|
});
|
|
|
|
test("viewTransition runs the update directly with reduced motion, without support, or in a hidden tab", () => {
|
|
for (const o of [{ reduce: true }, { vt: false }, { hidden: true }]) {
|
|
const calls = env(o);
|
|
viewTransition(() => calls.push("update"));
|
|
expect([o, calls]).toEqual([o, ["update"]]);
|
|
}
|
|
delete g.document; delete g.window;
|
|
const plain: string[] = [];
|
|
viewTransition(() => plain.push("update"));
|
|
expect(plain).toEqual(["update"]);
|
|
});
|
|
|
|
test("holdDecision: show the first value, hold while loading, swap to a new key, replace the same key", () => {
|
|
type L = { id: string; course: string };
|
|
const key = (l: L) => l.id;
|
|
const sameCourse = (c: string) => (l: L) => l.course === c;
|
|
const a = { id: "a", course: "x" }, b = { id: "b", course: "x" }, a2 = { id: "a", course: "x" };
|
|
expect(holdDecision<L>(null, null, key)).toBe("show-next");
|
|
expect(holdDecision<L>(null, a, key)).toBe("show-next");
|
|
expect(holdDecision<L>(a, a, key)).toBe("show-next");
|
|
expect(holdDecision<L>(a, null, key, sameCourse("x"))).toBe("hold");
|
|
expect(holdDecision<L>(a, null, key, sameCourse("y"))).toBe("replace");
|
|
expect(holdDecision<L>(a, b, key)).toBe("swap");
|
|
expect(holdDecision<L>(a, a2, key)).toBe("replace");
|
|
expect(holdDecision<L>(a, b, key, sameCourse("y"))).toBe("replace");
|
|
});
|