From dd41ed2c51beae07288fdfa724e410e0d321d278 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Wed, 22 Jul 2026 01:01:05 -0500 Subject: feat(a11y): engage the audit enforcement ratchet (#21) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The point of the Phase 0 harness finally lands: named findings in textClipped, dynamicType, hitRegion, elementDetection, sufficientElementDescription, and trait now FAIL the build on the empty-state suite. Regressions in five phases of accessibility work are gated, not narrated. Three carve-outs, each earned by evidence rather than convenience: - contrast stays report-only. The two long-standing Settings findings are rows scrolled under the translucent tab bar, and their attribution flips between a row name and nil run-to-run — no suppression is narrow enough to keep CI stable. The centralised palette is the real guard. - The seeded dense-row tests run reportOnly. Bisection showed the audit degrades on children-ignored content — the correct VoiceOver treatment for dense rows — emitting unattributed contrast/dynamicType failures on rows that measure 6-7:1 and render correctly. - Characterised noise is suppressed narrowly and always logged as [noise: reason]: disabled controls (WCAG 1.4.3 exempt), "nearly passed" near-misses, system field placeholders (flagged at any length — proven by shortening them to no effect), and unattributed clipped/dynamic-type artifacts. noiseReason(for:) records each rule's provenance inline. Validated in both directions. Positive: the full 11-test suite passes with enforcement live, dark and light, on an erased simulator. Negative: re-injecting the Phase 3 icon-exposure regression produced two named [FAIL] findings and a failed suite — on both screens sharing the component — then went green again on revert. Docs and the CI workflow comment updated to describe the engaged state. --- DomainDigUITests/AccessibilityAuditTests.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'DomainDigUITests/AccessibilityAuditTests.swift') diff --git a/DomainDigUITests/AccessibilityAuditTests.swift b/DomainDigUITests/AccessibilityAuditTests.swift index 0863d32..0a8f457 100644 --- a/DomainDigUITests/AccessibilityAuditTests.swift +++ b/DomainDigUITests/AccessibilityAuditTests.swift @@ -89,7 +89,7 @@ final class AccessibilityAuditTests: XCTestCase { func testSeededDashboard() throws { let app = AccessibilityAuditHarness.launch(seeded: true) app.selectRootTab("Dashboard") - let audited = try AccessibilityAuditHarness.audit(app, screen: "seeded-dashboard", test: self) + let audited = try AccessibilityAuditHarness.audit(app, screen: "seeded-dashboard", test: self, reportOnly: true) try XCTSkipUnless(audited, "Audit did not complete in time for seeded Dashboard") } @@ -100,7 +100,7 @@ final class AccessibilityAuditTests: XCTestCase { let trackedDomains = app.buttons["Tracked Domains"] XCTAssertTrue(trackedDomains.waitForExistence(timeout: 5)) trackedDomains.tap() - let audited = try AccessibilityAuditHarness.audit(app, screen: "seeded-tracked-domains", test: self) + let audited = try AccessibilityAuditHarness.audit(app, screen: "seeded-tracked-domains", test: self, reportOnly: true) try XCTSkipUnless(audited, "Audit did not complete in time for seeded Tracked Domains") } @@ -108,7 +108,7 @@ final class AccessibilityAuditTests: XCTestCase { func testSeededBatchResults() throws { let app = AccessibilityAuditHarness.launch(seeded: true) app.selectRootTab("Inspect") - let audited = try AccessibilityAuditHarness.audit(app, screen: "seeded-batch", test: self) + let audited = try AccessibilityAuditHarness.audit(app, screen: "seeded-batch", test: self, reportOnly: true) try XCTSkipUnless(audited, "Audit did not complete in time for seeded batch results") } @@ -123,12 +123,12 @@ final class AccessibilityAuditTests: XCTestCase { var unaudited: [String] = [] app.selectRootTab("Dashboard") - if try !AccessibilityAuditHarness.audit(app, screen: "seeded-dashboard-accessibilityXXXL", test: self) { + if try !AccessibilityAuditHarness.audit(app, screen: "seeded-dashboard-accessibilityXXXL", test: self, reportOnly: true) { unaudited.append("Dashboard") } app.selectRootTab("Inspect") - if try !AccessibilityAuditHarness.audit(app, screen: "seeded-batch-accessibilityXXXL", test: self) { + if try !AccessibilityAuditHarness.audit(app, screen: "seeded-batch-accessibilityXXXL", test: self, reportOnly: true) { unaudited.append("Inspect batch") } @@ -136,7 +136,7 @@ final class AccessibilityAuditTests: XCTestCase { let trackedDomains = app.buttons["Tracked Domains"] if trackedDomains.waitForExistence(timeout: 5) { trackedDomains.tap() - if try !AccessibilityAuditHarness.audit(app, screen: "seeded-tracked-domains-accessibilityXXXL", test: self) { + if try !AccessibilityAuditHarness.audit(app, screen: "seeded-tracked-domains-accessibilityXXXL", test: self, reportOnly: true) { unaudited.append("Tracked Domains") } } -- cgit v1.2.3