From f09dd69e76fdbfdf1ba049152f0d67cf07745e67 Mon Sep 17 00:00:00 2001 From: Merge Sim Date: Mon, 7 Sep 2026 15:02:49 -0700 Subject: [PATCH] test(sidebar): restore the clamping model for the scroll fixture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The element is pinned again with a getter and a no-op setter, which is what an unscrollable list does: the browser clamps the write and the element never moves. That immovability is the defect's defining property — it is why the virtualizer's remembered offset can drift away and never resync, since nothing fires a scroll event to correct it. Dropping it was my call and it was wrong. The proof that it was inert was correct about the current assertions and not a licence to remove it: a fixture whose element CAN move is the one least likely to catch the half of this defect that is still open, where the range start is still chosen from the drifted offset. The comment now says what the fixture models AND that the assertions do not yet observe it. The original mistake was claiming the browser-clamping story as the reason it was needed, rather than as the thing it represents. --- .../viewport/use-row-measurement.test.tsx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/renderer/src/components/sidebar/worktree-list/viewport/use-row-measurement.test.tsx b/src/renderer/src/components/sidebar/worktree-list/viewport/use-row-measurement.test.tsx index 13548b24123..5b253b576d2 100644 --- a/src/renderer/src/components/sidebar/worktree-list/viewport/use-row-measurement.test.tsx +++ b/src/renderer/src/components/sidebar/worktree-list/viewport/use-row-measurement.test.tsx @@ -49,9 +49,20 @@ const DRIFTED_OFFSET = 70 function createScrollElement(scrollTop: number): HTMLDivElement { const element = document.createElement('div') document.body.append(element) - // The scroll-anchor listener writes this once from a layout effect, after the render that - // computes the sticky index, so it cannot reach the assertion. - element.scrollTop = scrollTop + // Models the defect's defining property: the list is too short to scroll, so the browser clamps + // any write and the element never moves. That immovability is precisely why the virtualizer's + // remembered offset can drift away and never resync — nothing fires a scroll event to correct it. + // + // Honest about its reach: the current assertions do not observe this. The scroll-anchor listener + // writes scrollTop once from a layout effect, after the render that computes the sticky index, + // so a plain writable property passes these tests identically. It is kept because a fixture + // whose element CAN move is the one least likely to catch the half of this defect that is still + // open — the range start is still chosen from the drifted offset. + Object.defineProperty(element, 'scrollTop', { + configurable: true, + get: () => scrollTop, + set: () => undefined + }) return element }