diff --git a/packages/studio/tests/e2e/edit-accuracy/case.mjs b/packages/studio/tests/e2e/edit-accuracy/case.mjs index 0b7bbd297c..0f91e62350 100644 --- a/packages/studio/tests/e2e/edit-accuracy/case.mjs +++ b/packages/studio/tests/e2e/edit-accuracy/case.mjs @@ -678,13 +678,14 @@ async function waitingQuad(page, map) { return quad; } -export async function sample(ctx, gesture, point, pointerScreen) { +/** The box as the preview shows it: the waiting marker's quad while a press waits for its replay, else the element. */ +export async function measureShown(ctx, gesture, read = measure, quadOf = contentQuad) { for (;;) { const waiting = await ctx.page.$("[data-dom-edit-press-waiting]"); try { - const m = await measure(ctx); + const m = await read(ctx); if (gesture === "crop") m.outline = await cropOutline(ctx, m.map); - const quad = waiting && (await contentQuad(waiting)).map(m.map.toComp); + const quad = waiting && (await quadOf(waiting)).map(m.map.toComp); // Replay removes the marker before moving the element. Do not combine a pre-replay // element read with a post-replay marker read into a position nobody displayed. if ( @@ -692,14 +693,18 @@ export async function sample(ctx, gesture, point, pointerScreen) { !(await waiting.evaluate((e) => e.hasAttribute("data-dom-edit-press-waiting"))) ) continue; - const shown = quad ? { ...m, quad, visible: quad } : m; - return { m: shown, actual: m.visible, p: point(shown), c: m.map.toComp(pointerScreen) }; + return { m: quad ? { ...m, quad, visible: quad } : m, actual: m.visible }; } finally { await waiting?.dispose(); } } } +export async function sample(ctx, gesture, point, pointerScreen) { + const { m, actual } = await measureShown(ctx, gesture); + return { m, actual, p: point(m), c: m.map.toComp(pointerScreen) }; +} + const TRACE_CATEGORIES = ["toplevel", "devtools.timeline", "blink.user_timing"]; const TRACE_MARK = "edit-bench-end"; diff --git a/packages/studio/tests/e2e/edit-accuracy/sequences.mjs b/packages/studio/tests/e2e/edit-accuracy/sequences.mjs index 9fa6288a17..1c266c9c71 100644 --- a/packages/studio/tests/e2e/edit-accuracy/sequences.mjs +++ b/packages/studio/tests/e2e/edit-accuracy/sequences.mjs @@ -10,6 +10,7 @@ import { chord, controlDrag, measure, + measureShown, nextFrame, openStudio, pointerGesture, @@ -273,7 +274,7 @@ async function driveStep(ctx, step, state) { const name = step.element ?? "A"; const c = ctx[name]; // In flight: pressed where the last drag let go, without reading the preview first. - let pre = step.inFlight ? state.last.lastMeasure : await measure(c); + let pre = step.inFlight ? state.last.lastMeasure : (await measureShown(c)).m; if (name !== state.selected) { await selectTarget(c, pre); state.selected = name; diff --git a/packages/studio/tests/e2e/edit-accuracy/settle.test.mjs b/packages/studio/tests/e2e/edit-accuracy/settle.test.mjs index c13b7f4ca4..ee2fa64794 100644 --- a/packages/studio/tests/e2e/edit-accuracy/settle.test.mjs +++ b/packages/studio/tests/e2e/edit-accuracy/settle.test.mjs @@ -6,6 +6,7 @@ import { STILL_FRAMES, backgroundRequest, heldStill, + measureShown, networkBusy, seekBound, swapPending, @@ -178,3 +179,38 @@ describe("the size auto-record keys hold", () => { expect(heldSize(new Map(), 1)).toBeUndefined(); }); }); + +describe("the box a press is measured against", () => { + const quad = (x) => [ + [x, 0], + [x + 1, 0], + [x + 1, 1], + [x, 1], + ]; + const marker = (answers) => ({ + evaluate: async () => answers.shift() ?? false, + dispose: async () => {}, + }); + const read = async () => ({ map: { toComp: (p) => p }, visible: quad(0) }); + const page = (markers) => ({ $: async () => markers.shift() ?? null }); + + it("reads the waiting marker while a press waits for its replay, not the element under it", async () => { + const shown = await measureShown({ page: page([marker([true])]) }, "move", read, async () => + quad(260), + ); + expect(shown.m.visible[0][0]).toBe(260); + expect(shown.actual[0][0]).toBe(0); + }); + + it("reads the element when nothing waits", async () => { + const shown = await measureShown({ page: page([]) }, "move", read, async () => quad(260)); + expect(shown.m.visible[0][0]).toBe(0); + }); + + it("reads again when the replay took the marker away between the two reads", async () => { + const shown = await measureShown({ page: page([marker([false])]) }, "move", read, async () => + quad(260), + ); + expect(shown.m.visible[0][0]).toBe(0); + }); +});