diff --git a/CHANGELOG.md b/CHANGELOG.md index 37f30fcd..cfe901b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,11 @@ building, testing, or releasing the app. ### Developer Experience +- Keep the loading and Use Reset progress unit tests passing when the + simulator has app accessibility enabled, where the system reads progress + labels as "In progress, …". Wait for the dashboard body before checking the + loading state. ([#527](https://github.com/hemsoft-dev/codexbar-ios/issues/527)) + - Split manual iPhone and iPad UI qualification into measured shards while preserving the 90-minute worker limit and automatic PR checks. Keep touch target assertions from rejecting 44-point controls due to floating-point noise. diff --git a/CodexBarIOSTests/FreeTierPresentationTests.swift b/CodexBarIOSTests/FreeTierPresentationTests.swift index bdc66bcd..b4270866 100644 --- a/CodexBarIOSTests/FreeTierPresentationTests.swift +++ b/CodexBarIOSTests/FreeTierPresentationTests.swift @@ -158,8 +158,15 @@ final class FreeTierPresentationTests: XCTestCase { func testDashboardShowsLoadingUntilInitialRefreshCompletes() throws { try withDashboard(performsLifecycleWork: true, settles: false) { probe in - XCTAssertEqual( - probe.element(identifier: "dashboard-account-loading")?.accessibilityLabel, "Loading accounts…", "\(probe.labels)" + // The toolbar can publish before the dashboard body, so wait for the first body state. + XCTAssertTrue(probe.waitUntil { + probe.element(identifier: "dashboard-account-loading") != nil + || probe.element(label: "Connect your first account") != nil + }, "\(probe.labels)") + XCTAssertTrue( + HostedViewProbe.isProgressLabel( + probe.element(identifier: "dashboard-account-loading")?.accessibilityLabel, "Loading accounts…" + ), "\(probe.labels)" ) XCTAssertNil(probe.element(label: "Connect your first account")) diff --git a/CodexBarIOSTests/ProviderUsageCardHiddenSeverityTests.swift b/CodexBarIOSTests/ProviderUsageCardHiddenSeverityTests.swift index 9f93ac59..454dc6db 100644 --- a/CodexBarIOSTests/ProviderUsageCardHiddenSeverityTests.swift +++ b/CodexBarIOSTests/ProviderUsageCardHiddenSeverityTests.swift @@ -436,6 +436,15 @@ final class ProviderUsageCardHiddenSeverityTests: XCTestCase { XCTAssertNil(lockedProbe.element(identifier: "claude-reset-cooldown")) } + @MainActor + func testProgressLabelMatchAcceptsOnlyTheLabelOrItsInProgressForm() { + XCTAssertTrue(HostedViewProbe.isProgressLabel("Using reset…", "Using reset…")) + XCTAssertTrue(HostedViewProbe.isProgressLabel("In progress, Using reset…", "Using reset…")) + for label in [nil, "", "In progress", "Use one reset", "Using reset", "In progress, Use one reset", "Using reset…, In progress"] { + XCTAssertFalse(HostedViewProbe.isProgressLabel(label, "Using reset…"), "\(String(describing: label))") + } + } + @MainActor func testResetInventoryShowsProgressThenFeedbackWhileUsingConfirmedReset() throws { let now = Date() @@ -459,7 +468,9 @@ final class ProviderUsageCardHiddenSeverityTests: XCTestCase { XCTAssertTrue(probe.waitUntil { probe.element(label: "Use reset") != nil }, "\(probe.labels)") XCTAssertTrue(probe.chooseAlertAction("Use reset"), "\(probe.labels)") XCTAssertTrue(probe.waitUntil { gate.request != nil }, "\(probe.labels)") - XCTAssertTrue(probe.waitUntil { probe.labels.contains("Using reset…") }, "\(probe.labels)") + XCTAssertTrue( + probe.waitUntil { probe.labels.contains { HostedViewProbe.isProgressLabel($0, "Using reset…") } }, "\(probe.labels)" + ) XCTAssertEqual(gate.request?.grantID, grant.id) XCTAssertEqual(gate.request?.binding, "binding") @@ -624,6 +635,12 @@ final class HostedViewProbe { elements.first { $0.accessibilityLabel?.hasPrefix(labelPrefix) == true } } + /// SwiftUI reports a labelled ProgressView as "In progress,