test(e2e): start the board marquee off the board's padding cliff

`selects the full lane across a single large marquee scroll jump` failed the
changed-e2e-specs job with `Received: 0` — no card ever previewed. The CI
trace shows the drag started at (284, 195) and the failure screenshot shows a
native text selection with no marquee overlay, so the board never accepted
the pointerdown.

An element scan across that row shows why: the marquee may only start on
empty board space, and the usable strip is only x 280-298 — the board's own
left edge on one side, the first lane's cards on the other. `selectionBox.x +
4` aims 4px inside that strip, so a layout that rounds a few pixels
differently lands outside the board entirely, where the pointerdown never
reaches the handler and the browser text-selects instead.

Aim at the middle of the measured strip, assert the start point really is
empty board space before pressing, and assert the selection rect appears so a
rejected gesture fails immediately instead of surfacing 15s later as "0 cards
previewed".

Also carried over from the first attempt at this deflake: the lane scroll now
jumps until the virtualizer stops moving the bottom, because a measured card
is much taller than the row estimate and a fixed pass budget commits the
marquee short of the last cards; and the final assertion checks the badge's
text so a short selection reports its count.
This commit is contained in:
Brennan Benson
2026-08-03 19:37:23 -07:00
parent 194e1a8d4d
commit 2617d4640f
@@ -373,28 +373,85 @@ test.describe('Workspace board lane virtualization', () => {
throw new Error('Expected the marquee lane and selection surface to have bounding boxes')
}
await orcaPage.mouse.move(selectionBox.x + 4, box.y + 12)
// Why: the marquee may only start on empty board space — the board ignores a
// pointerdown on a card, and one that misses the board entirely never reaches
// its handler at all, so the browser text-selects instead and no marquee runs.
// The usable strip is the board's padding between its own left edge and the
// first lane's cards; starting a fixed 4px inside it hugs that outer edge and
// falls off it whenever layout rounds differently. Aim at the middle instead.
const firstCardBox = await laneCards.first().boundingBox()
if (!firstCardBox) {
throw new Error('Expected the first marquee card to have a bounding box')
}
const startX = Math.round((selectionBox.x + firstCardBox.x) / 2)
const startY = Math.round(box.y + 12)
const startTarget = await orcaPage.evaluate(
({ x, y }) => {
const element = document.elementFromPoint(x, y)
return {
onSurface: Boolean(element?.closest('[data-workspace-board-selection-surface]')),
onIgnoredTarget: Boolean(
element?.closest('[data-workspace-board-card-id], a, button, input, [role="button"]')
)
}
},
{ x: startX, y: startY }
)
expect(
startTarget,
`marquee start point (${startX}, ${startY}) must be empty board space; ` +
`selectionBox.x=${selectionBox.x} firstCard.x=${firstCardBox.x}`
).toEqual({ onSurface: true, onIgnoredTarget: false })
await orcaPage.mouse.move(startX, startY)
await orcaPage.mouse.down()
await orcaPage.mouse.move(box.x + box.width - 18, box.y + 80, { steps: 4 })
// Why: proves the board accepted the gesture. Without it a rejected
// pointerdown only shows up 15s later as "0 cards previewed", which reads as
// a virtualization bug rather than a marquee that never started.
await expect(orcaPage.locator('[data-workspace-board-selection-rect]')).toBeVisible()
await expect
.poll(() => lane.locator('[data-workspace-board-card-area-selected="true"]').count(), {
timeout: 15_000
})
.toBeGreaterThan(0)
await laneScroll.evaluate(async (element) => {
for (let pass = 0; pass < 4; pass++) {
// Why: a measured card is much taller than the lane's row estimate, so each
// jump to the bottom re-measures the window and grows the spacer past the
// scrollTop the jump just landed on. A fixed pass budget commits the marquee
// mid-growth on a loaded machine — short of the last cards — so jump until
// the virtualizer stops moving the bottom instead.
const laneScrollSettle = await laneScroll.evaluate(async (element) => {
let settledPasses = 0
let passes = 0
while (settledPasses < 2 && passes < 40) {
passes += 1
element.scrollTop = element.scrollHeight
element.dispatchEvent(new Event('scroll', { bubbles: true }))
await new Promise<void>((resolve) => {
requestAnimationFrame(() => requestAnimationFrame(() => resolve()))
})
const maxScrollTop = element.scrollHeight - element.clientHeight
settledPasses = element.scrollTop >= maxScrollTop - 1 ? settledPasses + 1 : 0
}
return {
passes,
scrollTop: element.scrollTop,
maxScrollTop: element.scrollHeight - element.clientHeight
}
})
expect(
laneScrollSettle.scrollTop,
`lane scroll never settled at its bottom: ${JSON.stringify(laneScrollSettle)}`
).toBeGreaterThanOrEqual(laneScrollSettle.maxScrollTop - 1)
await orcaPage.mouse.move(box.x + box.width - 18, box.y + box.height - 12)
await orcaPage.mouse.up()
await expect(
orcaPage.getByText(`${MARQUEE_WORKSPACE_COUNT} selected`, { exact: true })
).toBeVisible()
// Why: assert the badge's text, not its presence — a marquee that stopped
// short reports the count it did commit instead of a bare locator timeout.
await expect(orcaPage.getByText(/^\d+ selected$/)).toHaveText(
`${MARQUEE_WORKSPACE_COUNT} selected`
)
})
})