mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
feat(spec): add keyedBy(element, tags) identity helper
Joins element.find({testTag: tag})?.text per tag with U+001F as the
delimiter so user-visible text can never collide with the separator.
Returns empty string for an undefined element.
This commit is contained in:
1 parent
4f8cb43bff
commit
6b50f2dbeb
3 files changed
+56
-2
No files matched your search
+13
-1
@@ -1,5 +1,17 @@
|
||||
import type { Extracted, State } from "./types.ts";
|
||||
import type { AccessibilityElement, Extracted, State } from "./types.ts";
|
||||
|
||||
export function extract<T>(getter: (state: State) => T): Extracted<T> {
|
||||
return globalThis.__sanderling__.extract(getter);
|
||||
}
|
||||
|
||||
const KEY_DELIMITER = "\x1f";
|
||||
|
||||
export function keyedBy(
|
||||
element: AccessibilityElement | undefined,
|
||||
tags: readonly string[],
|
||||
): string {
|
||||
if (!element) return "";
|
||||
return tags
|
||||
.map(tag => element.find({ testTag: tag })?.text ?? "")
|
||||
.join(KEY_DELIMITER);
|
||||
}
|
||||
@@ -23,7 +23,7 @@ export type {
|
||||
WeightedEntry,
|
||||
} from "./types.ts";
|
||||
|
||||
export { extract } from "./extract.ts";
|
||||
export { extract, keyedBy } from "./extract.ts";
|
||||
export { always, eventually, next, now } from "./ltl.ts";
|
||||
export {
|
||||
InputText,
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
eventually,
|
||||
extract,
|
||||
from,
|
||||
keyedBy,
|
||||
next,
|
||||
now,
|
||||
pressKey,
|
||||
@@ -281,6 +282,47 @@ test("from forwards items to the runtime", () => {
|
||||
assert.equal(sampler.generate(), "a");
|
||||
});
|
||||
|
||||
function elementWithChildren(
|
||||
cells: Record<string, string>,
|
||||
): AccessibilityElement {
|
||||
return {
|
||||
find: selector => {
|
||||
if (typeof selector === "string" || Array.isArray(selector)) return undefined;
|
||||
const tag = (selector as Record<string, string>).testTag;
|
||||
if (!tag) return undefined;
|
||||
const text = cells[tag];
|
||||
if (text === undefined) return undefined;
|
||||
return { text, find: () => undefined, findAll: () => [] };
|
||||
},
|
||||
findAll: () => [],
|
||||
};
|
||||
}
|
||||
|
||||
test("keyedBy joins testTag-resolved texts with a stable delimiter", () => {
|
||||
installFakeRuntime();
|
||||
const row = elementWithChildren({
|
||||
TxnDate: "2026-04-26",
|
||||
TxnNote: "Coffee",
|
||||
TxnAmount: "$5.00",
|
||||
});
|
||||
const key = keyedBy(row, ["TxnDate", "TxnNote", "TxnAmount"]);
|
||||
assert.equal(key, "2026-04-26\x1fCoffee\x1f$5.00");
|
||||
});
|
||||
|
||||
test("keyedBy returns empty string for an undefined element", () => {
|
||||
installFakeRuntime();
|
||||
assert.equal(keyedBy(undefined, ["TxnDate"]), "");
|
||||
});
|
||||
|
||||
test("keyedBy substitutes empty strings for missing children", () => {
|
||||
installFakeRuntime();
|
||||
const row = elementWithChildren({ TxnDate: "2026-04-26" });
|
||||
assert.equal(
|
||||
keyedBy(row, ["TxnDate", "TxnNote", "TxnAmount"]),
|
||||
"2026-04-26\x1f\x1f",
|
||||
);
|
||||
});
|
||||
|
||||
test("default generators proxy through to the runtime", () => {
|
||||
installFakeRuntime();
|
||||
assert.equal(taps.__sanderlingActionGenerator, true);
|
||||
|
||||
Reference in new issue
Block a user