mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-04 12:07:09 +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> {
|
export function extract<T>(getter: (state: State) => T): Extracted<T> {
|
||||||
return globalThis.__sanderling__.extract(getter);
|
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,
|
WeightedEntry,
|
||||||
} from "./types.ts";
|
} from "./types.ts";
|
||||||
|
|
||||||
export { extract } from "./extract.ts";
|
export { extract, keyedBy } from "./extract.ts";
|
||||||
export { always, eventually, next, now } from "./ltl.ts";
|
export { always, eventually, next, now } from "./ltl.ts";
|
||||||
export {
|
export {
|
||||||
InputText,
|
InputText,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
eventually,
|
eventually,
|
||||||
extract,
|
extract,
|
||||||
from,
|
from,
|
||||||
|
keyedBy,
|
||||||
next,
|
next,
|
||||||
now,
|
now,
|
||||||
pressKey,
|
pressKey,
|
||||||
@@ -281,6 +282,47 @@ test("from forwards items to the runtime", () => {
|
|||||||
assert.equal(sampler.generate(), "a");
|
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", () => {
|
test("default generators proxy through to the runtime", () => {
|
||||||
installFakeRuntime();
|
installFakeRuntime();
|
||||||
assert.equal(taps.__sanderlingActionGenerator, true);
|
assert.equal(taps.__sanderlingActionGenerator, true);
|
||||||
|
|||||||
Reference in new issue
Block a user