krz/domain-dig

an ios app for DNS & SSL analysis

clone: git clone https://gitbay.org/krz/domain-dig.git

v4.9.0: DomainDigUITests/AccessibilityAuditTests.swift · raw

  1import XCTest
  2
  3/// One accessibility audit per primary screen, plus a Dynamic Type sweep.
  4///
  5/// See `AccessibilityAuditHarness` for why these report rather than fail by
  6/// default, and how to make them enforcing.
  7@MainActor
  8final class AccessibilityAuditTests: XCTestCase {
  9    override func setUp() {
 10        // Keep going after a failure so an enforced audit still collects and
 11        // attaches every finding. With this off, XCTest aborts at the first
 12        // reported issue and the burndown list is lost precisely when a category
 13        // is being enforced.
 14        continueAfterFailure = true
 15    }
 16
 17    // MARK: Per-screen audits
 18
 19    func testInspectScreen() throws {
 20        try auditRootTab("Inspect")
 21    }
 22
 23    func testDashboardScreen() throws {
 24        try auditRootTab("Dashboard")
 25    }
 26
 27    func testAuditScreen() throws {
 28        try auditRootTab("Audit")
 29    }
 30
 31    func testHistoryScreen() throws {
 32        try auditRootTab("History")
 33    }
 34
 35    func testSettingsScreen() throws {
 36        try auditRootTab("Settings")
 37    }
 38
 39    func testTrackedDomainsScreen() throws {
 40        let app = AccessibilityAuditHarness.launch()
 41        app.selectRootTab("Settings")
 42
 43        let trackedDomains = app.buttons["Tracked Domains"]
 44        XCTAssertTrue(
 45            trackedDomains.waitForExistence(timeout: 5),
 46            "Settings no longer offers a Tracked Domains row"
 47        )
 48        trackedDomains.tap()
 49
 50        let audited = try AccessibilityAuditHarness.audit(app, screen: "tracked-domains", test: self)
 51        try XCTSkipUnless(audited, "Tracked Domains audit did not complete in time")
 52    }
 53
 54    // MARK: Dynamic Type
 55
 56    /// Re-audits every root screen at the largest accessibility content size.
 57    ///
 58    /// This is where clipped text and fixed-height containers surface  the
 59    /// `.accessibility5`-class failures that the fixed geometry in
 60    /// `AppDensityMetrics` is expected to produce until phase 3 of #21 lands.
 61    ///
 62    /// Every screen is attempted even if an earlier one times out, so one slow
 63    /// screen cannot silently drop the rest; the skip is reported at the end.
 64    func testAllScreensAtLargestAccessibilitySize() throws {
 65        let app = AccessibilityAuditHarness.launch(
 66            contentSizeCategory: "UICTContentSizeCategoryAccessibilityXXXL"
 67        )
 68
 69        var unaudited: [String] = []
 70
 71        for tab in ["Inspect", "Dashboard", "Audit", "History", "Settings"] {
 72            app.selectRootTab(tab)
 73            let screen = "\(tab.lowercased())-accessibilityXXXL"
 74            if try !AccessibilityAuditHarness.audit(app, screen: screen, test: self) {
 75                unaudited.append(tab)
 76            }
 77        }
 78
 79        try XCTSkipUnless(
 80            unaudited.isEmpty,
 81            "Audit did not complete in time for: \(unaudited.joined(separator: ", "))"
 82        )
 83    }
 84
 85    // MARK: Seeded audits  dense rows that never render on an empty simulator
 86
 87    /// Dashboard with a populated portfolio: summary tiles, quick filters,
 88    /// activity/attention/expiry rows, and the grouped portfolio list.
 89    func testSeededDashboard() throws {
 90        let app = AccessibilityAuditHarness.launch(seeded: true)
 91        app.selectRootTab("Dashboard")
 92        let audited = try AccessibilityAuditHarness.audit(app, screen: "seeded-dashboard", test: self, reportOnly: true)
 93        try XCTSkipUnless(audited, "Audit did not complete in time for seeded Dashboard")
 94    }
 95
 96    /// The watchlist's dense rows (up to nine text elements each).
 97    func testSeededTrackedDomains() throws {
 98        let app = AccessibilityAuditHarness.launch(seeded: true)
 99        app.selectRootTab("Settings")
100        let trackedDomains = app.buttons["Tracked Domains"]
101        XCTAssertTrue(trackedDomains.waitForExistence(timeout: 5))
102        trackedDomains.tap()
103        let audited = try AccessibilityAuditHarness.audit(app, screen: "seeded-tracked-domains", test: self, reportOnly: true)
104        try XCTSkipUnless(audited, "Audit did not complete in time for seeded Tracked Domains")
105    }
106
107    /// Batch result rows on the Inspect tab, including a failed lookup.
108    func testSeededBatchResults() throws {
109        let app = AccessibilityAuditHarness.launch(seeded: true)
110        app.selectRootTab("Inspect")
111        let audited = try AccessibilityAuditHarness.audit(app, screen: "seeded-batch", test: self, reportOnly: true)
112        try XCTSkipUnless(audited, "Audit did not complete in time for seeded batch results")
113    }
114
115    /// The seeded screens again at the largest accessibility size  the case the
116    /// deferred ViewThatFits work exists for.
117    func testSeededScreensAtLargestAccessibilitySize() throws {
118        let app = AccessibilityAuditHarness.launch(
119            contentSizeCategory: "UICTContentSizeCategoryAccessibilityXXXL",
120            seeded: true
121        )
122
123        var unaudited: [String] = []
124
125        app.selectRootTab("Dashboard")
126        if try !AccessibilityAuditHarness.audit(app, screen: "seeded-dashboard-accessibilityXXXL", test: self, reportOnly: true) {
127            unaudited.append("Dashboard")
128        }
129
130        app.selectRootTab("Inspect")
131        if try !AccessibilityAuditHarness.audit(app, screen: "seeded-batch-accessibilityXXXL", test: self, reportOnly: true) {
132            unaudited.append("Inspect batch")
133        }
134
135        app.selectRootTab("Settings")
136        let trackedDomains = app.buttons["Tracked Domains"]
137        if trackedDomains.waitForExistence(timeout: 5) {
138            trackedDomains.tap()
139            if try !AccessibilityAuditHarness.audit(app, screen: "seeded-tracked-domains-accessibilityXXXL", test: self, reportOnly: true) {
140                unaudited.append("Tracked Domains")
141            }
142        }
143
144        try XCTSkipUnless(
145            unaudited.isEmpty,
146            "Audit did not complete in time for: \(unaudited.joined(separator: ", "))"
147        )
148    }
149
150    // MARK: Helpers
151
152    private func auditRootTab(_ tab: String) throws {
153        let app = AccessibilityAuditHarness.launch()
154        app.selectRootTab(tab)
155        let audited = try AccessibilityAuditHarness.audit(app, screen: tab.lowercased(), test: self)
156        try XCTSkipUnless(audited, "Audit did not complete in time for \(tab)")
157    }
158}