From c16cb88d384193d447fde345cc6c776714ae699e Mon Sep 17 00:00:00 2001 From: PJ Date: Wed, 19 Aug 2026 09:41:39 +0530 Subject: [PATCH] test(spec): pin text against the key beside it in either order object keys iterate in insertion order, so the order the author wrote them in decided what a compound selector meant. the innermost rule is pinned over the whole selector's matches: a row whose badge carries the class and the text both is dropped, one whose badge carries the text alone is kept, and a state key is anded before either. --- pkg/spec/test/web-runtime.test.ts | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/pkg/spec/test/web-runtime.test.ts b/pkg/spec/test/web-runtime.test.ts index f93a7e8..2bee099 100644 --- a/pkg/spec/test/web-runtime.test.ts +++ b/pkg/spec/test/web-runtime.test.ts @@ -871,6 +871,77 @@ test("selected selects the live property, not the markup attribute", () => { }); }); +// text written beside another key was DROPPED, so `{testID, text}` resolved to +// the testID alone and selected every row carrying it. internal/hierarchy ANDs +// the two, so the goja host answered with the one row the author named while +// this host answered with all of them: a find landed on a row nobody wrote, and +// a property over it passed having checked a different element. +function matchedIDs(selector: unknown): string[] { + const ax = __testing__.buildAx() as { findAll(selector: unknown): { id: string }[] }; + return ax.findAll(selector).map((element) => element.id); +} + +test("text is ANDed with the key beside it, in either order", () => { + const alice = fakeElement({ + tag: "div", x: 0, y: 0, width: 120, height: 20, id: "customer_row_a1", + testid: "customer-row", text: "Alice", + }); + const bob = fakeElement({ + tag: "div", x: 0, y: 20, width: 120, height: 20, id: "customer_row_b2", + testid: "customer-row", text: "Bob", + }); + withFakeDocument([alice, bob], () => { + assert.deepEqual(matchedIDs({ testID: "customer-row", text: "Alice" }), ["customer_row_a1"]); + assert.deepEqual(matchedIDs({ text: "Alice", testID: "customer-row" }), ["customer_row_a1"]); + assert.deepEqual(matchedIDs({ id: "customer_row_a1", text: "Alice" }), ["customer_row_a1"]); + assert.deepEqual(matchedIDs({ id: "customer_row_a1", text: "Bob" }), []); + assert.deepEqual(matchedIDs({ text: "Bob", id: "customer_row_a1" }), []); + }); +}); + +// The innermost rule holds over what the WHOLE selector matched, the way +// internal/hierarchy holds it: an ancestor whose only matching descendant a +// sibling key excludes was never a match to drop it by. Resolving text to its +// own innermost match first and filtering afterwards loses plain_row. +test("text keeps the innermost element the whole selector matched", () => { + const nested = fakeElement({ + tag: "div", x: 0, y: 0, width: 120, height: 20, id: "nested_row", + attrs: { class: "row" }, text: "Sent Sent", + children: [{ + tag: "span", x: 0, y: 0, width: 40, height: 20, id: "nested_badge", + attrs: { class: "row" }, text: "Sent", + }], + }); + const plain = fakeElement({ + tag: "div", x: 0, y: 20, width: 120, height: 20, id: "plain_row", + attrs: { class: "row" }, text: "Sent", + children: [{ + tag: "span", x: 0, y: 20, width: 40, height: 20, id: "plain_badge", text: "Sent", + }], + }); + withFakeDocument([nested, plain], () => { + assert.deepEqual(matchedIDs({ className: "row", text: "Sent" }), ["nested_badge", "plain_row"]); + }); +}); + +// A state key is answered against the live element rather than compiled into +// the query, and text has to be ANDed with it before the innermost rule runs: +// the innermost element carrying "January" is the option, and the select is the +// only element that is both. +test("text is ANDed with a state key before the innermost rule", () => { + const month = fakeElement({ + tag: "select", x: 0, y: 0, width: 120, height: 20, id: "month", clickable: true, + text: "January February", + children: [ + { tag: "option", x: 0, y: 0, width: 120, height: 20, id: "january", text: "January" }, + { tag: "option", x: 0, y: 20, width: 120, height: 20, id: "february", text: "February" }, + ], + }); + withFakeDocument([month], () => { + assert.deepEqual(matchedIDs({ text: "January", clickable: true }), ["month"]); + }); +}); + test("attrs carries every other attribute alongside tag and aria-label", () => { const attrs = attrsOf( domElement({ tag: "input", attributes: { id: "txn-note", placeholder: "What's this for?" } }),