176 lines
6.1 KiB
Swift
176 lines
6.1 KiB
Swift
//
|
|
// AndromidaUITests.swift
|
|
// AndromidaUITests
|
|
//
|
|
// Created by Matt Bruce on 1/25/26.
|
|
//
|
|
|
|
import XCTest
|
|
|
|
final class AndromidaUITests: XCTestCase {
|
|
|
|
override func setUpWithError() throws {
|
|
continueAfterFailure = false
|
|
}
|
|
|
|
@MainActor
|
|
func testOnboardingFlowCompletes() throws {
|
|
let onboardingApp = makeApp(resetDefaults: true, hasCompletedSetupWizard: false)
|
|
onboardingApp.launch()
|
|
|
|
let getStarted = onboardingApp.buttons["onboarding.getStarted"]
|
|
XCTAssertTrue(getStarted.waitForExistence(timeout: 8))
|
|
|
|
onboardingApp.terminate()
|
|
|
|
let completedApp = makeApp(resetDefaults: false, hasCompletedSetupWizard: true)
|
|
completedApp.launch()
|
|
|
|
let ritualsTab = completedApp.tabBars.buttons["Rituals"]
|
|
XCTAssertTrue(ritualsTab.waitForExistence(timeout: 8))
|
|
}
|
|
|
|
@MainActor
|
|
func testOnboardingHappyPath() throws {
|
|
let app = makeApp(resetDefaults: true, hasCompletedSetupWizard: false)
|
|
app.launch()
|
|
|
|
XCTAssertTrue(app.buttons["onboarding.getStarted"].waitForExistence(timeout: 8))
|
|
app.buttons["onboarding.getStarted"].tap()
|
|
|
|
tapFirstAvailableElement(
|
|
app: app,
|
|
identifiers: ["onboarding.goal.health"],
|
|
fallbackLabels: ["Health"]
|
|
)
|
|
XCTAssertTrue(app.buttons["onboarding.goalContinue"].waitForExistence(timeout: 8))
|
|
app.buttons["onboarding.goalContinue"].tap()
|
|
|
|
tapFirstAvailableElement(
|
|
app: app,
|
|
identifiers: ["onboarding.time.morning"],
|
|
fallbackLabels: ["Morning"]
|
|
)
|
|
XCTAssertTrue(app.buttons["onboarding.timeContinue"].waitForExistence(timeout: 8))
|
|
app.buttons["onboarding.timeContinue"].tap()
|
|
|
|
if app.buttons["onboarding.startRitual"].waitForExistence(timeout: 8) {
|
|
app.buttons["onboarding.startRitual"].tap()
|
|
} else {
|
|
XCTAssertTrue(app.buttons["onboarding.skipRitual"].waitForExistence(timeout: 8))
|
|
app.buttons["onboarding.skipRitual"].tap()
|
|
}
|
|
|
|
if app.buttons["onboarding.firstCheckInSkip"].waitForExistence(timeout: 8) {
|
|
app.buttons["onboarding.firstCheckInSkip"].tap()
|
|
} else {
|
|
XCTAssertTrue(app.buttons["onboarding.firstCheckInContinueToRituals"].waitForExistence(timeout: 8))
|
|
app.buttons["onboarding.firstCheckInContinueToRituals"].tap()
|
|
}
|
|
|
|
XCTAssertTrue(app.buttons["onboarding.notificationsMaybeLater"].waitForExistence(timeout: 8))
|
|
app.buttons["onboarding.notificationsMaybeLater"].tap()
|
|
|
|
XCTAssertTrue(app.buttons["onboarding.letsGo"].waitForExistence(timeout: 8))
|
|
app.buttons["onboarding.letsGo"].tap()
|
|
|
|
XCTAssertTrue(app.tabBars.buttons["Rituals"].waitForExistence(timeout: 8))
|
|
}
|
|
|
|
@MainActor
|
|
func testCreateRitualFromRitualsTab() throws {
|
|
let app = makeApp(resetDefaults: true, hasCompletedSetupWizard: true)
|
|
app.launch()
|
|
|
|
let ritualsTab = app.tabBars.buttons["Rituals"]
|
|
XCTAssertTrue(ritualsTab.waitForExistence(timeout: 8))
|
|
ritualsTab.tap()
|
|
|
|
let addMenu = app.buttons["rituals.addMenu"]
|
|
XCTAssertTrue(addMenu.waitForExistence(timeout: 8))
|
|
addMenu.tap()
|
|
|
|
let createNew = app.buttons["rituals.createNew"]
|
|
XCTAssertTrue(createNew.waitForExistence(timeout: 8))
|
|
createNew.tap()
|
|
|
|
let titleField = app.textFields["ritualEditor.titleField"]
|
|
XCTAssertTrue(titleField.waitForExistence(timeout: 8))
|
|
titleField.tap()
|
|
titleField.typeText("UI Test Ritual")
|
|
|
|
let themeField = app.textFields["ritualEditor.themeField"]
|
|
XCTAssertTrue(themeField.waitForExistence(timeout: 8))
|
|
themeField.tap()
|
|
themeField.typeText("Daily focus")
|
|
|
|
let newHabitField = app.textFields["ritualEditor.newHabitField"]
|
|
XCTAssertTrue(newHabitField.waitForExistence(timeout: 8))
|
|
newHabitField.tap()
|
|
newHabitField.typeText("Stretch")
|
|
|
|
let addHabitButton = app.buttons["ritualEditor.addHabitButton"]
|
|
XCTAssertTrue(addHabitButton.waitForExistence(timeout: 8))
|
|
addHabitButton.tap()
|
|
|
|
let saveButton = app.buttons["ritualEditor.saveButton"]
|
|
XCTAssertTrue(saveButton.waitForExistence(timeout: 8))
|
|
saveButton.tap()
|
|
|
|
XCTAssertTrue(app.staticTexts["UI Test Ritual"].waitForExistence(timeout: 8))
|
|
}
|
|
|
|
@MainActor
|
|
func testLaunchPerformance() throws {
|
|
let app = makeApp(resetDefaults: true, hasCompletedSetupWizard: true)
|
|
measure(metrics: [XCTApplicationLaunchMetric()]) {
|
|
app.launch()
|
|
app.terminate()
|
|
}
|
|
}
|
|
|
|
private func makeApp(resetDefaults: Bool, hasCompletedSetupWizard: Bool) -> XCUIApplication {
|
|
let app = XCUIApplication()
|
|
app.launchEnvironment["UITEST_MODE"] = "1"
|
|
if resetDefaults {
|
|
app.launchEnvironment["UITEST_RESET_USER_DEFAULTS"] = "1"
|
|
}
|
|
app.launchEnvironment["UITEST_HAS_COMPLETED_SETUP_WIZARD"] = hasCompletedSetupWizard ? "1" : "0"
|
|
return app
|
|
}
|
|
|
|
private func tapFirstAvailableElement(
|
|
app: XCUIApplication,
|
|
identifiers: [String],
|
|
fallbackLabels: [String],
|
|
timeout: TimeInterval = 8
|
|
) {
|
|
for identifier in identifiers {
|
|
let candidates = [
|
|
app.buttons[identifier],
|
|
app.otherElements[identifier],
|
|
app.staticTexts[identifier],
|
|
app.descendants(matching: .any)[identifier]
|
|
]
|
|
for element in candidates where element.waitForExistence(timeout: 1) {
|
|
element.tap()
|
|
return
|
|
}
|
|
}
|
|
|
|
for label in fallbackLabels {
|
|
let candidates = [
|
|
app.buttons[label],
|
|
app.otherElements[label],
|
|
app.staticTexts[label]
|
|
]
|
|
for element in candidates where element.waitForExistence(timeout: timeout) {
|
|
element.tap()
|
|
return
|
|
}
|
|
}
|
|
|
|
XCTFail("Unable to locate tap target. identifiers=\(identifiers), labels=\(fallbackLabels)")
|
|
}
|
|
}
|