Files
Reflect/Tests iOS/Screens/SettingsScreen.swift
Trey t 44b46f88e2 Fix 23 failing UI tests: accessibility hierarchy, test mode, and interaction issues
App fixes:
- Remove empty_state identifier from EmptyHomeView VStack (was overriding mood_header)
- Fix resetAppState to set needsOnboarding=true (fresh state) instead of false
- Set bypassSubscription explicitly based on launch arg presence (was defaulting to true in DEBUG)

Test fixes:
- TabBarScreen: use coordinate tap to avoid iOS 26 Liquid Glass hittability issues
- SettingsScreen: use coordinate tap for segments, handle Settings label ambiguity with tab bar
- EntryDetailScreen: use mood_button_ identifiers instead of label matching (was matching entry rows)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:14:16 -06:00

94 lines
3.4 KiB
Swift

//
// SettingsScreen.swift
// Tests iOS
//
// Screen object for the Settings tab (Customize + Settings sub-tabs).
//
import XCTest
struct SettingsScreen {
let app: XCUIApplication
// MARK: - Elements
var settingsHeader: XCUIElement { app.staticTexts["settings_header"] }
var customizeSegment: XCUIElement { app.buttons["Customize"] }
var upgradeBanner: XCUIElement { app.otherElements["upgrade_banner"] }
var subscribeButton: XCUIElement { app.buttons["subscribe_button"] }
var whyUpgradeButton: XCUIElement { app.buttons["why_upgrade_button"] }
var browseThemesButton: XCUIElement { app.buttons["browse_themes_button"] }
var clearDataButton: XCUIElement { app.buttons["settings_clear_data"].firstMatch }
var analyticsToggle: XCUIElement { app.descendants(matching: .any).matching(identifier: "settings_analytics_toggle").firstMatch }
var showOnboardingButton: XCUIElement { app.buttons["settings_show_onboarding"].firstMatch }
// MARK: - Actions
func tapCustomizeTab() {
let segment = customizeSegment
_ = segment.waitForExistence(timeout: 5)
segment.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
}
func tapSettingsTab() {
// Find the "Settings" segment in the segmented control (not the tab bar button).
// Try segmentedControls first, then fall back to finding by exclusion.
let segCtrl = app.segmentedControls.buttons["Settings"]
if segCtrl.waitForExistence(timeout: 3) {
segCtrl.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
return
}
// Fallback: find a "Settings" button that is NOT the tab bar button
let candidates = app.buttons.matching(NSPredicate(format: "label == 'Settings'")).allElementsBoundByIndex
let tabBarBtn = app.tabBars.buttons["Settings"]
for candidate in candidates where candidate.frame != tabBarBtn.frame {
candidate.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
return
}
}
func tapClearData() {
let button = clearDataButton
if button.exists && !button.isHittable {
app.swipeUp()
}
_ = button.waitForExistence(timeout: 5)
button.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
}
func tapAnalyticsToggle() {
let toggle = analyticsToggle
if toggle.exists && !toggle.isHittable {
app.swipeUp()
}
_ = toggle.waitForExistence(timeout: 5)
toggle.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
}
// MARK: - Assertions
func assertVisible(file: StaticString = #file, line: UInt = #line) {
XCTAssertTrue(
settingsHeader.waitForExistence(timeout: 5),
"Settings header should be visible",
file: file, line: line
)
}
func assertUpgradeBannerVisible(file: StaticString = #file, line: UInt = #line) {
XCTAssertTrue(
upgradeBanner.waitForExistence(timeout: 5),
"Upgrade banner should be visible",
file: file, line: line
)
}
func assertUpgradeBannerHidden(file: StaticString = #file, line: UInt = #line) {
XCTAssertTrue(
upgradeBanner.waitForDisappearance(timeout: 5),
"Upgrade banner should be hidden (subscribed)",
file: file, line: line
)
}
}