mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
test(runner): sibling taps reach the driver at their own coordinates
Drives 40 real draws from a spec that taps each card, through the picker, the serializer and DecodeAction, and asserts on the points the driver saw. Against the shared-selector bug all 40 landed on the first card. Claude-Session: https://claude.ai/code/session_01A5KmftdEJ49A9z5mF5ESrX
This commit is contained in:
1 parent
03af6abe72
commit
fd7bf17256
1 file changed
+65
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
@@ -2463,3 +2464,67 @@ func traceStepIndices(t *testing.T, directory string) []int {
|
||||
}
|
||||
return steps
|
||||
}
|
||||
|
||||
// siblingCardsSpec is the shape folio's Home screen authors: every account card
|
||||
// carries the same testTag, and each one is its own tap target.
|
||||
const siblingCardsSpec = `
|
||||
import { actions, always, extract, Tap } from "@sanderling/spec";
|
||||
const cards = extract(state => state.ax.findAll({ testTag: "AccountCard" }));
|
||||
globalThis.properties = {
|
||||
alwaysHolds: always(() => true),
|
||||
};
|
||||
globalThis.actions = actions(() => cards.current.map(card => Tap({ on: card })));
|
||||
`
|
||||
|
||||
const siblingCardsTree = `{
|
||||
"attributes": {"resource-id": "root", "bounds": "[0,0,100,300]"},
|
||||
"children": [
|
||||
{"attributes": {"testTag": "AccountCard", "text": "Alpha", "bounds": "[0,0,100,100]"}, "clickable": true, "children": []},
|
||||
{"attributes": {"testTag": "AccountCard", "text": "Beta", "bounds": "[0,100,100,200]"}, "clickable": true, "children": []},
|
||||
{"attributes": {"testTag": "AccountCard", "text": "Gamma", "bounds": "[0,200,100,300]"}, "clickable": true, "children": []}
|
||||
]
|
||||
}`
|
||||
|
||||
// TestRunner_SiblingTapsReachTheDriverAtTheirOwnCoordinates is the check the
|
||||
// whole selector-uniqueness rule exists for. Three cards sharing one testTag
|
||||
// each produce their own tap; if they reach the driver naming a selector all
|
||||
// three answer to, resolveCoordinates re-resolves every one of them onto the
|
||||
// first card and the fuzzer can never open the other two.
|
||||
func TestRunner_SiblingTapsReachTheDriverAtTheirOwnCoordinates(t *testing.T) {
|
||||
state := newHarnessWithSpec(t, siblingCardsSpec)
|
||||
tree, err := hierarchy.Parse(siblingCardsTree)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := state.verifier.PushSnapshot(verifier.SnapshotInput{Tree: tree}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for range 40 {
|
||||
action, err := state.verifier.NextAction()
|
||||
if err != nil {
|
||||
t.Fatalf("NextAction: %v", err)
|
||||
}
|
||||
if action.Kind != verifier.ActionKindTap {
|
||||
t.Fatalf("spec offers taps only, got %q", action.Kind)
|
||||
}
|
||||
mustDispatch(t, state.mock, action, tree)
|
||||
}
|
||||
|
||||
tapped := map[string]bool{}
|
||||
for _, dispatched := range state.mock.Actions() {
|
||||
if dispatched.Kind != mockdriver.ActionTap {
|
||||
t.Fatalf("expected coordinate taps only, got %v", dispatched)
|
||||
}
|
||||
tapped[fmt.Sprintf("%d,%d", dispatched.X, dispatched.Y)] = true
|
||||
}
|
||||
want := []string{"50,50", "50,150", "50,250"}
|
||||
for _, center := range want {
|
||||
if !tapped[center] {
|
||||
t.Errorf("no tap reached the driver at (%s); the driver saw %v", center, slices.Sorted(maps.Keys(tapped)))
|
||||
}
|
||||
}
|
||||
if len(tapped) != len(want) {
|
||||
t.Errorf("driver saw %d distinct tap points, want %d: %v", len(tapped), len(want), slices.Sorted(maps.Keys(tapped)))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user