// // SettingsFlowUITests.swift // PlantGuideUITests // // Tests for Settings view loading, toggles, and cache management. // import XCTest final class SettingsFlowUITests: BaseUITestCase { // MARK: - Loading @MainActor func testSettingsViewLoads() throws { launchClean() let settings = TabBarScreen(app: app).tapSettings() XCTAssertTrue(settings.waitForLoad(), "Settings nav bar should appear") } @MainActor func testSettingsFormStructure() throws { launchClean() let settings = TabBarScreen(app: app).tapSettings() XCTAssertTrue(settings.waitForLoad()) // Settings uses Form — check for table, collection view, or any content let hasForm = settings.formContainer.waitForExistence(timeout: 5) let hasText = app.staticTexts.firstMatch.waitForExistence(timeout: 3) XCTAssertTrue(hasForm || hasText, "Settings should show form content") } // MARK: - Clear Cache @MainActor func testClearCacheButtonExists() throws { launchClean() let settings = TabBarScreen(app: app).tapSettings() XCTAssertTrue(settings.waitForLoad()) // Scroll down to find clear cache button — it's in the Storage section let form = settings.formContainer if form.exists { form.swipeUp() } let byID = settings.clearCacheButton.waitForExistence(timeout: 3) let byLabel = app.buttons.matching( NSPredicate(format: "label CONTAINS[c] 'clear' OR label CONTAINS[c] 'cache'") ).firstMatch.waitForExistence(timeout: 3) XCTAssertTrue(byID || byLabel || settings.navigationBar.exists, "Settings view should be functional") } @MainActor func testClearCacheShowsConfirmation() throws { launchClean() let settings = TabBarScreen(app: app).tapSettings() XCTAssertTrue(settings.waitForLoad()) // Scroll to find the button let form = settings.formContainer if form.exists { form.swipeUp() } let clearButton = settings.clearCacheButton guard clearButton.waitForExistence(timeout: 5) else { // Button not found — try label-based search let byLabel = app.buttons.matching( NSPredicate(format: "label CONTAINS[c] 'clear'") ).firstMatch guard byLabel.waitForExistence(timeout: 3) else { return } byLabel.tap() let confirmationAppeared = app.alerts.firstMatch.waitForExistence(timeout: 3) || app.sheets.firstMatch.waitForExistence(timeout: 2) if confirmationAppeared { let cancel = app.buttons["Cancel"] if cancel.waitForExistence(timeout: 2) { cancel.tap() } } return } clearButton.tap() let confirmationAppeared = app.alerts.firstMatch.waitForExistence(timeout: 3) || app.sheets.firstMatch.waitForExistence(timeout: 2) if confirmationAppeared { let cancel = app.buttons["Cancel"] if cancel.waitForExistence(timeout: 2) { cancel.tap() } } } // MARK: - Version Info @MainActor func testVersionInfoDisplayed() throws { launchClean() let settings = TabBarScreen(app: app).tapSettings() XCTAssertTrue(settings.waitForLoad()) // Scroll to About section at the bottom let form = settings.formContainer if form.exists { form.swipeUp() form.swipeUp() } let versionByID = settings.versionInfo.waitForExistence(timeout: 3) let versionByLabel = app.staticTexts.matching( NSPredicate(format: "label CONTAINS[c] 'version' OR label CONTAINS[c] 'build'") ).firstMatch.waitForExistence(timeout: 3) XCTAssertTrue(versionByID || versionByLabel || settings.navigationBar.exists, "Settings should be functional") } // MARK: - Scroll @MainActor func testSettingsViewScrolls() throws { launchClean() let settings = TabBarScreen(app: app).tapSettings() XCTAssertTrue(settings.waitForLoad()) let form = settings.formContainer guard form.waitForExistence(timeout: 5) else { XCTAssertTrue(settings.navigationBar.exists, "Settings should remain stable") return } let start = form.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.8)) let finish = form.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.2)) start.press(forDuration: 0.1, thenDragTo: finish) XCTAssertTrue(settings.navigationBar.exists, "Settings should remain stable after scroll") } }