mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
fix(web): resolve testTag through data-testid or id
Compose Multiplatform emits its testTag into the element id, which the native table already accepts via the resource-id alias. The two web selector tables were the only place that rejected it. Claude-Session: https://claude.ai/code/session_01Fj4wJUikdABuMQEETwW55J
This commit is contained in:
1 parent
be2fbadc9d
commit
d25b56379a
4 files changed
+31
-3
No files matched your search
@@ -42,7 +42,13 @@ func TranslateStringSelector(selector string) (string, bool, error) {
|
|||||||
return `[aria-label="` + cssEscape(value) + `"]`, false, nil
|
return `[aria-label="` + cssEscape(value) + `"]`, false, nil
|
||||||
case "descPrefix":
|
case "descPrefix":
|
||||||
return `[aria-label^="` + cssEscape(value) + `"]`, false, nil
|
return `[aria-label^="` + cssEscape(value) + `"]`, false, nil
|
||||||
case "testTag", "testID", "testid", "data-testid":
|
case "testTag":
|
||||||
|
// Mirrors the in-page table and the native resource-id alias: a
|
||||||
|
// testTag reaches the DOM as data-testid or as an id, depending on
|
||||||
|
// the toolkit. `:is()` keeps this one compound selector.
|
||||||
|
escaped := cssEscape(value)
|
||||||
|
return `:is([data-testid="` + escaped + `"], [id="` + escaped + `"])`, false, nil
|
||||||
|
case "testID", "testid", "data-testid":
|
||||||
return `[data-testid="` + cssEscape(value) + `"]`, false, nil
|
return `[data-testid="` + cssEscape(value) + `"]`, false, nil
|
||||||
case "placeholder", "placeholderValue", "hintText":
|
case "placeholder", "placeholderValue", "hintText":
|
||||||
return `[placeholder="` + cssEscape(value) + `"]`, false, nil
|
return `[placeholder="` + cssEscape(value) + `"]`, false, nil
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func TestTranslateStringSelector_KnownKeys(t *testing.T) {
|
|||||||
{"accessibilityLabel:logout", `[aria-label="logout"]`, false},
|
{"accessibilityLabel:logout", `[aria-label="logout"]`, false},
|
||||||
{"aria-label:Sign in", `[aria-label="Sign in"]`, false},
|
{"aria-label:Sign in", `[aria-label="Sign in"]`, false},
|
||||||
{"descPrefix:account:", `[aria-label^="account:"]`, false},
|
{"descPrefix:account:", `[aria-label^="account:"]`, false},
|
||||||
{"testTag:submit", `[data-testid="submit"]`, false},
|
{"testTag:submit", `:is([data-testid="submit"], [id="submit"])`, false},
|
||||||
{"testID:submit", `[data-testid="submit"]`, false},
|
{"testID:submit", `[data-testid="submit"]`, false},
|
||||||
{"placeholder:Email", `[placeholder="Email"]`, false},
|
{"placeholder:Email", `[placeholder="Email"]`, false},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,12 @@ function noopFormula(): unknown {
|
|||||||
const KNOWN_KEY_TO_CSS: Record<string, (value: string) => string> = {
|
const KNOWN_KEY_TO_CSS: Record<string, (value: string) => string> = {
|
||||||
id: (v) => `[id="${cssEscape(v)}"]`,
|
id: (v) => `[id="${cssEscape(v)}"]`,
|
||||||
"resource-id": (v) => `[id="${cssEscape(v)}"]`,
|
"resource-id": (v) => `[id="${cssEscape(v)}"]`,
|
||||||
testTag: (v) => `[data-testid="${cssEscape(v)}"]`,
|
// The native table aliases testTag onto resource-id, which the host DOM walk
|
||||||
|
// fills from el.id, so the native path already accepts a testTag emitted as
|
||||||
|
// an id (what Compose Multiplatform does on web). Accept both here so the
|
||||||
|
// tables agree. `:is()` keeps this one compound, since a multi-key selector
|
||||||
|
// concatenates the parts.
|
||||||
|
testTag: (v) => `:is([data-testid="${cssEscape(v)}"], [id="${cssEscape(v)}"])`,
|
||||||
testID: (v) => `[data-testid="${cssEscape(v)}"]`,
|
testID: (v) => `[data-testid="${cssEscape(v)}"]`,
|
||||||
"data-testid": (v) => `[data-testid="${cssEscape(v)}"]`,
|
"data-testid": (v) => `[data-testid="${cssEscape(v)}"]`,
|
||||||
className: (v) => `[class~="${cssEscape(v)}"]`,
|
className: (v) => `[class~="${cssEscape(v)}"]`,
|
||||||
|
|||||||
@@ -310,6 +310,23 @@ test("selectorFromObject maps known keys to their canonical attribute", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Compose Multiplatform emits its testTag into `id`, which the native table
|
||||||
|
// already accepts via the resource-id alias. The web table must not be the one
|
||||||
|
// place that rejects it.
|
||||||
|
test("selectorFromObject resolves testTag through data-testid or id", () => {
|
||||||
|
assert.deepEqual(selectorFromObject({ testTag: "LoginSubmit" }), {
|
||||||
|
css: `:is([data-testid="LoginSubmit"], [id="LoginSubmit"])`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Multi-key selectors concatenate their parts into one compound, so the
|
||||||
|
// two-attribute testTag match has to stay a single compound piece.
|
||||||
|
test("selectorFromObject composes testTag with a second key", () => {
|
||||||
|
assert.deepEqual(selectorFromObject({ testTag: "Row", "aria-label": "first" }), {
|
||||||
|
css: `:is([data-testid="Row"], [id="Row"])[aria-label="first"]`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test("selectorFromObject falls back to a literal attribute for unknown keys", () => {
|
test("selectorFromObject falls back to a literal attribute for unknown keys", () => {
|
||||||
assert.deepEqual(selectorFromObject({ "data-foo": "bar" }), {
|
assert.deepEqual(selectorFromObject({ "data-foo": "bar" }), {
|
||||||
css: `[data-foo="bar"]`,
|
css: `[data-foo="bar"]`,
|
||||||
|
|||||||
Reference in new issue
Block a user