mirror of
https://github.com/bulwarkmail/native.git
synced 2026-10-31 16:06:32 +00:00
Merge branch 'cu-e2e' into catch-up-2026-11
This commit is contained in:
@@ -32,7 +32,9 @@ tags:
|
||||
visible: "Photos & Videos"
|
||||
timeout: 10000
|
||||
- assertVisible: "Camera"
|
||||
- assertVisible: "Files"
|
||||
# A server with Files offers "Upload from this device" and "Attach from
|
||||
# Files" instead of a plain "Files".
|
||||
- assertVisible: "Upload from this device|Files"
|
||||
- takeScreenshot: compose-02-attach-sheet
|
||||
- evalScript: ${output.pickPhoto = ORIENTATION != 'landscape'}
|
||||
# The system photo picker runs in another process: XCTest sees none of its
|
||||
|
||||
@@ -11,8 +11,12 @@ tags:
|
||||
direction: DOWN
|
||||
centerElement: true
|
||||
timeout: 20000
|
||||
# Swipe the row itself: the avatar checkbox's label has the subject too, and
|
||||
# a swipe that starts on it only selects the row (#91).
|
||||
- swipe:
|
||||
from: ".*Grüße aus München.*"
|
||||
from:
|
||||
id: email-row
|
||||
text: ".*Grüße aus München.*"
|
||||
direction: LEFT
|
||||
duration: 400
|
||||
# The undo bar shows for 5 s; when it goes, the Compose button slides into
|
||||
@@ -27,14 +31,18 @@ tags:
|
||||
- takeScreenshot: swipe-02-undone
|
||||
|
||||
- swipe:
|
||||
from: ".*Grüße aus München.*"
|
||||
from:
|
||||
id: email-row
|
||||
text: ".*Grüße aus München.*"
|
||||
direction: RIGHT
|
||||
duration: 400
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
- takeScreenshot: swipe-03-read-toggled
|
||||
- swipe:
|
||||
from: ".*Grüße aus München.*"
|
||||
from:
|
||||
id: email-row
|
||||
text: ".*Grüße aus München.*"
|
||||
direction: RIGHT
|
||||
duration: 400
|
||||
- waitForAnimationToEnd:
|
||||
|
||||
@@ -63,7 +63,10 @@ tags:
|
||||
direction: DOWN
|
||||
centerElement: true
|
||||
timeout: 20000
|
||||
- longPressOn: ".*Grüße aus München.*"
|
||||
# The row, not its avatar checkbox (whose label has the subject too).
|
||||
- longPressOn:
|
||||
id: email-row
|
||||
text: ".*Grüße aus München.*"
|
||||
- extendedWaitUntil:
|
||||
visible: "Clear selection"
|
||||
timeout: 10000
|
||||
@@ -76,7 +79,9 @@ tags:
|
||||
visible: "Clear selection"
|
||||
commands:
|
||||
- tapOn: "Clear selection"
|
||||
- longPressOn: ".*Grüße aus München.*"
|
||||
- longPressOn:
|
||||
id: email-row
|
||||
text: ".*Grüße aus München.*"
|
||||
- tapOn: "Unstar|Star"
|
||||
- runFlow:
|
||||
when:
|
||||
|
||||
@@ -48,9 +48,11 @@ tags:
|
||||
- extendedWaitUntil:
|
||||
visible: "Keep scheduled"
|
||||
timeout: 10000
|
||||
# The dialog's button (below its message), not its title or the button
|
||||
# behind it. Cancelling now moves the message back to Drafts.
|
||||
- tapOn:
|
||||
text: "Cancel send"
|
||||
below: "Keep scheduled|.*will not be delivered.*"
|
||||
below: ".*will not be (sent|delivered).*"
|
||||
- extendedWaitUntil:
|
||||
notVisible: ".*${output.subject}.*"
|
||||
timeout: 30000
|
||||
|
||||
@@ -34,7 +34,12 @@ tags:
|
||||
timeout: 5000
|
||||
- takeScreenshot: calendar-04-week
|
||||
|
||||
# Create
|
||||
# Create. The button starts the event on the selected day: make that today
|
||||
# (a stray tap, such as one through the notification prompt, can select
|
||||
# another day), so the schedule below finds it after Go to today.
|
||||
- tapOn: "Go to today"
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
- tapOn: "New event"
|
||||
- extendedWaitUntil:
|
||||
visible: "Save"
|
||||
@@ -46,6 +51,19 @@ tags:
|
||||
- pressKey: Enter
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
# A new event starts on the calendar's default reminders; Customize turns
|
||||
# them into the event's own list, which has Add reminder.
|
||||
- scrollUntilVisible:
|
||||
element: "Customize|Add reminder"
|
||||
direction: DOWN
|
||||
timeout: 10000
|
||||
- runFlow:
|
||||
when:
|
||||
visible: "Customize"
|
||||
commands:
|
||||
- tapOn: "Customize"
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
- scrollUntilVisible:
|
||||
element: "Add reminder"
|
||||
direction: DOWN
|
||||
|
||||
@@ -44,20 +44,22 @@ tags:
|
||||
timeout: 20000
|
||||
- takeScreenshot: files-04-folder-created
|
||||
- longPressOn: ".*${output.folder}.*"
|
||||
# Delete moves it to the trash at once, with Undo and no question (like the
|
||||
# webmail). A tap while the actions sheet still slides in can miss: tap
|
||||
# again while Delete is still there.
|
||||
- extendedWaitUntil:
|
||||
visible: "Delete"
|
||||
timeout: 10000
|
||||
- repeat:
|
||||
while:
|
||||
notVisible: "Delete this item.*"
|
||||
visible: "Delete"
|
||||
times: 3
|
||||
commands:
|
||||
- tapOn: "Delete"
|
||||
- tapOn:
|
||||
text: "Delete"
|
||||
optional: true
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
- extendedWaitUntil:
|
||||
visible: "Delete this item.*"
|
||||
timeout: 10000
|
||||
- tapOn:
|
||||
text: "Delete"
|
||||
below: "Delete this item.*"
|
||||
- extendedWaitUntil:
|
||||
notVisible: ".*${output.folder}.*"
|
||||
timeout: 20000
|
||||
|
||||
@@ -11,6 +11,11 @@ tags:
|
||||
visible: "Search settings"
|
||||
timeout: 20000
|
||||
- takeScreenshot: settings-00-list
|
||||
# The search also lists the settings inside each page under it, so a common
|
||||
# word ("Folders", "Calendar") pushes the page's row below the keyboard.
|
||||
# Each Q matches its page near the top. A PROOF the search lists under the
|
||||
# row would pass on the iPad without the page, so those differ. The Themes
|
||||
# cards are one element each, named by the theme: check the page's text.
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: account, ROW: ".*@example.org, .*", PROOF: "Logged-in accounts|Display Name"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: language, ROW: "Language, Region & Time, .*", Q: "Language", PROOF: "Date Format"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: notifications, ROW: "Notifications, .*", Q: "Notifications", PROOF: "Email Notifications"}}
|
||||
@@ -22,16 +27,16 @@ tags:
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: vacation, ROW: "Out of Office, .*", Q: "Office", PROOF: "Reply automatically"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: filters, ROW: "Filters, .*", Q: "Filters", PROOF: "Email Filters"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: templates, ROW: "Templates, .*", Q: "Templates", PROOF: "Email Templates"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: folders, ROW: "Folders, .*", Q: "Folders", PROOF: ".*Inbox.*"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: folders, ROW: "Folders, .*", Q: "New folder", PROOF: ".*Inbox.*"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: tags, ROW: "Tags, .*", Q: "Tags", PROOF: "Email Tags"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: downloads, ROW: "Downloads, .*", Q: "Downloads", PROOF: "Email .*eml.* filename"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: security, ROW: "Security, .*", Q: "Security", PROOF: "Account Security|Detecting server capabilities.*"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: content, ROW: "Content & Senders, .*", Q: "Content", PROOF: "External Content"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: calendar, ROW: "Calendar, .*", Q: "Calendar", PROOF: "Default view"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: contacts, ROW: "Contacts, .*", Q: "Contacts", PROOF: "Group by first letter"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: content, ROW: "Content & Senders, .*", Q: "Content &", PROOF: "External Content"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: calendar, ROW: "Calendar, .*", Q: "Week start", PROOF: "Default view"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: contacts, ROW: "Contacts, .*", Q: "Group by", PROOF: "Sort by last name"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: files, ROW: "Files, .*", Q: "Files", PROOF: "Default View"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: sidebar-apps, ROW: "Sidebar Apps, .*", Q: "Sidebar", PROOF: "Keep Apps Loaded"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: themes, ROW: "Themes, .*", Q: "Themes", PROOF: "The default light and dark palettes."}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: themes, ROW: "Themes, .*", Q: "Themes", PROOF: "Pick a colou?r theme.*"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: storage, ROW: "Storage & backup, .*", Q: "Storage", PROOF: "Offline mail.*"}}
|
||||
- runFlow: {file: ../subflows/settings-page.yaml, env: {NAME: about, ROW: "About, .*", Q: "About", PROOF: "This device"}}
|
||||
- tapOn:
|
||||
|
||||
@@ -10,8 +10,11 @@ tags:
|
||||
env:
|
||||
CAMERA: deny
|
||||
- tapOn: "Scan a sign-in code.*"
|
||||
# Denied for good: "Camera access is disabled..."; not asked yet (the
|
||||
# simulator doesn't always apply the denial up front): "Bulwark Mail needs
|
||||
# camera access..." (English catalog) or the built-in fallback wording.
|
||||
- extendedWaitUntil:
|
||||
visible: "Camera access is.*|Scanning a sign-in QR code uses the camera.*"
|
||||
visible: "Camera access is.*|.*needs camera access.*|Scanning a sign-in QR code uses the camera.*"
|
||||
timeout: 15000
|
||||
- takeScreenshot: scanner-01-denied
|
||||
- tapOn: "Close"
|
||||
|
||||
@@ -11,9 +11,13 @@ appId: org.bulwarkmail.mobile
|
||||
- setOrientation: PORTRAIT
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
# Maestro repeats a tap that seems to change nothing; here the repeat
|
||||
# landed on the app once the alert was gone (a day in the calendar's
|
||||
# month grid, which opened that day). Tap once.
|
||||
- tapOn:
|
||||
text: "Allow"
|
||||
optional: true
|
||||
retryTapIfNoChange: false
|
||||
- runFlow:
|
||||
when:
|
||||
true: ${ORIENTATION == 'landscape'}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
# covers it (the tap then opens another tab): on the phone, scroll it to the
|
||||
# middle. The iPad's list is a column Maestro's scroll (in the middle of the
|
||||
# screen) doesn't reach; its rows fit on screen.
|
||||
# The avatar's "Select <sender>: <subject>" checkbox mentions the subject
|
||||
# too, and a tap on it selects the row instead of opening it (#91): match
|
||||
# the row itself by its id.
|
||||
appId: org.bulwarkmail.mobile
|
||||
---
|
||||
- runFlow:
|
||||
@@ -10,7 +13,9 @@ appId: org.bulwarkmail.mobile
|
||||
true: ${DEVICE != 'tablet'}
|
||||
commands:
|
||||
- scrollUntilVisible:
|
||||
element: ".*${SUBJECT}.*"
|
||||
element:
|
||||
id: email-row
|
||||
text: ".*${SUBJECT}.*"
|
||||
direction: DOWN
|
||||
centerElement: true
|
||||
visibilityPercentage: 100
|
||||
@@ -20,13 +25,17 @@ appId: org.bulwarkmail.mobile
|
||||
true: ${DEVICE == 'tablet'}
|
||||
commands:
|
||||
- scrollUntilVisible:
|
||||
element: ".*${SUBJECT}.*"
|
||||
element:
|
||||
id: email-row
|
||||
text: ".*${SUBJECT}.*"
|
||||
direction: DOWN
|
||||
timeout: 30000
|
||||
# A tap while the list still moves lands on another row.
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 5000
|
||||
- tapOn: ".*${SUBJECT}.*"
|
||||
- tapOn:
|
||||
id: email-row
|
||||
text: ".*${SUBJECT}.*"
|
||||
# The message toolbar's "more" button: "Reply All" shows on the phone, but
|
||||
# the iPad pane has a quick reply box instead for mail to one recipient.
|
||||
- extendedWaitUntil:
|
||||
|
||||
@@ -25,6 +25,14 @@ appId: org.bulwarkmail.mobile
|
||||
element: "Sign out"
|
||||
direction: DOWN
|
||||
timeout: 30000
|
||||
# The scroll can stop with the button half under the tab bar, where
|
||||
# a tap reaches the tab bar instead: scroll on to the end of the list.
|
||||
- swipe:
|
||||
start: 50%,70%
|
||||
end: 50%,30%
|
||||
duration: 400
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
- tapOn: "Sign out"
|
||||
- extendedWaitUntil:
|
||||
visible: "The account is removed from this device.*"
|
||||
|
||||
@@ -4,10 +4,15 @@
|
||||
# field and type again. The caret is still at the end of what was just
|
||||
# typed, so eraseText (which deletes before the caret) empties it; selecting
|
||||
# the text with a long press didn't work and appended instead. SECRET=yes
|
||||
# skips the check (a password field shows dots).
|
||||
# skips the check (a password field shows dots). TAP=no types into the
|
||||
# field that has the focus already.
|
||||
appId: org.bulwarkmail.mobile
|
||||
---
|
||||
- tapOn: ${HINT}
|
||||
- runFlow:
|
||||
when:
|
||||
true: ${TAP != 'no'}
|
||||
commands:
|
||||
- tapOn: ${HINT}
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
- inputText: ${TEXT}
|
||||
|
||||
@@ -11,12 +11,25 @@ appId: org.bulwarkmail.mobile
|
||||
env:
|
||||
HINT: "user@example.com"
|
||||
TEXT: ${LOGIN}
|
||||
# On the iPhone, Safari's keyboard toolbar (Previous, Next, Done) can sit
|
||||
# over the password field, and a tap there leaves the focus in Email (the
|
||||
# password then went into Email). Its Next moves the focus to the password.
|
||||
- evalScript: ${output.webNext = false}
|
||||
- runFlow:
|
||||
when:
|
||||
visible: "Next"
|
||||
commands:
|
||||
- tapOn: "Next"
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
- evalScript: ${output.webNext = true}
|
||||
- runFlow:
|
||||
file: type-web.yaml
|
||||
env:
|
||||
HINT: "Enter your password"
|
||||
TEXT: ${PASSWORD}
|
||||
SECRET: "yes"
|
||||
TAP: "${output.webNext ? 'no' : 'yes'}"
|
||||
- tapOn: "Sign in"
|
||||
- runFlow:
|
||||
when:
|
||||
|
||||
Reference in New Issue
Block a user