Fix 4 flaky UI tests for iOS 26 compatibility

- AppLaunchTests/StabilityTests: Increase assertTabSelected timeout to
  8s for iOS 26 Liquid Glass delayed isSelected state updates
- DeepLinkTests: Detect SubscriptionStoreView container instead of text
  labels, since Apple's native view shows "Subscription Unavailable" in
  test storefront
- SettingsActionTests: Check for empty state after clearing data, bump
  Settings header timeout to 8s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-02-26 18:59:22 -06:00
parent 087d8c4cdd
commit 16c5c34942
5 changed files with 16 additions and 11 deletions

View File

@@ -51,7 +51,8 @@ final class AppLaunchTests: BaseUITestCase {
}
/// Wait for a tab to become selected (iOS 26 Liquid Glass may delay state updates).
private func assertTabSelected(_ tab: XCUIElement, name: String, timeout: TimeInterval = 3) {
private func assertTabSelected(_ tab: XCUIElement, name: String, timeout: TimeInterval = 8) {
// Re-query the element to get fresh state, since isSelected can be stale.
let predicate = NSPredicate(format: "isSelected == true")
let expectation = XCTNSPredicateExpectation(predicate: predicate, object: tab)
let result = XCTWaiter.wait(for: [expectation], timeout: timeout)

View File

@@ -57,12 +57,12 @@ final class DeepLinkTests: BaseUITestCase {
app.open(subscribeURL)
// Subscription view should appear as a sheet.
// Look for common subscription UI elements.
let subscribeText = app.staticTexts.matching(
NSPredicate(format: "label CONTAINS[c] 'subscribe' OR label CONTAINS[c] 'premium' OR label CONTAINS[c] 'upgrade' OR label CONTAINS[c] 'Reflect+'")
).firstMatch
// Detect the SubscriptionStoreView container (works even when products are unavailable in test).
let storeContainer = app.descendants(matching: .any)
.matching(identifier: "Subscription Store View Container")
.firstMatch
let found = subscribeText.waitForExistence(timeout: 8)
let found = storeContainer.waitForExistence(timeout: 8)
captureScreenshot(name: "deeplink_subscribe_result")

View File

@@ -53,7 +53,7 @@ struct SettingsScreen {
func assertVisible(file: StaticString = #file, line: UInt = #line) {
XCTAssertTrue(
settingsHeader.waitForExistence(timeout: 5),
settingsHeader.waitForExistence(timeout: 8),
"Settings header should be visible",
file: file, line: line
)

View File

@@ -45,10 +45,14 @@ final class SettingsActionTests: BaseUITestCase {
tabBar.tapDay()
// App should remain usable after clearing data.
assertDayContentVisible(timeout: 10)
// After a full clear, Day view may show mood header, entry rows, or empty state.
let hasEntry = app.firstEntryRow.waitForExistence(timeout: 10)
let hasMoodHeader = app.element(UITestID.Day.moodHeader).waitForExistence(timeout: 2)
let hasEmptyState = app.element(UITestID.Day.emptyStateNoData).waitForExistence(timeout: 2)
XCTAssertTrue(hasEntry || hasMoodHeader || hasEmptyState,
"Day view should show entries, mood header, or empty state after clearing data")
// Clear action should not crash the app, even if the resulting day content
// is rehydrated by app-specific defaults/placeholders.
// Clear action should not crash the app.
XCTAssertTrue(app.tabBars.firstMatch.exists, "App should remain responsive after clearing data")
captureScreenshot(name: "data_cleared")

View File

@@ -67,7 +67,7 @@ final class StabilityTests: BaseUITestCase {
}
/// Wait for a tab to become selected (iOS 26 Liquid Glass may delay state updates).
private func assertTabSelected(_ tab: XCUIElement, name: String, timeout: TimeInterval = 3) {
private func assertTabSelected(_ tab: XCUIElement, name: String, timeout: TimeInterval = 8) {
let predicate = NSPredicate(format: "isSelected == true")
let expectation = XCTNSPredicateExpectation(predicate: predicate, object: tab)
let result = XCTWaiter.wait(for: [expectation], timeout: timeout)