// // DayScreen.swift // Tests iOS // // Screen object for the Day (main) view — mood logging and entry list. // import XCTest struct DayScreen { let app: XCUIApplication private let defaultTimeout: TimeInterval = 2 private let navigationTimeout: TimeInterval = 5 // MARK: - Elements var moodHeader: XCUIElement { app.element(UITestID.Day.moodHeader) } func moodButton(for mood: MoodChoice) -> XCUIElement { app.buttons["mood_button_\(mood.rawValue)"] } func entryRow(dateString: String) -> XCUIElement { app.element("\(UITestID.Day.entryRowPrefix)\(dateString)") } var anyEntryRow: XCUIElement { app.firstEntryRow } // MARK: - Actions @discardableResult func logMood(_ mood: MoodChoice, file: StaticString = #filePath, line: UInt = #line) -> DayScreen { moodButton(for: mood) .waitUntilHittableOrFail(timeout: defaultTimeout, message: "Mood button '\(mood.rawValue)' not hittable", file: file, line: line) .forceTap(file: file, line: line) moodHeader.waitForNonExistence(timeout: navigationTimeout, message: "Mood header should disappear after logging", file: file, line: line) return self } // MARK: - Assertions @discardableResult func assertVisible(file: StaticString = #filePath, line: UInt = #line) -> DayScreen { // Day view shows mood header (empty state) OR entry rows (has data) — either proves it loaded let hasHeader = moodHeader.waitForExistence(timeout: navigationTimeout) let hasEntry = !hasHeader && anyEntryRow.waitForExistence(timeout: defaultTimeout) if !hasHeader && !hasEntry { XCTFail("Day screen should show mood header or entry list", file: file, line: line) } return self } func assertMoodHeaderHidden(file: StaticString = #filePath, line: UInt = #line) { moodHeader.waitForNonExistence(timeout: navigationTimeout, message: "Mood header should be hidden after logging", file: file, line: line) } func assertEntryExists(dateString: String, file: StaticString = #filePath, line: UInt = #line) { entryRow(dateString: dateString) .waitForExistenceOrFail(timeout: defaultTimeout, message: "Entry row for \(dateString) should exist", file: file, line: line) } func assertAnyEntryExists(file: StaticString = #filePath, line: UInt = #line) { anyEntryRow .waitForExistenceOrFail(timeout: defaultTimeout, message: "At least one entry row should exist", file: file, line: line) } } /// Represents the 5 selectable mood values for test code. enum MoodChoice: String { case great, good, average, bad, horrible }