Skip to content

Commit c36b9c9

Browse files
Make Python drawer qualification detect clipped nested destinations
1 parent 4598799 commit c36b9c9

6 files changed

Lines changed: 296 additions & 52 deletions

File tree

‎.github/workflows/docs-visual.yml‎

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ jobs:
142142
shift 3
143143
local capture_args=()
144144
local capture_url=http://127.0.0.1:4173/
145-
if [ "$width" = 640 ] && [ "$height" = 360 ]; then
145+
if [ "$width" = 640 ] && [ "$height" = 360 ] && [ "$state" = default ]; then
146146
capture_args+=(--full-page)
147147
fi
148148
if [ "$state" = search-populated ]; then
@@ -162,7 +162,7 @@ jobs:
162162
local route=$1 position=$2 state=$3 width=$4 height=$5
163163
shift 5
164164
local capture_args=()
165-
if [ "$width" = 640 ] && [ "$height" = 360 ]; then
165+
if [ "$width" = 640 ] && [ "$height" = 360 ] && [ "$state" = default ]; then
166166
capture_args+=(--full-page)
167167
fi
168168
node visual-controller/scripts/pipeline_visual_capture.mjs \
@@ -218,18 +218,73 @@ jobs:
218218
"revision": os.environ["SOURCE_REVISION"],
219219
}
220220
expected_routes = {
221-
"/reference/client/": {"position": "first", "surface": "python-sdk-client-reference"},
222-
"/reference/serializer/": {"position": "middle", "surface": "python-sdk-serializer-reference"},
223-
"/reference/testing/": {"position": "final", "surface": "python-sdk-testing-reference"},
221+
"/reference/client/": {
222+
"active": "Client",
223+
"position": "first",
224+
"surface": "python-sdk-client-reference",
225+
},
226+
"/reference/serializer/": {
227+
"active": "Serializer",
228+
"position": "middle",
229+
"surface": "python-sdk-serializer-reference",
230+
},
231+
"/reference/testing/": {
232+
"active": "Testing",
233+
"position": "final",
234+
"surface": "python-sdk-testing-reference",
235+
},
224236
}
237+
238+
def validate_reference_panel(panel, expected_active, label):
239+
if not isinstance(panel, dict):
240+
raise ValueError(f"{label} has no measured reference panel")
241+
try:
242+
active = panel["active"]
243+
drawer = panel["drawer"]
244+
reference_list = panel["list"]
245+
active_top = float(active["top"])
246+
active_bottom = float(active["bottom"])
247+
list_top = float(reference_list["top"])
248+
list_bottom = float(reference_list["bottom"])
249+
drawer_bottom = float(drawer["bottom"])
250+
client_height = float(reference_list["clientHeight"])
251+
except (KeyError, TypeError, ValueError) as error:
252+
raise ValueError(f"{label} has malformed reference panel geometry") from error
253+
if active.get("text") != expected_active:
254+
raise ValueError(f"{label} does not identify its active destination")
255+
if active_top < list_top - 1 or active_bottom > list_bottom + 1:
256+
raise ValueError(f"{label} clips its active destination")
257+
if abs(list_bottom - drawer_bottom) > 1 or client_height < 200:
258+
raise ValueError(f"{label} does not use the available drawer height")
259+
if reference_list.get("overflowY") != "auto":
260+
raise ValueError(f"{label} does not expose the qualified nested-list viewport")
261+
225262
if (
226-
keyboard.get("schema") != "durable-workflow.python-docs.nested-navigation/v2"
263+
keyboard.get("schema") != "durable-workflow.python-docs.nested-navigation/v3"
227264
or keyboard.get("outcome") != "pass"
228265
or set(keyboard.get("routes", [])) != set(expected_routes)
229266
):
230267
raise SystemExit("nested reference keyboard evidence did not qualify the required route positions")
231268
if keyboard.get("source") != expected_source:
232269
raise SystemExit("nested reference keyboard evidence is not bound to the captured source")
270+
regression = keyboard.get("regression", {})
271+
three_row_fixture = regression.get("three_row_list", {})
272+
if (
273+
three_row_fixture.get("visible_rows") != 3
274+
or three_row_fixture.get("geometry") != "affected fixture rejected"
275+
or three_row_fixture.get("interaction") != "affected fixture rejected"
276+
):
277+
raise SystemExit("nested reference evidence did not exercise the three-row clipped-list fixture")
278+
try:
279+
validate_reference_panel(
280+
three_row_fixture.get("reference_panel"),
281+
expected_routes["/reference/testing/"]["active"],
282+
"three-row clipped-list fixture",
283+
)
284+
except ValueError:
285+
pass
286+
else:
287+
raise SystemExit("retained visual-evidence validation accepted the three-row clipped-list fixture")
233288
keyboard_viewports = {
234289
(entry["route"], entry["viewport"]["width"], entry["viewport"]["height"]): entry
235290
for entry in keyboard.get("viewports", [])
@@ -261,7 +316,7 @@ jobs:
261316
viewport_key = (viewport.get("width"), viewport.get("height"))
262317
page_route = urlsplit(captured.get("page_url", "")).path
263318
route_contract = expected_routes.get(page_route)
264-
expected_full_page = viewport_key == (640, 360)
319+
expected_full_page = viewport_key == (640, 360) and state == "default"
265320
if (
266321
route_contract is None
267322
or captured.get("surface") != route_contract["surface"]
@@ -280,6 +335,16 @@ jobs:
280335
active_keyboard_controls = keyboard_state.get("active_keyboard_controls")
281336
if state == "navigation-open" and not active_keyboard_controls:
282337
raise SystemExit(f"{report.name} has no active drawer keyboard traversal evidence")
338+
reference_panel = keyboard_state.get("reference_panel")
339+
if state == "navigation-open":
340+
try:
341+
validate_reference_panel(
342+
reference_panel,
343+
route_contract["active"],
344+
report.name,
345+
)
346+
except ValueError as error:
347+
raise SystemExit(str(error)) from error
283348
geometry = captured["geometry"]
284349
if geometry["unreachable_controls"]:
285350
raise SystemExit(
@@ -300,18 +365,19 @@ jobs:
300365
"full_page": captured["full_page"],
301366
"pointer_unreachable_controls": geometry["unreachable_controls"],
302367
"active_keyboard_controls": active_keyboard_controls or [],
368+
"reference_panel": reference_panel,
303369
}
304370
)
305371
if observed_states != expected_states:
306372
raise SystemExit(f"nested reference state matrix does not match: {sorted(observed_states)}")
307373
308374
qualification = {
309-
"schema": "durable-workflow.python-docs.nested-navigation-qualification/v2",
375+
"schema": "durable-workflow.python-docs.nested-navigation-qualification/v3",
310376
"outcome": "pass",
311377
"source": expected_source,
312378
"routes": list(expected_routes),
313379
"states": qualified_states,
314-
"regression": keyboard.get("regression"),
380+
"regression": regression,
315381
}
316382
(evidence_root / "nested-navigation-qualification.json").write_text(
317383
f"{json.dumps(qualification, indent=2)}\n",

‎docs/javascripts/navigation-accessibility.js‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,25 @@
9292
const releaseInactivePanelControls = () => {
9393
for (const element of panelInerted) element.inert = false;
9494
panelInerted = [];
95+
for (const list of drawer.querySelectorAll(".dw-navigation__ancestor-list")) {
96+
list.classList.remove("dw-navigation__ancestor-list");
97+
}
9598
};
9699

97100
const isolateActivePanel = () => {
98101
releaseInactivePanelControls();
99102
if (!modalOpen) return;
100103

101104
const activePanel = activeNavigationPanel();
105+
for (
106+
let ancestor = activePanel.parentElement;
107+
ancestor && ancestor !== drawer;
108+
ancestor = ancestor.parentElement
109+
) {
110+
if (ancestor.classList.contains("md-nav__list")) {
111+
ancestor.classList.add("dw-navigation__ancestor-list");
112+
}
113+
}
102114
const inactivePanels = [...drawer.querySelectorAll("input.md-nav__toggle:not(:checked)")]
103115
.map((panelToggle) => panelToggle.parentElement?.querySelector(":scope > nav.md-nav"))
104116
.filter((panel) => panel instanceof HTMLElement);

‎docs/stylesheets/layout.css‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
}
66

77
@media screen and (max-width: 59.984375em) {
8+
.md-sidebar--primary .md-nav__list.dw-navigation__ancestor-list {
9+
overflow: visible;
10+
}
11+
812
.md-nav--primary > .dw-navigation__close {
913
display: flex;
1014
}

0 commit comments

Comments
 (0)