diff --git a/internal/driver/ioscompanion/hierarchymap_test.go b/internal/driver/ioscompanion/hierarchymap_test.go index f87409d..e6268b5 100644 --- a/internal/driver/ioscompanion/hierarchymap_test.go +++ b/internal/driver/ioscompanion/hierarchymap_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "os" "path/filepath" + "strings" "testing" "github.com/priyanshujain/sanderling/internal/hierarchy" @@ -243,3 +244,17 @@ func TestHasUnresolvedValues(t *testing.T) { }) } } + +func TestMapHierarchySentinelValueMapsAsEmpty(t *testing.T) { + dump := `[{"type":"TextField","AXUniqueId":"F","AXLabel":"Email","AXValue":"Invalid","frame":{"x":0,"y":0,"width":10,"height":10},"enabled":true}]` + mapped, err := MapHierarchy([]byte(dump), 100, 100) + if err != nil { + t.Fatal(err) + } + if strings.Contains(string(mapped), "Invalid") { + t.Fatalf("sentinel leaked into mapped tree: %s", mapped) + } + if !strings.Contains(string(mapped), "hintText") { + t.Fatalf("empty editable field should map label to hintText: %s", mapped) + } +} diff --git a/internal/driver/ioscompanion/input_test.go b/internal/driver/ioscompanion/input_test.go index 02d4035..0f82055 100644 --- a/internal/driver/ioscompanion/input_test.go +++ b/internal/driver/ioscompanion/input_test.go @@ -384,3 +384,22 @@ func TestUsesPasteboardThreshold(t *testing.T) { } } } + +func TestPasteLandedMaskedSecureField(t *testing.T) { + cases := []struct { + name string + dump string + want bool + }{ + {name: "all bullets counts as landed", dump: `[{"type":"TextField","AXUniqueId":"PW","AXValue":"•••••"}]`, want: true}, + {name: "empty secure field not landed", dump: `[{"type":"TextField","AXUniqueId":"PW","AXValue":""}]`, want: false}, + {name: "mixed bullets and text not masked", dump: `[{"type":"TextField","AXUniqueId":"PW","AXValue":"••a"}]`, want: false}, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + if got := pasteLanded([]byte(c.dump), "PW", "secret9"); got != c.want { + t.Fatalf("got %v, want %v", got, c.want) + } + }) + } +}