// // SettingsActionTests.swift // Tests iOS // // Settings actions: clear data, analytics toggle. // import XCTest final class SettingsActionTests: BaseUITestCase { override var seedFixture: String? { "week_of_moods" } override var bypassSubscription: Bool { true } /// TC-063 / TC-160: Navigate to Settings, clear all data, verify entries are gone. func testClearData_RemovesAllEntries() { // First verify we have data let dayScreen = DayScreen(app: app) let entryRow = app.descendants(matching: .any) .matching(NSPredicate(format: "identifier BEGINSWITH %@", "entry_row_")) .firstMatch XCTAssertTrue( entryRow.waitForExistence(timeout: 5), "Entry rows should exist before clearing" ) // Navigate to Settings tab let tabBar = TabBarScreen(app: app) let settingsScreen = tabBar.tapSettings() settingsScreen.assertVisible() // Switch to Settings sub-tab (not Customize) settingsScreen.tapSettingsTab() // Scroll down to find Clear All Data (it's in the DEBUG section at the bottom) let clearButton = app.descendants(matching: .any) .matching(identifier: "settings_clear_data") .firstMatch // May need multiple swipes — button is at the very bottom of Settings for _ in 0..<4 { if clearButton.waitForExistence(timeout: 1) { break } app.swipeUp() } guard clearButton.waitForExistence(timeout: 5) else { // In non-DEBUG builds, clear data might not be visible // Skip test gracefully return } clearButton.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap() // Navigate back to Day tab tabBar.tapDay() // Verify entries are gone — use descendants to match any element type let moodHeader = app.descendants(matching: .any) .matching(identifier: "mood_header") .firstMatch let noData = app.descendants(matching: .any) .matching(identifier: "empty_state_no_data") .firstMatch let headerAppeared = moodHeader.waitForExistence(timeout: 5) let noDataAppeared = noData.waitForExistence(timeout: 2) // Also verify that no entry rows exist let staleEntry = app.descendants(matching: .any) .matching(NSPredicate(format: "identifier BEGINSWITH %@", "entry_row_")) .firstMatch let entriesGone = !staleEntry.waitForExistence(timeout: 2) XCTAssertTrue( headerAppeared || noDataAppeared || entriesGone, "After clearing data, empty state should show or entries should be gone" ) captureScreenshot(name: "data_cleared") } /// TC-067: Toggle analytics opt-out. func testAnalyticsToggle_Tappable() { let tabBar = TabBarScreen(app: app) let settingsScreen = tabBar.tapSettings() settingsScreen.assertVisible() // Switch to Settings sub-tab settingsScreen.tapSettingsTab() // Find the analytics toggle let analyticsToggle = app.descendants(matching: .any) .matching(identifier: "settings_analytics_toggle") .firstMatch // May need to scroll to find it if !analyticsToggle.waitForExistence(timeout: 3) { app.swipeUp() app.swipeUp() } guard analyticsToggle.waitForExistence(timeout: 5) else { // Toggle may not be visible depending on scroll position captureScreenshot(name: "analytics_toggle_not_found") return } // Tap the toggle analyticsToggle.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap() captureScreenshot(name: "analytics_toggled") } }