diff --git a/internal/driver/chrome/fact_parity_test.go b/internal/driver/chrome/fact_parity_test.go index c251240..fc9be28 100644 --- a/internal/driver/chrome/fact_parity_test.go +++ b/internal/driver/chrome/fact_parity_test.go @@ -57,6 +57,13 @@ type elementFacts struct { // typed value may be written into the shared record, so the two producers // disagreeing about it writes a credential into a run's trace. secure string + // checked, selected and focused reach a spec through the ax handle alone: + // they decide nothing about which action is offered, so the target + // enumeration does not carry them, and a selector naming one of them + // resolves against this same reading. + checked bool + selected bool + focused bool // handleClickable and handleEditable are the same facts on the ax element a // spec reaches through state.ax.find, a third place they are computed and the // one that has twice been the odd one out: clickable answered a hardcoded @@ -135,6 +142,9 @@ func factsFromHierarchyDump(t *testing.T, dump string) []factRow { scrollable: element.Attributes["scrollable"] == "true", hintText: element.Attributes["hintText"], secure: secureFromDump(element), + checked: element.Checked, + selected: element.Selected, + focused: element.Focused, positiveBounds: hasPositiveBounds( element.Bounds.Width(), element.Bounds.Height(), @@ -184,6 +194,9 @@ func factsFromWebRuntime( HandleClickable bool `json:"handleClickable"` HandleEditable bool `json:"handleEditable"` Secure *bool `json:"secure"` + Checked bool `json:"checked"` + Selected bool `json:"selected"` + Focused bool `json:"focused"` Width int `json:"width"` Height int `json:"height"` } @@ -204,6 +217,9 @@ func factsFromWebRuntime( handleClickable: item.HandleClickable, handleEditable: item.HandleEditable, secure: secureFromWebRuntime(item.Secure), + checked: item.Checked, + selected: item.Selected, + focused: item.Focused, positiveBounds: hasPositiveBounds(item.Width, item.Height), }, }) @@ -268,6 +284,9 @@ func requireBothPolarities(t *testing.T, rows []factRow) { {"editable", func(f elementFacts) bool { return f.editable }}, {"scrollable", func(f elementFacts) bool { return f.scrollable }}, {"hintText", func(f elementFacts) bool { return f.hintText != "" }}, + {"checked", func(f elementFacts) bool { return f.checked }}, + {"selected", func(f elementFacts) bool { return f.selected }}, + {"focused", func(f elementFacts) bool { return f.focused }}, {"positiveBounds", func(f elementFacts) bool { return f.positiveBounds }}, } { var sawTrue, sawFalse bool @@ -440,6 +459,9 @@ func compareDerivedFacts(t *testing.T, fromDump, fromWebRuntime []factRow) { {"enabled", dump.enabled, web.enabled}, {"editable", dump.editable, web.editable}, {"scrollable", dump.scrollable, web.scrollable}, + {"checked", dump.checked, web.checked}, + {"selected", dump.selected, web.selected}, + {"focused", dump.focused, web.focused}, {"positiveBounds", dump.positiveBounds, web.positiveBounds}, } { if fact.dump != fact.web { diff --git a/internal/driver/chrome/testdata/fact-parity-shadow.html b/internal/driver/chrome/testdata/fact-parity-shadow.html index c10073b..22d0ff3 100644 --- a/internal/driver/chrome/testdata/fact-parity-shadow.html +++ b/internal/driver/chrome/testdata/fact-parity-shadow.html @@ -27,9 +27,19 @@ + +
plain
`; + // document.activeElement names the HOST while focus is inside its shadow + // root, so a producer that does not descend reports focus on the mount + // element and never on the control, which is what a Compose for Web page + // looks like from the outside. + root.getElementById("shadow-agree").checked = true; + root.getElementById("shadow-save").focus(); diff --git a/internal/driver/chrome/testdata/fact-parity.html b/internal/driver/chrome/testdata/fact-parity.html index b118e79..b7d4e25 100644 --- a/internal/driver/chrome/testdata/fact-parity.html +++ b/internal/driver/chrome/testdata/fact-parity.html @@ -97,6 +97,14 @@
diff --git a/pkg/spec/test/dom-facts-probe.ts b/pkg/spec/test/dom-facts-probe.ts index 182c588..218a23e 100644 --- a/pkg/spec/test/dom-facts-probe.ts +++ b/pkg/spec/test/dom-facts-probe.ts @@ -22,6 +22,9 @@ type AxHandle = { clickable?: boolean; editable?: boolean; secure?: boolean | null; + checked?: boolean; + selected?: boolean; + focused?: boolean; }; type Ax = { find(selector: unknown): AxHandle | undefined }; @@ -55,6 +58,13 @@ function domFacts(): unknown[] { // side compares it against a dump that leaves the fact out entirely for an // element no producer states it for. secure: handle?.secure ?? null, + // The three states the target enumeration does not carry: they decide + // nothing about which action is offered, so they reach a spec through the + // handle alone, and a selector naming them resolves against the same + // reading. + checked: handle?.checked ?? false, + selected: handle?.selected ?? false, + focused: handle?.focused ?? false, width: target.width ?? 0, height: target.height ?? 0, };