Files
sanderling/pkg/spec/test/dom-facts-probe.ts
T
pj 04327e63b6 test(chrome): the handle and the enumeration agree on editable too
The helper compared clickable alone, so the inherited-contenteditable bug
was caught by unit test only and never in a real browser.
2026-08-18 00:15:55 +05:30

62 lines
2.2 KiB
TypeScript

/// <reference lib="dom" />
// The V8 host's fact producer, read back element by element.
//
// internal/driver/chrome/fact_parity_test.go bundles this probe into a live page
// and compares what it returns against the hierarchy dump the goja host reads
// off the SAME page. Both sides derive their facts here, in production code:
// collectTargets is the shipped walk, and targetElements is the shipped
// enumeration domain, so the id at index i names the element facts[i] describes.
// The dump carries that id as `resource-id`, which is what the Go side joins on.
import { __testing__ } from "../src/web-runtime.ts";
const { collectTargets, targetElements, buildAx } = __testing__;
// The handle facts are read back off the shipped ax element, the way a spec
// reaches them and the way internal/verifier/llm.go handleLabel reads them, so
// the comparison runs over what the model is actually shown rather than over a
// recomputation of it.
type AxHandle = {
attrs?: Record<string, string>;
clickable?: boolean;
editable?: boolean;
};
type Ax = { find(selector: unknown): AxHandle | undefined };
function handleOf(ax: Ax, id: string): AxHandle | undefined {
return id ? ax.find({ id }) : undefined;
}
function domFacts(): unknown[] {
const elements = targetElements();
const facts = collectTargets();
const ax = buildAx() as Ax;
if (elements.length !== facts.length) {
throw new Error(
`collectTargets reported ${facts.length} targets over ${elements.length} elements`,
);
}
return elements.map((element, index) => {
const target = facts[index]!;
const handle = handleOf(ax, element.id);
return {
id: element.id,
tag: element.tagName.toLowerCase(),
clickable: target.clickable,
enabled: target.enabled,
editable: target.editable,
scrollable: target.scrollable,
hintText: handle?.attrs?.hintText ?? "",
handleClickable: handle?.clickable ?? false,
handleEditable: handle?.editable ?? false,
width: target.width ?? 0,
height: target.height ?? 0,
};
});
}
type FactsGlobal = { __sanderlingDomFacts__: () => unknown[] };
(globalThis as unknown as FactsGlobal).__sanderlingDomFacts__ = domFacts;