From f02a65772b11662d2d4ad8dbbc87cd3b2a561673 Mon Sep 17 00:00:00 2001 From: PJ Date: Wed, 19 Aug 2026 10:37:03 +0530 Subject: [PATCH] fix(chrome): a hint target is not tapped by the placeholder attribute TapSelector is a third resolver, and it built [placeholder="..."] for hintText and placeholderValue too. Now that both matchers read the accessible-name ladder, that CSS names a field whose hint is its aria-label and whose placeholder happens to carry the value, which is an element neither matcher named. No CSS says what the ladder says, so both keys fall through to a match that reaches nothing and the step fails naming the selector, the way every other derived key in this file already does. A selector reaches here only where the dump resolved it to no coordinates at all. --- internal/driver/chrome/translate.go | 10 +++++++++- internal/driver/chrome/translate_test.go | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/internal/driver/chrome/translate.go b/internal/driver/chrome/translate.go index b8e2684..f89fcb3 100644 --- a/internal/driver/chrome/translate.go +++ b/internal/driver/chrome/translate.go @@ -64,7 +64,15 @@ func TranslateStringSelector(selector string) (string, bool, error) { return `:is([data-testid="` + escaped + `"], [id="` + escaped + `"])`, false, nil case "testID", "testid", "data-testid": return `[data-testid="` + cssEscape(value) + `"]`, false, nil - case "placeholder", "placeholderValue", "hintText": + case "placeholder": + // The attribute the markup writes. hintText and placeholderValue name + // the accessible-name ladder above it instead (fieldHint in driver.go), + // which no CSS says, so they fall through to a match that reaches + // nothing and the step fails by name. Building this selector for them + // tapped a field whose hint is its aria-label and whose placeholder + // happens to carry the value, which is an element neither matcher + // names: a selector reaches here only where the dump resolved it to no + // coordinates at all. return `[placeholder="` + cssEscape(value) + `"]`, false, nil default: if !attrNamePattern.MatchString(kind) { diff --git a/internal/driver/chrome/translate_test.go b/internal/driver/chrome/translate_test.go index a781db2..687499a 100644 --- a/internal/driver/chrome/translate_test.go +++ b/internal/driver/chrome/translate_test.go @@ -44,6 +44,13 @@ func TestTranslateStringSelector_KnownKeys(t *testing.T) { {"testTag:submit", `:is([data-testid="submit"], [id="submit"])`, false}, {"testID:submit", `[data-testid="submit"]`, false}, {"placeholder:Email", `[placeholder="Email"]`, false}, + // hintText and placeholderValue name the accessible-name ladder, which + // no CSS says, so they reach nothing here rather than the field whose + // placeholder happens to carry the value and whose hint is its + // aria-label. Both matchers name that field by its aria-label alone, so + // a tap by placeholder acts on an element nobody selected. + {"hintText:Email", `[hintText*="Email"]`, false}, + {"placeholderValue:Email", `[placeholderValue*="Email"]`, false}, } for _, testCase := range cases { got, isXPath, err := TranslateStringSelector(testCase.selector)