test(studio): a drag is measured against the box the preview shows

This commit is contained in:
Miguel Angel Simon Sierra
2026-10-25 23:02:05 -04:00
parent a058cde725
commit 49f5d7e020
3 changed files with 48 additions and 6 deletions
@@ -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";
@@ -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;
@@ -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);
});
});