feat(hierarchy): an element reports whether it masks what is typed into it

ios reads it off SecureTextField, which the companion already sent and
nothing read; web reads input[type=password]. Android cannot: the native
tree mapper drops the password attribute before the sidecar sees it, so
the fact is three-valued and null there rather than a false that would
read as "not secure".
This commit is contained in:
pj committed 2026-08-18 17:16:55 +05:30
1 parent 5f1f50c2fb
commit b1e95739ad
11 files changed
+186 -5

No files matched your search

+47
View File
@@ -235,6 +235,53 @@ func TestBoolFieldsFromNode(t *testing.T) {
}
}
// secure is the one state flag with three answers: a producer that reports
// nothing leaves the element unknown rather than known-not-secure, and a
// consumer deciding what a typed value may be written into a record reads the
// difference.
func TestSecureIsUnknownUntilAProducerReportsIt(t *testing.T) {
cases := []struct {
name string
node string
wantReported bool
wantSecure bool
}{
{"reported secure", `{"attributes": {"bounds": "[0,0,10,10]"}, "secure": true}`, true, true},
{"reported not secure", `{"attributes": {"bounds": "[0,0,10,10]"}, "secure": false}`, true, false},
{"never reported", `{"attributes": {"bounds": "[0,0,10,10]"}}`, false, false},
}
for _, testCase := range cases {
t.Run(testCase.name, func(t *testing.T) {
tree, err := Parse(testCase.node)
if err != nil {
t.Fatalf("Parse: %v", err)
}
element := tree.Elements[0]
if element.SecureReported() != testCase.wantReported {
t.Errorf("SecureReported = %v, want %v", element.SecureReported(), testCase.wantReported)
}
if element.Secure != testCase.wantSecure {
t.Errorf("Secure = %v, want %v", element.Secure, testCase.wantSecure)
}
})
}
}
// A selector reaches the fact by the same route every other boolean state does.
func TestSecureIsSelectable(t *testing.T) {
tree, err := Parse(`{"attributes": {"resource-id": "root", "bounds": "[0,0,10,10]"}, "children": [
{"attributes": {"resource-id": "pwd", "bounds": "[0,0,10,5]"}, "secure": true, "children": []},
{"attributes": {"resource-id": "email", "bounds": "[0,5,10,10]"}, "secure": false, "children": []}
]}`)
if err != nil {
t.Fatalf("Parse: %v", err)
}
element := tree.Find("secure:true")
if element == nil || element.ResourceID != "pwd" {
t.Errorf("secure:true resolved to %+v, want the pwd element", element)
}
}
func TestEditableDerivation(t *testing.T) {
cases := []struct {
name string