From 96ffeaa0e22a67165d08fb5b833c2ab76a8feccd Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Thu, 22 Oct 2026 17:11:21 +0200 Subject: [PATCH] ci: pick a photo in the ios compose flow, settle settings rows before tapping, answer prompts in portrait and tap undo sooner --- .maestro/features/02-read-messages.yaml | 4 +- .maestro/features/03-compose-send.yaml | 76 +++++++++++++--------- .maestro/features/06-swipe-undo.yaml | 5 +- .maestro/features/07-move-delete-tag.yaml | 23 +++++-- .maestro/features/09-calendar.yaml | 8 +-- .maestro/subflows/allow-notifications.yaml | 11 +++- .maestro/subflows/settings-page.yaml | 38 +++++++++++ .maestro/subflows/signed-in.yaml | 11 ++-- 8 files changed, 126 insertions(+), 50 deletions(-) diff --git a/.maestro/features/02-read-messages.yaml b/.maestro/features/02-read-messages.yaml index 2b3002cb..b7be998e 100644 --- a/.maestro/features/02-read-messages.yaml +++ b/.maestro/features/02-read-messages.yaml @@ -44,7 +44,9 @@ tags: visible: ".*q3-report.pdf.*" timeout: 20000 - takeScreenshot: read-04-attachment -- tapOn: ".*q3-report.pdf.*" +# The message's attachment chip (name and size); on the iPad the list row +# next to it shows the name too. +- tapOn: ".*q3-report.pdf.*[0-9]+ B.*" - extendedWaitUntil: visible: "Share" timeout: 30000 diff --git a/.maestro/features/03-compose-send.yaml b/.maestro/features/03-compose-send.yaml index 85a9ef89..0e4a8320 100644 --- a/.maestro/features/03-compose-send.yaml +++ b/.maestro/features/03-compose-send.yaml @@ -25,9 +25,7 @@ tags: - takeScreenshot: compose-01-filled # The attach sheet offers its options one by one (it used to be a single -# accessibility element). The system photo and file pickers run in another -# process that XCTest can't drive, so a picked attachment is covered by the -# forward in 04-incoming-reply-forward instead. +# accessibility element, and picking one opened no picker on iOS). - tapOn: "Attach" - extendedWaitUntil: visible: "Photos & Videos" @@ -35,41 +33,54 @@ tags: - assertVisible: "Camera" - assertVisible: "Files" - takeScreenshot: compose-02-attach-sheet -- tapOn: "Photos & Videos" -# The system photo picker (another process) opens over the composer. -# (Optional until we know what XCTest sees of it; the screenshot shows it.) -- extendedWaitUntil: - notVisible: "Draft saved|New Message" - timeout: 10000 - optional: true -- waitForAnimationToEnd: - timeout: 5000 -- takeScreenshot: compose-03-photo-picker -# Close it: its Cancel button if XCTest sees it, else swipe the sheet down. +- evalScript: ${output.pickPhoto = ORIENTATION != 'landscape'} +# The system photo picker runs in another process: XCTest sees none of its +# elements, but taps by position reach it. Pick the first photo (the app +# icon, added by boot-sim.sh) and confirm with the check mark. The iPad in +# landscape lays the picker out differently, so it only closes the sheet. - runFlow: when: - visible: "Cancel" + true: ${!output.pickPhoto} commands: - tapOn: "Cancel" - runFlow: when: - notVisible: "New Message" + true: ${output.pickPhoto} commands: - - swipe: - start: 50%,12% - end: 50%,95% - duration: 400 -- waitForAnimationToEnd: - timeout: 3000 -# A swipe too many closes the composer: keep it. -- runFlow: - when: - visible: "Save or discard draft?" - commands: - - tapOn: "Cancel" + - tapOn: "Photos & Videos" + - extendedWaitUntil: + notVisible: "Draft saved|New Message" + timeout: 10000 + optional: true + - waitForAnimationToEnd: + timeout: 5000 + - takeScreenshot: compose-03-photo-picker + - runFlow: + when: + true: ${DEVICE == 'tablet'} + commands: + - tapOn: + point: "44%,33%" + - waitForAnimationToEnd: + timeout: 2000 + - tapOn: + point: "90%,26%" + - runFlow: + when: + true: ${DEVICE != 'tablet'} + commands: + - tapOn: + point: "16%,25%" + - waitForAnimationToEnd: + timeout: 2000 + - tapOn: + point: "90%,13%" - extendedWaitUntil: visible: "New Message" - timeout: 10000 + timeout: 20000 +- waitForAnimationToEnd: + timeout: 5000 +- takeScreenshot: compose-04-with-photo - tapOn: "Send" - extendedWaitUntil: @@ -80,3 +91,10 @@ tags: file: ../subflows/assert-delivered.yaml env: SUBJECT: ${output.subject} +- runFlow: + when: + true: ${output.pickPhoto} + commands: + - assertTrue: + condition: ${output.helper.attachments.length >= 1} + label: "${output.subject} carries the picked photo" diff --git a/.maestro/features/06-swipe-undo.yaml b/.maestro/features/06-swipe-undo.yaml index b2d147dc..ff5159a8 100644 --- a/.maestro/features/06-swipe-undo.yaml +++ b/.maestro/features/06-swipe-undo.yaml @@ -20,7 +20,10 @@ tags: timeout: 10000 - takeScreenshot: swipe-01-archived - assertNotVisible: ".*Grüße aus München.*" -- tapOn: "UNDO" +- tapOn: + text: "UNDO" + # The undo bar shows for 5 s: don't spend them waiting for the screen to settle. + waitToSettleTimeoutMs: 500 - extendedWaitUntil: visible: ".*Grüße aus München.*" timeout: 15000 diff --git a/.maestro/features/07-move-delete-tag.yaml b/.maestro/features/07-move-delete-tag.yaml index 666cd7ed..d55e23ac 100644 --- a/.maestro/features/07-move-delete-tag.yaml +++ b/.maestro/features/07-move-delete-tag.yaml @@ -21,12 +21,18 @@ tags: - extendedWaitUntil: visible: "Move to..." timeout: 10000 -- tapOn: "Projects" +- tapOn: + text: "Projects" + # The undo bar shows for 5 s: don't spend them waiting for the screen to settle. + waitToSettleTimeoutMs: 500 - extendedWaitUntil: visible: "Moved to Projects" timeout: 15000 - takeScreenshot: actions-02-moved -- tapOn: "UNDO" +- tapOn: + text: "UNDO" + # The undo bar shows for 5 s: don't spend them waiting for the screen to settle. + waitToSettleTimeoutMs: 500 - runFlow: ../subflows/close-message.yaml - extendedWaitUntil: visible: ".*Weekly digest.*" @@ -38,15 +44,18 @@ tags: env: SUBJECT: Weekly digest - takeScreenshot: actions-03a-before-delete -- tapOn: "Delete" -- waitForAnimationToEnd: - timeout: 3000 -- takeScreenshot: actions-03b-after-delete +- tapOn: + text: "Delete" + # The undo bar shows for 5 s: don't spend them waiting for the screen to settle. + waitToSettleTimeoutMs: 500 - extendedWaitUntil: visible: "Email moved to Trash" timeout: 15000 - takeScreenshot: actions-03-deleted -- tapOn: "UNDO" +- tapOn: + text: "UNDO" + # The undo bar shows for 5 s: don't spend them waiting for the screen to settle. + waitToSettleTimeoutMs: 500 - runFlow: ../subflows/close-message.yaml - extendedWaitUntil: visible: ".*Weekly digest.*" diff --git a/.maestro/features/09-calendar.yaml b/.maestro/features/09-calendar.yaml index 259e631a..a975fd1e 100644 --- a/.maestro/features/09-calendar.yaml +++ b/.maestro/features/09-calendar.yaml @@ -12,13 +12,7 @@ tags: - extendedWaitUntil: visible: ".*Would Like to Send You Notifications.*|Go to today" timeout: 30000 -- runFlow: - when: - visible: ".*Would Like to Send You Notifications.*" - commands: - - tapOn: - text: "Allow" - optional: true +- runFlow: ../subflows/allow-notifications.yaml - extendedWaitUntil: visible: "Go to today" timeout: 30000 diff --git a/.maestro/subflows/allow-notifications.yaml b/.maestro/subflows/allow-notifications.yaml index 914fe45f..154ee098 100644 --- a/.maestro/subflows/allow-notifications.yaml +++ b/.maestro/subflows/allow-notifications.yaml @@ -1,12 +1,21 @@ # The app asks for notification permission now and then (calendar # reminders, push). The system alert covers the whole app, so XCTest sees -# nothing else until it is answered: allow it when it is up. +# nothing else until it is answered: allow it when it is up. Taps on system +# alerts miss in landscape, so answer it in portrait. appId: org.bulwarkmail.mobile --- - runFlow: when: visible: ".*Would Like to Send You Notifications.*" commands: + - setOrientation: PORTRAIT + - waitForAnimationToEnd: + timeout: 3000 - tapOn: text: "Allow" optional: true + - runFlow: + when: + true: ${ORIENTATION == 'landscape'} + commands: + - setOrientation: LANDSCAPE_LEFT diff --git a/.maestro/subflows/settings-page.yaml b/.maestro/subflows/settings-page.yaml index 7b4c8800..fe46f5a9 100644 --- a/.maestro/subflows/settings-page.yaml +++ b/.maestro/subflows/settings-page.yaml @@ -4,6 +4,7 @@ # (Swipe coordinates have to be literals.) appId: org.bulwarkmail.mobile --- +- evalScript: ${output.swiped = false} - runFlow: when: true: ${DEVICE == 'tablet'} @@ -17,6 +18,17 @@ appId: org.bulwarkmail.mobile start: 18%,80% end: 18%,40% duration: 600 + - evalScript: ${output.swiped = true} + # The row counts as visible as soon as its top edge shows: one more + # short scroll brings all of it on screen, so the tap lands on it. + - runFlow: + when: + true: ${output.swiped} + commands: + - swipe: + start: 18%,70% + end: 18%,55% + duration: 600 - runFlow: when: true: ${DEVICE != 'tablet'} @@ -30,9 +42,35 @@ appId: org.bulwarkmail.mobile start: 50%,80% end: 50%,40% duration: 600 + - evalScript: ${output.swiped = true} + - runFlow: + when: + true: ${output.swiped} + commands: + - swipe: + start: 50%,70% + end: 50%,55% + duration: 600 +# A tap while the list still coasts from the swipe only stops it. +- waitForAnimationToEnd: + timeout: 5000 - tapOn: ${ROW} - waitForAnimationToEnd: timeout: 5000 +# On the phone the page replaces the list: make sure it opened before +# scrolling (else the swipes below scroll the list away). +- runFlow: + when: + true: ${DEVICE != 'tablet'} + commands: + - runFlow: + when: + notVisible: "Back" + commands: + - tapOn: ${ROW} + - extendedWaitUntil: + visible: "Back" + timeout: 10000 # PROOF can be further down the page: scroll the page (the right-hand pane # on the iPad) until it shows. - runFlow: diff --git a/.maestro/subflows/signed-in.yaml b/.maestro/subflows/signed-in.yaml index a56209c8..d0834467 100644 --- a/.maestro/subflows/signed-in.yaml +++ b/.maestro/subflows/signed-in.yaml @@ -7,15 +7,18 @@ appId: org.bulwarkmail.mobile notifications: allow photos: allow camera: allow +# Answer the notification prompt (if the app asks) before turning to +# landscape: rotated, taps on system alerts miss. +- setOrientation: PORTRAIT +- extendedWaitUntil: + visible: "Enter server details manually|Inbox|.*Would Like to Send You Notifications.*" + timeout: 120000 +- runFlow: allow-notifications.yaml - runFlow: when: true: ${ORIENTATION == 'landscape'} commands: - setOrientation: LANDSCAPE_LEFT -- extendedWaitUntil: - visible: "Enter server details manually|Inbox|.*Would Like to Send You Notifications.*" - timeout: 120000 -- runFlow: allow-notifications.yaml - extendedWaitUntil: visible: "Enter server details manually|Inbox" timeout: 30000