Files
siftlode/frontend/src/lib/useScrollFade.dom.test.tsx
T
peter c9b8fe15a3 fix(ui): a scroller with no edge to fade carries no mask
iPad WebKit kept a scrolled container's mask stuck to its content: at the
bottom of a scrolled page the last strip, a table's pager, sat under a dark
band. With nothing to fade there is no mask; isolation keeps its layer.
2026-10-08 02:43:58 +02:00

50 lines
1.7 KiB
TypeScript

// @vitest-environment jsdom
import { describe, it, expect, beforeAll, afterEach } from "vitest";
import { render, cleanup, fireEvent } from "@testing-library/react";
import { useScrollFade } from "./useScrollFade";
beforeAll(() => {
class Stub {
observe() {}
unobserve() {}
disconnect() {}
}
globalThis.ResizeObserver ??= Stub as unknown as typeof ResizeObserver;
});
afterEach(cleanup);
function Scroller({ fadeTop = true }: { fadeTop?: boolean }) {
const fade = useScrollFade(20, fadeTop);
const { ref } = fade;
return <div data-testid="s" ref={ref} style={fade.style} />;
}
/** A scroller 100 px tall over 300 px of content, scrolled to `top`. */
function scrolledTo(el: HTMLElement, top: number) {
Object.defineProperties(el, {
clientHeight: { configurable: true, value: 100 },
scrollHeight: { configurable: true, value: 300 },
scrollTop: { configurable: true, value: top, writable: true },
});
fireEvent.scroll(el);
}
// iPad WebKit kept a scrolled container's mask stuck to the content: at the bottom of a scrolled page
// the last strip (a table's pager) sat under a dark band. With no edge to fade there is no mask.
describe("useScrollFade", () => {
it("masks the edge that is clipped", () => {
const { getByTestId } = render(<Scroller />);
const el = getByTestId("s");
scrolledTo(el, 0);
expect(el.style.maskImage).toContain("calc(100% - 20px)");
});
it("sets no mask once nothing fades, and keeps the layer it made", () => {
const { getByTestId } = render(<Scroller fadeTop={false} />);
const el = getByTestId("s");
scrolledTo(el, 200);
expect(el.style.maskImage).toBe("");
expect(el.style.isolation).toBe("isolate");
});
});