// // EntryDetailScreen.swift // Tests iOS // // Screen object for the Entry Detail sheet (edit mood, notes, delete). // import XCTest struct EntryDetailScreen { let app: XCUIApplication // MARK: - Elements var sheet: XCUIElement { app.element(UITestID.EntryDetail.sheet) } var doneButton: XCUIElement { app.element(UITestID.EntryDetail.doneButton) } var deleteButton: XCUIElement { app.element(UITestID.EntryDetail.deleteButton) } var moodGrid: XCUIElement { app.otherElements["entry_detail_mood_grid"] } /// Mood buttons inside the detail sheet's mood grid. /// Match by the mood_button_ identifier prefix to avoid matching entry rows. func moodButton(for mood: MoodChoice) -> XCUIElement { app.buttons["mood_button_\(mood.rawValue)"] } // MARK: - Actions func dismiss() { let button = doneButton button.tapWhenReady(timeout: 5) } func selectMood(_ mood: MoodChoice) { let button = moodButton(for: mood) button.tapWhenReady(timeout: 5) } func deleteEntry() { let button = deleteButton // Scroll down to reveal delete button (may be off-screen below reflection/notes/photo sections) if button.waitForExistence(timeout: 3) && !button.isHittable { sheet.swipeUp() } button.tapWhenReady(timeout: 5) let alert = app.alerts.firstMatch guard alert.waitForExistence(timeout: 5) else { return } let deleteButton = alert.buttons.matching(NSPredicate(format: "label CONTAINS[cd] %@", "Delete")).firstMatch if deleteButton.waitForExistence(timeout: 2) { deleteButton.tapWhenReady() return } // Fallback: destructive action is usually the last button. let fallback = alert.buttons.element(boundBy: max(alert.buttons.count - 1, 0)) if fallback.exists { fallback.tapWhenReady() } } // MARK: - Assertions func assertVisible(file: StaticString = #file, line: UInt = #line) { XCTAssertTrue( sheet.waitForExistence(timeout: 5), "Entry Detail sheet should be visible", file: file, line: line ) } func assertDismissed(file: StaticString = #file, line: UInt = #line) { XCTAssertTrue( sheet.waitForDisappearance(timeout: 5), "Entry Detail sheet should be dismissed", file: file, line: line ) } }