mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-03 03:27:10 +00:00
feat(hierarchy): testTag alias resolves to resource-id and accessibilityIdentifier
Compose's testTag surfaces as resource-id on Android and as
accessibilityIdentifier on iOS. Selectors written as
{ testTag: "Foo" } now match either, so Sanderling specs can use the
same tag on both platforms.
Also rounds out the iOS identifier aliases so resource-id /
identifier / accessibilityIdentifier all resolve to one another.
This commit is contained in:
1 parent
28909d954b
commit
d115cdfd97
2 files changed
+58
-4
No files matched your search
@@ -18,7 +18,9 @@
|
|||||||
//
|
//
|
||||||
// Cross-platform aliases are expanded automatically: "label" / "accessibilityLabel"
|
// Cross-platform aliases are expanded automatically: "label" / "accessibilityLabel"
|
||||||
// resolve to accessibilityText; "content-desc" also checks accessibilityText and
|
// resolve to accessibilityText; "content-desc" also checks accessibilityText and
|
||||||
// vice-versa; "identifier" / "accessibilityIdentifier" resolve to resource-id.
|
// vice-versa; "identifier" / "accessibilityIdentifier" / "testTag" resolve to
|
||||||
|
// resource-id (and to each other) so a Compose testTag matches whether the
|
||||||
|
// underlying platform exposes it as resource-id (Android) or accessibilityIdentifier (iOS).
|
||||||
package hierarchy
|
package hierarchy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -113,10 +115,12 @@ var attributeAliases = map[string][]string{
|
|||||||
// accessibilityText is the canonical key; also check content-desc for Android/web
|
// accessibilityText is the canonical key; also check content-desc for Android/web
|
||||||
"accessibilityText": {"content-desc"},
|
"accessibilityText": {"content-desc"},
|
||||||
// resource-id canonical key; also check identifier (iOS AXElement raw field)
|
// resource-id canonical key; also check identifier (iOS AXElement raw field)
|
||||||
"resource-id": {"identifier"},
|
"resource-id": {"identifier", "accessibilityIdentifier"},
|
||||||
// iOS identifier names
|
// iOS identifier names
|
||||||
"identifier": {"resource-id"},
|
"identifier": {"resource-id", "accessibilityIdentifier"},
|
||||||
"accessibilityIdentifier": {"resource-id"},
|
"accessibilityIdentifier": {"resource-id", "identifier"},
|
||||||
|
// Compose testTag surfaces as resource-id on Android, accessibilityIdentifier on iOS
|
||||||
|
"testTag": {"resource-id", "identifier", "accessibilityIdentifier"},
|
||||||
// iOS AXElement raw name for hintText
|
// iOS AXElement raw name for hintText
|
||||||
"placeholderValue": {"hintText"},
|
"placeholderValue": {"hintText"},
|
||||||
// iOS AXElement raw name for class
|
// iOS AXElement raw name for class
|
||||||
|
|||||||
@@ -464,6 +464,56 @@ func TestNodeFindScopedSearch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTestTagAliasMatchesResourceIDAndroid(t *testing.T) {
|
||||||
|
input := `{
|
||||||
|
"attributes": {"resource-id": "AccountCard", "bounds": "[0,0,100,100]"},
|
||||||
|
"children": []
|
||||||
|
}`
|
||||||
|
tree, _ := Parse(input)
|
||||||
|
sel := Selector{Filters: []AttrFilter{{Attr: "testTag", Value: "AccountCard"}}}
|
||||||
|
if len(searchSubtreeBySelector(tree.Root, sel)) == 0 {
|
||||||
|
t.Fatal("expected testTag selector to match resource-id on Android")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTestTagAliasMatchesAccessibilityIdentifierIOS(t *testing.T) {
|
||||||
|
input := `{
|
||||||
|
"attributes": {"accessibilityIdentifier": "AccountCard", "bounds": "[0,0,100,100]"},
|
||||||
|
"children": []
|
||||||
|
}`
|
||||||
|
tree, _ := Parse(input)
|
||||||
|
sel := Selector{Filters: []AttrFilter{{Attr: "testTag", Value: "AccountCard"}}}
|
||||||
|
matches := searchSubtreeBySelector(tree.Root, sel)
|
||||||
|
if len(matches) == 0 {
|
||||||
|
t.Fatal("expected testTag selector to match accessibilityIdentifier on iOS")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTestTagAliasMatchesIdentifierIOSRaw(t *testing.T) {
|
||||||
|
input := `{
|
||||||
|
"attributes": {"identifier": "AccountCard", "bounds": "[0,0,100,100]"},
|
||||||
|
"children": []
|
||||||
|
}`
|
||||||
|
tree, _ := Parse(input)
|
||||||
|
sel := Selector{Filters: []AttrFilter{{Attr: "testTag", Value: "AccountCard"}}}
|
||||||
|
matches := searchSubtreeBySelector(tree.Root, sel)
|
||||||
|
if len(matches) == 0 {
|
||||||
|
t.Fatal("expected testTag selector to match identifier on iOS raw AXElement")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourceIDFallsBackToAccessibilityIdentifier(t *testing.T) {
|
||||||
|
input := `{
|
||||||
|
"attributes": {"accessibilityIdentifier": "MyButton", "bounds": "[0,0,100,100]"},
|
||||||
|
"children": []
|
||||||
|
}`
|
||||||
|
tree, _ := Parse(input)
|
||||||
|
sel := Selector{Filters: []AttrFilter{{Attr: "resource-id", Value: "MyButton"}}}
|
||||||
|
if len(searchSubtreeBySelector(tree.Root, sel)) == 0 {
|
||||||
|
t.Fatal("expected resource-id selector to fall back to accessibilityIdentifier")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestNodeFindDoesNotReturnSiblings(t *testing.T) {
|
func TestNodeFindDoesNotReturnSiblings(t *testing.T) {
|
||||||
tree, _ := Parse(pathDump)
|
tree, _ := Parse(pathDump)
|
||||||
a2Node := tree.FindNode("id:A2")
|
a2Node := tree.FindNode("id:A2")
|
||||||
|
|||||||
Reference in new issue
Block a user