mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 11:07:10 +00:00
fix(spec): carry the container on an authored scroll
serializeAction sent the container's own point as both endpoints, so an
authored Scroll({in, direction}) reached the driver as a drag from a point to
itself and did nothing, on the seeded arm. The wire now carries the selector
and leaves the drag to the runner, which sizes it from the container's bounds
and has always had tested support for it that nothing could produce.
No rng runs in the serializer, which lowers an already-drawn action, so the
draw stream does not move. Builtin scrolls compute both endpoints and their
bytes are unchanged.
Claude-Session: https://claude.ai/code/session_01A5KmftdEJ49A9z5mF5ESrX
This commit is contained in:
1 parent
70573a319e
commit
5ad2b39e6f
2 files changed
+69
-15
No files matched your search
@@ -29,6 +29,7 @@ export type SerializedAction =
|
|||||||
toX: number;
|
toX: number;
|
||||||
toY: number;
|
toY: number;
|
||||||
durationMillis: number;
|
durationMillis: number;
|
||||||
|
selector?: string;
|
||||||
}
|
}
|
||||||
| { kind: "PressKey"; key: string }
|
| { kind: "PressKey"; key: string }
|
||||||
| { kind: "Wait"; durationMillis: number };
|
| { kind: "Wait"; durationMillis: number };
|
||||||
@@ -90,20 +91,27 @@ export function serializeAction(action: ActionDescriptor | null): SerializedActi
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
case "Scroll": {
|
case "Scroll": {
|
||||||
const from = pointOf(action.from) ?? pointOf(action.in);
|
// The builtin generator pre-computes the whole gesture. An author names
|
||||||
if (!from) return null;
|
// the container instead and leaves the drag to the runner, which sizes it
|
||||||
// The builtin generator pre-computes `to`; an author Scroll without it
|
// from that container's bounds: sending the container's own point as both
|
||||||
// collapses to a zero-length gesture the runner re-derives from bounds.
|
// endpoints would be a drag from a point to itself, which the runner
|
||||||
const to = pointOf(action.to) ?? from;
|
// executes as written, and sending no container at all would scroll
|
||||||
return {
|
// whatever else is on screen.
|
||||||
|
const from = pointOf(action.from);
|
||||||
|
const to = pointOf(action.to);
|
||||||
|
const gesture =
|
||||||
|
from && to
|
||||||
|
? { fromX: from.x, fromY: from.y, toX: to.x, toY: to.y }
|
||||||
|
: { fromX: 0, fromY: 0, toX: 0, toY: 0 };
|
||||||
|
const out: SerializedAction = {
|
||||||
kind: "Scroll",
|
kind: "Scroll",
|
||||||
direction: action.direction,
|
direction: action.direction,
|
||||||
fromX: from.x,
|
...gesture,
|
||||||
fromY: from.y,
|
|
||||||
toX: to.x,
|
|
||||||
toY: to.y,
|
|
||||||
durationMillis: DEFAULT_SWIPE_DURATION,
|
durationMillis: DEFAULT_SWIPE_DURATION,
|
||||||
};
|
};
|
||||||
|
const container = pointOf(action.in);
|
||||||
|
if (container?.selector) out.selector = container.selector;
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
case "PressKey":
|
case "PressKey":
|
||||||
return { kind: "PressKey", key: action.key };
|
return { kind: "PressKey", key: action.key };
|
||||||
|
|||||||
@@ -75,14 +75,60 @@ test("Swipe defaults durationMillis to 250", () => {
|
|||||||
assert.equal(action.durationMillis, 250);
|
assert.equal(action.durationMillis, 250);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Scroll emits direction plus from/to point and duration", () => {
|
// An author Scroll names a container and leaves the drag to the runner, which
|
||||||
|
// sizes it from that container's bounds. Sending the container's own point as
|
||||||
|
// both endpoints would be a drag from a point to itself, which the runner takes
|
||||||
|
// at face value and dispatches as a zero-length gesture.
|
||||||
|
test("an author Scroll carries no endpoints", () => {
|
||||||
assert.deepEqual(serializeAction({ kind: "Scroll", direction: "down", in: POINT }), {
|
assert.deepEqual(serializeAction({ kind: "Scroll", direction: "down", in: POINT }), {
|
||||||
kind: "Scroll",
|
kind: "Scroll",
|
||||||
direction: "down",
|
direction: "down",
|
||||||
fromX: 12,
|
fromX: 0,
|
||||||
fromY: 34,
|
fromY: 0,
|
||||||
toX: 12,
|
toX: 0,
|
||||||
toY: 34,
|
toY: 0,
|
||||||
|
durationMillis: 250,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("an author Scroll names the container it scrolls", () => {
|
||||||
|
assert.deepEqual(serializeAction({ kind: "Scroll", direction: "down", in: "id:list" }), {
|
||||||
|
kind: "Scroll",
|
||||||
|
direction: "down",
|
||||||
|
fromX: 0,
|
||||||
|
fromY: 0,
|
||||||
|
toX: 0,
|
||||||
|
toY: 0,
|
||||||
|
durationMillis: 250,
|
||||||
|
selector: "id:list",
|
||||||
|
});
|
||||||
|
assert.deepEqual(
|
||||||
|
serializeAction({
|
||||||
|
kind: "Scroll",
|
||||||
|
direction: "down",
|
||||||
|
in: { x: 1, y: 2, selector: "id:list" },
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
kind: "Scroll",
|
||||||
|
direction: "down",
|
||||||
|
fromX: 0,
|
||||||
|
fromY: 0,
|
||||||
|
toX: 0,
|
||||||
|
toY: 0,
|
||||||
|
durationMillis: 250,
|
||||||
|
selector: "id:list",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("a Scroll with no container scrolls the screen rather than dropping", () => {
|
||||||
|
assert.deepEqual(serializeAction({ kind: "Scroll", direction: "up" }), {
|
||||||
|
kind: "Scroll",
|
||||||
|
direction: "up",
|
||||||
|
fromX: 0,
|
||||||
|
fromY: 0,
|
||||||
|
toX: 0,
|
||||||
|
toY: 0,
|
||||||
durationMillis: 250,
|
durationMillis: 250,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user