commit 3aa823bc97725a43894095ccee5327fca6144831
parent d9b521d738d0ce7fd23a3c95a235ba047bcb0b55
Author: triesap <tyson@radroots.org>
Date: Sat, 29 Aug 2026 02:22:34 +0000
ios: separate contrast and persona audits
- Keep the dedicated five-form accessibility lane responsible for contrast.
- Retain semantic, clipping, trait, and hit-region audits in P04 attempts.
- Remove the brittle native picker disclosure exception entirely.
- Verify the full contrast lane on the final separated source bytes.
Diffstat:
1 file changed, 19 insertions(+), 28 deletions(-)
diff --git a/RadrootsUITests/RadrootsRemoteQualificationUITests.swift b/RadrootsUITests/RadrootsRemoteQualificationUITests.swift
@@ -420,9 +420,23 @@ final class RadrootsRemoteQualificationUITests: XCTestCase {
]
}
+ private var personaSemanticAuditTypes: XCUIAccessibilityAuditType {
+ [
+ .elementDetection,
+ .hitRegion,
+ .sufficientElementDescription,
+ .textClipped,
+ .trait,
+ ]
+ }
+
@MainActor
- private func performLocalSocialAccessibilityAudit(_ app: XCUIApplication) throws {
- try app.performAccessibilityAudit(for: accessibilityAuditTypes) { issue in
+ private func performLocalSocialAccessibilityAudit(
+ _ app: XCUIApplication,
+ includeContrast: Bool = true
+ ) throws {
+ let auditTypes = includeContrast ? accessibilityAuditTypes : personaSemanticAuditTypes
+ try app.performAccessibilityAudit(for: auditTypes) { issue in
if issue.auditType == .contrast && issue.compactDescription == "Contrast nearly passed" {
return true
}
@@ -445,9 +459,6 @@ final class RadrootsRemoteQualificationUITests: XCTestCase {
{
return true
}
- if self.isNativeAddTypePickerDisclosureIssue(issue, app: app) {
- return true
- }
// Xcode 26 can emit text-clipping findings with no element, identifier,
// label, type, or frame. Element-bound findings remain fatal.
guard let element = issue.element else { return issue.auditType == .textClipped }
@@ -458,28 +469,6 @@ final class RadrootsRemoteQualificationUITests: XCTestCase {
}
@MainActor
- private func isNativeAddTypePickerDisclosureIssue(
- _ issue: XCUIAccessibilityAuditIssue,
- app: XCUIApplication
- ) -> Bool {
- guard issue.auditType == .contrast, let element = issue.element else { return false }
- let picker = app.descendants(matching: .any)["radroots.add.type"]
- guard picker.exists, picker.isEnabled, let selected = picker.value as? String else {
- return false
- }
- let governedLabels = ["Update", "Photo update", "Ask", "Event", "Food availability"]
- guard governedLabels.contains(selected), element.frame.intersects(picker.frame) else {
- return false
- }
- // Xcode 26 folds the system navigation-link disclosure glyph into the
- // picker's SwiftUI accessibility node. The selected value is explicitly
- // primary-colored; only that native decorative glyph is exempted here.
- let exactLabels = [selected, "Type", "Type, \(selected)"]
- return element.identifier == "radroots.add.type"
- || (element.identifier.isEmpty && exactLabels.contains(element.label))
- }
-
- @MainActor
private func systemChromePartiallyOccludes(_ element: XCUIElement, app: XCUIApplication) -> Bool {
let frame = element.frame
let navigationBar = app.navigationBars.firstMatch
@@ -848,7 +837,9 @@ final class RadrootsRemoteQualificationUITests: XCTestCase {
assertProgressiveDisclosure(app, type: type)
}
if interactionProfile == "novice_accessibility_keyboard" {
- try performLocalSocialAccessibilityAudit(app)
+ // The dedicated accessibility test owns the exact full contrast lane.
+ // Persona attempts retain every semantic audit plus keyboard/focus use.
+ try performLocalSocialAccessibilityAudit(app, includeContrast: false)
}
try completeOpenDraft(app, flow: attempt.flow, marker: attempt.marker)
}