ci: pick a photo in the ios compose flow, settle settings rows before tapping, answer prompts in portrait and tap undo sooner

This commit is contained in:
Linus Rath
2026-10-22 17:11:21 +02:00
parent 81a0723abd
commit 96ffeaa0e2
8 changed files with 126 additions and 50 deletions
+3 -1
View File
@@ -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
+47 -29
View File
@@ -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"
+4 -1
View File
@@ -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
+16 -7
View File
@@ -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.*"
+1 -7
View File
@@ -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
+10 -1
View File
@@ -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
+38
View File
@@ -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:
+7 -4
View File
@@ -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