test/domains/ref-stability-test.ts (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
import { test, describe } from "node:test";
import assert from "node:assert/strict";
import { createFakeClient, axNode } from "./fake-client";
import { interactiveDiff } from "../../src/domains/ref-resolve";
import { ok } from "../../src/util/result";
const SEEDED = [
{ ref: "e1", backendId: 101, sig: "textbox|Email||" },
{ ref: "e2", backendId: 102, sig: "textbox|Name||" },
{ ref: "e3", backendId: 103, sig: "button|Go||" },
];
const treeWithNewButtonFirst = ok({
nodes: [
axNode("1", "RootWebArea", "", { childIds: ["9", "2", "3", "4"] }),
axNode("9", "button", "Dismiss", { parentId: "1", backendDOMNodeId: 999 }),
axNode("2", "textbox", "Email", { parentId: "1", backendDOMNodeId: 101 }),
axNode("3", "textbox", "Name", { parentId: "1", backendDOMNodeId: 102 }),
axNode("4", "button", "Go", { parentId: "1", backendDOMNodeId: 103 }),
],
});
const treeUnchanged = ok({
nodes: [
axNode("1", "RootWebArea", "", { childIds: ["2", "3", "4"] }),
axNode("2", "textbox", "Email", { parentId: "1", backendDOMNodeId: 101, value: { value: "a@b.com" } }),
axNode("3", "textbox", "Name", { parentId: "1", backendDOMNodeId: 102 }),
axNode("4", "button", "Go", { parentId: "1", backendDOMNodeId: 103 }),
],
});
describe("ref stability across a mutation", () => {
test("an element appearing above the others does not steal their refs", async () => {
const fake = await createFakeClient({
refs: SEEDED,
canned: { "Accessibility.getFullAXTree": treeWithNewButtonFirst },
});
await interactiveDiff(fake.client);
assert.equal(fake.session.resolveRef("e1"), 101);
assert.equal(fake.session.resolveRef("e2"), 102);
assert.equal(fake.session.resolveRef("e3"), 103);
});
test("a newly appeared element gets a fresh ref rather than an existing one", async () => {
const fake = await createFakeClient({
refs: SEEDED,
canned: { "Accessibility.getFullAXTree": treeWithNewButtonFirst },
});
const diff = await interactiveDiff(fake.client);
assert.equal(fake.session.resolveRef("e4"), 999);
assert.match(diff, /\*\[e4\] button "Dismiss"/);
});
test("refs are unchanged when the interactive set is unchanged", async () => {
const fake = await createFakeClient({
refs: SEEDED,
canned: { "Accessibility.getFullAXTree": treeUnchanged },
});
const diff = await interactiveDiff(fake.client);
assert.equal(fake.session.resolveRef("e1"), 101);
assert.equal(fake.session.resolveRef("e2"), 102);
assert.equal(fake.session.resolveRef("e3"), 103);
assert.match(diff, /\[e1\] textbox "Email": value "" → "a@b.com"/);
});
test("every published ref maps to a distinct element", async () => {
const fake = await createFakeClient({
refs: SEEDED,
canned: { "Accessibility.getFullAXTree": treeWithNewButtonFirst },
});
await interactiveDiff(fake.client);
const seen = new Set<number>();
for (const ref of ["e1", "e2", "e3", "e4"]) {
const backendId = fake.session.resolveRef(ref);
assert.ok(backendId !== undefined, `${ref} resolved to nothing`);
assert.equal(seen.has(backendId), false, `${ref} duplicates another ref's element`);
seen.add(backendId);
}
});
});
|