mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
feat(verifier): add doubleTaps random-target generator
This commit is contained in:
1 parent
177b571b0a
commit
801f09d455
3 files changed
+54
-6
No files matched your search
@@ -62,11 +62,12 @@ const (
|
|||||||
|
|
||||||
internalKindActions = "actions"
|
internalKindActions = "actions"
|
||||||
internalKindWeighted = "weighted"
|
internalKindWeighted = "weighted"
|
||||||
internalKindBuiltinTaps = "taps"
|
internalKindBuiltinTaps = "taps"
|
||||||
internalKindBuiltinTyping = "typing"
|
internalKindBuiltinDoubleTaps = "doubleTaps"
|
||||||
internalKindBuiltinSwipes = "swipes"
|
internalKindBuiltinTyping = "typing"
|
||||||
internalKindBuiltinWaitOnce = "waitOnce"
|
internalKindBuiltinSwipes = "swipes"
|
||||||
internalKindBuiltinPressKey = "pressKey"
|
internalKindBuiltinWaitOnce = "waitOnce"
|
||||||
|
internalKindBuiltinPressKey = "pressKey"
|
||||||
)
|
)
|
||||||
|
|
||||||
// installRuntimeBindings exposes globalThis.__sanderling__ to the loaded spec.
|
// installRuntimeBindings exposes globalThis.__sanderling__ to the loaded spec.
|
||||||
@@ -118,6 +119,9 @@ func (v *Verifier) installRuntimeBindings() error {
|
|||||||
if err := sanderling.Set("taps", v.builtinGenerator(internalKindBuiltinTaps)); err != nil {
|
if err := sanderling.Set("taps", v.builtinGenerator(internalKindBuiltinTaps)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := sanderling.Set("doubleTaps", v.builtinGenerator(internalKindBuiltinDoubleTaps)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := sanderling.Set("typing", v.builtinGenerator(internalKindBuiltinTyping)); err != nil {
|
if err := sanderling.Set("typing", v.builtinGenerator(internalKindBuiltinTyping)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,6 +282,36 @@ func TestNextAction_NoSetupRegistered(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestDoubleTapsBuiltin_TargetsClickable verifies the doubleTaps builtin emits
|
||||||
|
// a DoubleTap action targeting a clickable, enabled element's center.
|
||||||
|
func TestDoubleTapsBuiltin_TargetsClickable(t *testing.T) {
|
||||||
|
const treeJSON = `{
|
||||||
|
"attributes": {"resource-id": "root", "bounds": "[0,0,100,100]"},
|
||||||
|
"children": [
|
||||||
|
{"attributes": {"testTag": "SubmitButton", "bounds": "[0,40,100,80]"}, "clickable": true, "enabled": true, "children": []}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
verifier := newVerifier(t)
|
||||||
|
mustLoad(t, verifier, `globalThis.actions = __sanderling__.doubleTaps;`)
|
||||||
|
tree, err := hierarchy.Parse(treeJSON)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := verifier.PushSnapshot(SnapshotInput{Snapshots: Snapshots{}, Tree: tree}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
action, err := verifier.NextAction()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if action.Kind != ActionKindDoubleTap {
|
||||||
|
t.Fatalf("kind = %v, want DoubleTap", action.Kind)
|
||||||
|
}
|
||||||
|
if action.X != 50 || action.Y != 60 {
|
||||||
|
t.Errorf("coords = (%d,%d), want (50,60) at SubmitButton center", action.X, action.Y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDoubleTap_RoundTrip(t *testing.T) {
|
func TestDoubleTap_RoundTrip(t *testing.T) {
|
||||||
verifier := newVerifier(t)
|
verifier := newVerifier(t)
|
||||||
mustLoad(t, verifier, `
|
mustLoad(t, verifier, `
|
||||||
|
|||||||
@@ -452,6 +452,8 @@ func (v *Verifier) resolveGenerator(generator goja.Value) (Action, error) {
|
|||||||
return v.resolveGenerator(picked)
|
return v.resolveGenerator(picked)
|
||||||
case internalKindBuiltinTaps:
|
case internalKindBuiltinTaps:
|
||||||
return v.generateRandomTap()
|
return v.generateRandomTap()
|
||||||
|
case internalKindBuiltinDoubleTaps:
|
||||||
|
return v.generateRandomDoubleTap()
|
||||||
case internalKindBuiltinTyping:
|
case internalKindBuiltinTyping:
|
||||||
return v.generateRandomInput()
|
return v.generateRandomInput()
|
||||||
case internalKindBuiltinSwipes:
|
case internalKindBuiltinSwipes:
|
||||||
@@ -468,6 +470,18 @@ func (v *Verifier) resolveGenerator(generator goja.Value) (Action, error) {
|
|||||||
// generateRandomTap picks a visible, tappable element from the last
|
// generateRandomTap picks a visible, tappable element from the last
|
||||||
// hierarchy snapshot and returns a Tap action targeting its center.
|
// hierarchy snapshot and returns a Tap action targeting its center.
|
||||||
func (v *Verifier) generateRandomTap() (Action, error) {
|
func (v *Verifier) generateRandomTap() (Action, error) {
|
||||||
|
return v.generateRandomTapKind(ActionKindTap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateRandomDoubleTap is the DoubleTap counterpart of generateRandomTap.
|
||||||
|
// Real user gestures include double-tap (image zoom, like-to-favorite,
|
||||||
|
// play/pause); a fuzzer that never emits one cannot exercise either those
|
||||||
|
// features or the sub-100ms race windows that single-step Tap cadence misses.
|
||||||
|
func (v *Verifier) generateRandomDoubleTap() (Action, error) {
|
||||||
|
return v.generateRandomTapKind(ActionKindDoubleTap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Verifier) generateRandomTapKind(kind ActionKind) (Action, error) {
|
||||||
if v.lastTree == nil {
|
if v.lastTree == nil {
|
||||||
return Action{}, ErrNoAction
|
return Action{}, ErrNoAction
|
||||||
}
|
}
|
||||||
@@ -486,7 +500,7 @@ func (v *Verifier) generateRandomTap() (Action, error) {
|
|||||||
}
|
}
|
||||||
picked := candidates[v.rng.IntN(len(candidates))]
|
picked := candidates[v.rng.IntN(len(candidates))]
|
||||||
x, y := picked.Bounds.Center()
|
x, y := picked.Bounds.Center()
|
||||||
return Action{Kind: ActionKindTap, X: x, Y: y}, nil
|
return Action{Kind: kind, X: x, Y: y}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// inputCorpus is the edge-case string pool the typing builtin draws from to
|
// inputCorpus is the edge-case string pool the typing builtin draws from to
|
||||||
|
|||||||
Reference in new issue
Block a user