Skip to content

Commit 560dc7a

Browse files
committed
test(conversation): run the momentum-cap test on a set clock
The test slept in real time and read the wall clock, so on a loaded machine a gap between two scrolls could outlast the gesture's quiet window and end the reader's gesture before the cap. It now moves performance.now itself, 100ms per scroll, and checks every scroll on each side of the two-second cap.
1 parent 6486bdb commit 560dc7a

1 file changed

Lines changed: 33 additions & 24 deletions

File tree

‎src/ui/conversation.test.tsx‎

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -643,32 +643,41 @@ describe("reader attribution and scroll listeners", () => {
643643
});
644644

645645
test("scrolls after the momentum cap are not the reader's", async () => {
646-
const { mounted, element, current } = mountPolicy("stick");
647-
giveGeometry(element, 10_000, 500);
648-
element.scrollTop = 9_500;
649-
const seen: { at: number; byReader: boolean }[] = [];
650-
current().subscribeScroll((snapshot) =>
651-
seen.push({ at: performance.now(), byReader: snapshot.byReader }),
652-
);
653-
await nextFrame();
654-
655-
flick(element, 9_000);
656-
const lifted = performance.now();
657-
let top = 9_000;
658-
while (performance.now() - lifted < 2_600) {
659-
await sleep(100);
660-
top -= 10;
661-
element.scrollTop = top;
662-
element.dispatchEvent(new Event("scroll"));
646+
// A clock the test moves, so a slow machine can't stretch the gap
647+
// between two scrolls past the gesture's quiet window.
648+
let now = 0;
649+
const originalNow = performance.now.bind(performance);
650+
performance.now = () => now;
651+
try {
652+
const { mounted, element, current } = mountPolicy("stick");
653+
giveGeometry(element, 10_000, 500);
654+
element.scrollTop = 9_500;
655+
const seen: { at: number; byReader: boolean }[] = [];
656+
current().subscribeScroll((snapshot) =>
657+
seen.push({ at: now, byReader: snapshot.byReader }),
658+
);
663659
await nextFrame();
660+
661+
flick(element, 9_000);
662+
const lifted = now;
663+
let top = 9_000;
664+
while (now - lifted < 2_600) {
665+
now += 100;
666+
top -= 10;
667+
element.scrollTop = top;
668+
element.dispatchEvent(new Event("scroll"));
669+
await nextFrame();
670+
}
671+
const early = seen.filter(({ at }) => at > lifted && at - lifted < 2_000);
672+
const late = seen.filter(({ at }) => at - lifted > 2_000);
673+
expect(early).toHaveLength(19);
674+
expect(early.every(({ byReader }) => byReader)).toBe(true);
675+
expect(late).toHaveLength(6);
676+
expect(late.every(({ byReader }) => !byReader)).toBe(true);
677+
mounted.unmount();
678+
} finally {
679+
performance.now = originalNow;
664680
}
665-
const early = seen.filter(({ at }) => at > lifted && at - lifted < 1_800);
666-
const late = seen.filter(({ at }) => at - lifted > 2_200);
667-
expect(early.length).toBeGreaterThan(10);
668-
expect(early.every(({ byReader }) => byReader)).toBe(true);
669-
expect(late.length).toBeGreaterThan(0);
670-
expect(late.every(({ byReader }) => !byReader)).toBe(true);
671-
mounted.unmount();
672681
});
673682

674683
test("a glide started inside the reader's window is not the reader's", async () => {

0 commit comments

Comments
 (0)