fix(spec): a secure selector names the password field on web

secure is derived from the field type, not written by the markup, so
matching it as a raw attribute reached nothing: the key is accepted, no
unknown-key error fires, and find answered undefined on web for the
field it answers with on ios. false is every editable field that is not
a password entry, since an element that is no field reports null and
answers to neither value.
This commit is contained in:
pj committed 2026-08-18 20:14:01 +05:30
1 parent 8414953135
commit b0895ef179
3 files changed
+49 -1

No files matched your search

+17
View File
@@ -119,8 +119,25 @@ const KNOWN_KEY_TO_CSS: Record<string, (value: string) => string> = {
placeholder: (v) => `[placeholder="${cssEscape(v)}"]`,
placeholderValue: (v) => `[placeholder="${cssEscape(v)}"]`,
hintText: (v) => `[placeholder="${cssEscape(v)}"]`,
secure: secureSelector,
};
// secure is derived from the field's type rather than written by the markup, so
// matching it as a raw attribute reaches nothing at all. Both producers of the
// fact, elementHandle below and the hierarchy dump in
// internal/driver/chrome/driver.go, read `type === "password"` off a field they
// call editable, so false is every editable field that is NOT a password entry
// rather than everything that is not one: an element that is no field reports
// null, as android reports null for everything, and answers to neither value.
function secureSelector(value: string): string {
if (value === "true") return `input[type="password"]`;
if (value !== "false") return ":not(*)";
const textInput = ["password", ...NON_TEXT_INPUT_TYPES]
.map((type) => `:not([type="${type}"])`)
.join("");
return `:is(input${textInput}, textarea, [contenteditable]:not([contenteditable="false"]))`;
}
// cssEscape delegates to the platform CSS.escape (per CSSOM spec). It produces
// output safe for both identifier and string contexts, since CSS string
// literals accept the same `\HEX ` and `\X` escape sequences as identifiers.