Skip to content

Commit 3ef51f4

Browse files
Merge issue #172: cover public detail states with JavaScript disabled (#172)
2 parents a6e0f59 + 015cfe9 commit 3ef51f4

4 files changed

Lines changed: 310 additions & 46 deletions

File tree

core/accessibility_registry.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,42 @@ def _state(
173173
),
174174
)
175175

176+
# The meaningful public read-only states that must render without client-side JavaScript. Keep
177+
# route-contract states (the removed people catalogue and approved redirect) in the complete
178+
# JavaScript-enabled scenario only: they assert an HTTP contract rather than a rendered page.
179+
#
180+
# The Playwright fixture owns the source-backed surface/marker map. Its policy check requires
181+
# this tuple to match that map exactly, so a stale/duplicated/unclassified registry ID fails before
182+
# a browser matrix can silently skip it.
183+
NO_JAVASCRIPT_PUBLIC_STATE_IDS = (
184+
"public.home",
185+
"public.blog-hub",
186+
"public.podcast-hub",
187+
"public.books-hub",
188+
"public.events-hub",
189+
"public.courses-hub",
190+
"public.wiki-hub",
191+
"public.docs-hub",
192+
"public.faq-hub",
193+
"public.slack",
194+
"public.article-detail",
195+
"public.podcast-transcript-media",
196+
"public.book-detail",
197+
"public.event-aggregate-speaker",
198+
"public.person-detail",
199+
"public.course-detail",
200+
"public.wiki-detail",
201+
"public.docs-nested",
202+
"public.faq-anchor",
203+
"public.wiki-results",
204+
"public.wiki-zero-results",
205+
"public.wiki-graph",
206+
"public.wiki-special-pages",
207+
"public.missing-media",
208+
"public.empty-state",
209+
"public.application-404",
210+
)
211+
176212
# No exception is accepted by this implementation. Keeping the typed registry here makes any
177213
# future exception reviewable and forces all required ownership/expiry fields to be supplied.
178214
AXE_EXCEPTIONS: tuple[AxeException, ...] = ()

core/static/core/accessibility.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ body {
66
overflow-wrap: anywhere;
77
}
88

9+
/*
10+
* Public detail artwork is rendered before the Tailwind runtime runs. Keep the
11+
* source-backed media inside the readable article column when JavaScript is
12+
* disabled (the utility classes still provide the richer JS-enabled styling).
13+
*/
14+
#main-content > #content > article > img {
15+
height: auto;
16+
max-width: 100%;
17+
}
18+
919
.faq-answer :is(code, pre) {
1020
overflow-wrap: anywhere;
1121
white-space: pre-wrap;

core/tests/test_accessibility.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
AXE_EXCEPTIONS,
1414
BEHAVIOR_SCENARIOS,
1515
CRITICAL_STATES,
16+
NO_JAVASCRIPT_PUBLIC_STATE_IDS,
1617
registry_fingerprint,
1718
template_readability_issues,
1819
template_surface,
@@ -65,6 +66,21 @@ def test_registry_identifiers_and_rendered_surfaces_are_fail_closed(self) -> Non
6566
self.assertTrue(state.route_contract)
6667
self.assertRegex(registry_fingerprint(), r"^[0-9a-f]{64}$")
6768

69+
def test_no_javascript_public_policy_is_exactly_rendered_public_states(self) -> None:
70+
self.assertEqual(len(NO_JAVASCRIPT_PUBLIC_STATE_IDS), 26)
71+
self.assertEqual(
72+
len(NO_JAVASCRIPT_PUBLIC_STATE_IDS),
73+
len(set(NO_JAVASCRIPT_PUBLIC_STATE_IDS)),
74+
)
75+
states = {state.identifier: state for state in CRITICAL_STATES}
76+
for identifier in NO_JAVASCRIPT_PUBLIC_STATE_IDS:
77+
with self.subTest(state=identifier):
78+
state = states[identifier]
79+
self.assertEqual(state.group, "public")
80+
self.assertEqual(state.behavior_test, "public-current-states")
81+
self.assertIsNotNone(state.axe_surface)
82+
self.assertFalse(state.route_contract)
83+
6884
def test_every_authored_product_template_has_one_surface_owner(self) -> None:
6985
root = Path(settings.BASE_DIR)
7086
candidates: set[Path] = set()

0 commit comments

Comments
 (0)