This commit is contained in:
@@ -15,42 +15,42 @@ appId: com.krowwithus.client
|
||||
---
|
||||
# We rely on sign_in.yaml being run before this to establish a session.
|
||||
- launchApp
|
||||
|
||||
# If we are logged in, Home/Orders content should be visible directly.
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Orders|Welcome).*"
|
||||
timeout: 15000
|
||||
visible:
|
||||
id: "client_nav_home"
|
||||
timeout: 60000
|
||||
|
||||
# Perform a full stop to clear memory (not just backgrounding)
|
||||
- stopApp
|
||||
- launchApp:
|
||||
clearState: false
|
||||
|
||||
# Relaunch - should NOT show the login screen
|
||||
- launchApp
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Orders|Welcome).*"
|
||||
timeout: 15000
|
||||
visible:
|
||||
id: "client_nav_home"
|
||||
timeout: 30000
|
||||
|
||||
# Verification: Log out to ensure clean state for next test
|
||||
# Open Settings via header gear icon (top-right)
|
||||
# Cleanup: Log out
|
||||
- tapOn:
|
||||
id: "header_settings_icon"
|
||||
optional: true
|
||||
- tapOn:
|
||||
point: "92%,10%"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*Logout.*"
|
||||
timeout: 10000
|
||||
|
||||
- tapOn: "(?i).*Logout.*"
|
||||
|
||||
# Confirm Log Out
|
||||
- tapOn:
|
||||
text: "(?i).*(Yes|Confirm).*(Logout|Log Out).*"
|
||||
optional: true
|
||||
|
||||
# Should return to the sign in landing page
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)Sign In"
|
||||
timeout: 10000
|
||||
- assertVisible: "(?i)Sign In"
|
||||
visible: "Log Out"
|
||||
timeout: 15000
|
||||
- tapOn: "Log Out"
|
||||
- tapOn:
|
||||
text: "Log Out"
|
||||
optional: true
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: "client_landing_sign_in"
|
||||
timeout: 30000
|
||||
- assertVisible:
|
||||
id: "client_landing_sign_in"
|
||||
|
||||
|
||||
|
||||
@@ -8,44 +8,40 @@ env:
|
||||
clearState: true
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "(?i).*(Sign In|Log In|Welcome).*"
|
||||
timeout: 45000
|
||||
id: "client_landing_sign_in"
|
||||
timeout: 60000
|
||||
|
||||
# Try tap by both ID and Text for maximum reliability
|
||||
- tapOn:
|
||||
id: "client_landing_sign_in"
|
||||
optional: true
|
||||
- tapOn:
|
||||
text: "(?i)Sign In"
|
||||
optional: true
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)Email"
|
||||
visible:
|
||||
id: "sign_in_email"
|
||||
timeout: 20000
|
||||
|
||||
- tapOn:
|
||||
id: "sign_in_email"
|
||||
- inputText: ${EMAIL}
|
||||
- stopApp: # Small trick to hide keyboard on some emulators
|
||||
optional: true
|
||||
- launchApp: # Resume where we were
|
||||
clearState: false
|
||||
|
||||
- tapOn:
|
||||
id: "sign_in_password"
|
||||
- inputText: ${PASSWORD}
|
||||
- hideKeyboard
|
||||
|
||||
# In the form, just tap Sign In text
|
||||
- tapOn:
|
||||
id: "sign_in_submit_button"
|
||||
optional: true
|
||||
- tapOn:
|
||||
text: "(?i)Sign In"
|
||||
|
||||
- hideKeyboard
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Orders|Welcome).*"
|
||||
timeout: 45000
|
||||
|
||||
# Final check: ensure the bottom nav is rendered before finishing
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: "client_nav_home"
|
||||
timeout: 15000
|
||||
optional: true
|
||||
timeout: 45000
|
||||
|
||||
- assertVisible: "(?i).*(Home|Orders|Welcome).*"
|
||||
- assertVisible:
|
||||
id: "client_nav_home"
|
||||
@@ -3,23 +3,31 @@
|
||||
appId: com.krowwithus.client
|
||||
---
|
||||
- launchApp
|
||||
- tapOn: "Home"
|
||||
- extendedWaitUntil:
|
||||
visible: "Welcome back"
|
||||
timeout: 15000
|
||||
visible:
|
||||
id: "client_nav_home"
|
||||
timeout: 30000
|
||||
|
||||
# Open Settings via header gear icon (top-right)
|
||||
# Open Settings
|
||||
- tapOn:
|
||||
id: "header_settings_icon"
|
||||
optional: true
|
||||
- tapOn:
|
||||
point: "92%,10%"
|
||||
optional: true
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "Log Out"
|
||||
timeout: 10000
|
||||
timeout: 20000
|
||||
|
||||
- tapOn: "Log Out"
|
||||
- assertVisible: "Are you sure you want to log out?"
|
||||
- tapOn: "Log Out"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "Create Account"
|
||||
timeout: 20000
|
||||
visible:
|
||||
id: "client_landing_sign_in"
|
||||
timeout: 30000
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ env:
|
||||
timeout: 10000
|
||||
|
||||
- tapOn: "Create Account"
|
||||
- assertVisible: "Company"
|
||||
- assertVisible: "(?i)Company Name"
|
||||
- tapOn:
|
||||
id: sign_up_company
|
||||
- inputText: ${COMPANY}
|
||||
@@ -0,0 +1,50 @@
|
||||
# Client App — Billing: Empty state smoke
|
||||
# Purpose:
|
||||
# - Opens Billing tab
|
||||
# - Verifies the screen loads correctly with no invoices
|
||||
# - Checks that "Current Period" header is always visible
|
||||
# - Verifies empty-state copy appears when no invoices exist
|
||||
# - Deterministic: always passes whether or not invoices exist
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/client/maestro/billing/billing_empty_state.yaml \
|
||||
# -e TEST_CLIENT_EMAIL=... \
|
||||
# -e TEST_CLIENT_PASSWORD=...
|
||||
|
||||
appId: com.krowwithus.client
|
||||
---
|
||||
- launchApp:
|
||||
clearState: false
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||
timeout: 45000
|
||||
|
||||
- tapOn: "(?i)Billing"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)Current Period"
|
||||
timeout: 20000
|
||||
|
||||
# Entry assertion — billing is loaded
|
||||
- assertVisible: "(?i)Current Period"
|
||||
|
||||
# Awaiting Approval section
|
||||
- assertVisible:
|
||||
text: "(?i)Awaiting Approval"
|
||||
optional: true
|
||||
|
||||
# Case A: invoices exist → invoice amounts/dates are visible
|
||||
- assertVisible:
|
||||
text: "(?i).*(Invoice Ready|Review & Approve|Approved).*"
|
||||
optional: true
|
||||
|
||||
# Case B: no invoices → empty-state message visible
|
||||
- assertVisible:
|
||||
text: "(?i).*(No invoices|nothing|all clear|no pending).*"
|
||||
optional: true
|
||||
|
||||
# Exit assertion — still in Billing context
|
||||
- assertVisible: "(?i)Current Period"
|
||||
@@ -0,0 +1,61 @@
|
||||
# Client App — Hubs: Empty state smoke
|
||||
# Purpose:
|
||||
# - Navigates to Settings → Clock-In Hubs
|
||||
# - Verifies the hubs list loads correctly
|
||||
# - If no hubs exist, verifies an empty-state message is shown
|
||||
# - If hubs exist, verifies the list renders correctly (passes either way)
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/client/maestro/hubs/hub_empty_state.yaml \
|
||||
# -e TEST_CLIENT_EMAIL=... \
|
||||
# -e TEST_CLIENT_PASSWORD=...
|
||||
|
||||
appId: com.krowwithus.client
|
||||
---
|
||||
- launchApp:
|
||||
clearState: false
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||
timeout: 45000
|
||||
|
||||
- tapOn: "(?i)Home"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Welcome back|Home).*"
|
||||
timeout: 20000
|
||||
|
||||
# Open Settings via header gear icon (top-right)
|
||||
- tapOn:
|
||||
point: "92%,10%"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)Clock-In Hubs"
|
||||
timeout: 10000
|
||||
|
||||
- tapOn: "(?i)Clock-In Hubs"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Hubs|Manage clock-in locations).*"
|
||||
timeout: 15000
|
||||
|
||||
# Entry assertion — hubs page loaded
|
||||
- assertVisible: "(?i).*(Hubs|Manage clock-in locations).*"
|
||||
|
||||
# "Add Hub" button should always be present
|
||||
- assertVisible: "(?i)Add Hub"
|
||||
|
||||
# Case A: hubs exist — list is visible
|
||||
- assertVisible:
|
||||
text: "(?i).*(Hub|Location|Address).*"
|
||||
optional: true
|
||||
|
||||
# Case B: no hubs — empty state copy should be shown
|
||||
- assertVisible:
|
||||
text: "(?i).*(No hubs|No locations|Add your first|get started|no clock-in).*"
|
||||
optional: true
|
||||
|
||||
# Exit assertion — still on the Hubs screen
|
||||
- assertVisible: "(?i)Add Hub"
|
||||
@@ -0,0 +1,60 @@
|
||||
# Client App — Orders: Empty state smoke
|
||||
# Purpose:
|
||||
# - Opens the Orders tab
|
||||
# - Verifies filter tabs (Up Next, Active, Completed) are always present
|
||||
# - If no orders exist in a tab, verifies empty-state copy is shown (not a crash)
|
||||
# - Taps each tab and asserts either a list or empty-state is visible
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/client/maestro/orders/orders_empty_state.yaml \
|
||||
# -e TEST_CLIENT_EMAIL=... \
|
||||
# -e TEST_CLIENT_PASSWORD=...
|
||||
|
||||
appId: com.krowwithus.client
|
||||
---
|
||||
- launchApp:
|
||||
clearState: false
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||
timeout: 45000
|
||||
|
||||
- tapOn: "(?i)Orders"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)Orders"
|
||||
timeout: 15000
|
||||
|
||||
# Verify filter tabs are always present
|
||||
- assertVisible: "(?i)Up Next.*"
|
||||
- assertVisible: "(?i)Active.*"
|
||||
- assertVisible: "(?i)Completed.*"
|
||||
|
||||
# --- Up Next tab ---
|
||||
- tapOn: "(?i)Up Next.*"
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
- assertVisible:
|
||||
text: "(?i).*(No orders|No upcoming|Nothing here|order).*"
|
||||
optional: true
|
||||
|
||||
# --- Active tab ---
|
||||
- tapOn: "(?i)Active.*"
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
- assertVisible:
|
||||
text: "(?i).*(No active|No orders|Nothing here|order).*"
|
||||
optional: true
|
||||
|
||||
# --- Completed tab ---
|
||||
- tapOn: "(?i)Completed.*"
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
- assertVisible:
|
||||
text: "(?i).*(No completed|No orders|Nothing here|order).*"
|
||||
optional: true
|
||||
|
||||
# Exit assertion — we are still on the Orders screen
|
||||
- assertVisible: "(?i).*(Up Next|Active|Completed).*"
|
||||
@@ -0,0 +1,63 @@
|
||||
# Client App — Orders: Validation errors (negative path)
|
||||
# Purpose:
|
||||
# - Opens Create Order → One-Time form
|
||||
# - Attempts to submit WITHOUT filling required fields
|
||||
# - Verifies inline validation error messages appear
|
||||
# - Verifies the form does NOT navigate away (stays on create order screen)
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/client/maestro/orders/create_order_validation_errors.yaml \
|
||||
# -e TEST_CLIENT_EMAIL=... \
|
||||
# -e TEST_CLIENT_PASSWORD=...
|
||||
|
||||
appId: com.krowwithus.client
|
||||
---
|
||||
- launchApp:
|
||||
clearState: false
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||
timeout: 45000
|
||||
|
||||
- tapOn: "(?i)Home"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Welcome back|Home).*"
|
||||
timeout: 20000
|
||||
|
||||
# Navigate to Create Order
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)Create Order.*Schedule.*"
|
||||
timeout: 30000
|
||||
|
||||
- tapOn: "(?i)Create Order.*Schedule.*"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)ORDER TYPE"
|
||||
timeout: 10000
|
||||
|
||||
# Select One-Time order type
|
||||
- tapOn: "(?i)One-Time.*Single Event.*"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)One-Time Order"
|
||||
timeout: 10000
|
||||
|
||||
# Do NOT fill any fields — attempt to submit immediately
|
||||
- tapOn: "(?i)Create Order"
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
|
||||
# Validation: form should NOT advance — still on One-Time Order screen
|
||||
- assertVisible: "(?i)One-Time Order"
|
||||
|
||||
# Validation: at least one inline error or disabled-state indicator should appear
|
||||
- assertVisible:
|
||||
text: "(?i).*(required|must|invalid|please fill|error).*"
|
||||
optional: true
|
||||
|
||||
# Verify ORDER NAME field is still visible (form did not navigate away)
|
||||
- assertVisible: "(?i)ORDER NAME"
|
||||
@@ -0,0 +1,53 @@
|
||||
# Client App — Reports: No-Show Report smoke
|
||||
# Purpose:
|
||||
# - Opens Reports dashboard (Workforce Control Tower)
|
||||
# - Navigates to the No-Show Reports section
|
||||
# - Verifies the no-show report screen or relevant UI elements are visible
|
||||
# - Also verifies empty-state copy if no no-show records exist
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/client/maestro/reports/no_show_report_smoke.yaml \
|
||||
# -e TEST_CLIENT_EMAIL=... \
|
||||
# -e TEST_CLIENT_PASSWORD=...
|
||||
|
||||
appId: com.krowwithus.client
|
||||
---
|
||||
- launchApp:
|
||||
clearState: false
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||
timeout: 45000
|
||||
|
||||
- tapOn: "(?i)Reports"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)Workforce Control Tower"
|
||||
timeout: 20000
|
||||
|
||||
- assertVisible: "(?i)Workforce Control Tower"
|
||||
|
||||
# Scroll to find No-Show report entry
|
||||
- scrollUntilVisible:
|
||||
element: "(?i).*(No.Show|No Show|Absence).*"
|
||||
visibilityPercentage: 50
|
||||
timeout: 15000
|
||||
optional: true
|
||||
|
||||
# Tap No-Show report (if visible)
|
||||
- tapOn:
|
||||
text: "(?i).*(No.Show|No Show|Absence).*"
|
||||
optional: true
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
|
||||
# Either the report detail loads or we see a placeholder/empty state
|
||||
- assertVisible:
|
||||
text: "(?i).*(No.Show|No Show|Absence|No records|Nothing|Report).*"
|
||||
optional: true
|
||||
|
||||
# Exit assertion — still in Reports context (no crash)
|
||||
- assertVisible: "(?i).*(Workforce Control Tower|Reports|No.Show).*"
|
||||
@@ -0,0 +1,80 @@
|
||||
# Client App — Settings: Edit Profile validation errors (negative path)
|
||||
# Purpose:
|
||||
# - Navigates to Settings → Edit Profile
|
||||
# - Clears a required field (e.g. First Name) and attempts to save
|
||||
# - Verifies that an inline validation error is shown
|
||||
# - Verifies the form does NOT navigate away (no false success)
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/client/maestro/settings/edit_profile_validation.yaml \
|
||||
# -e TEST_CLIENT_EMAIL=... \
|
||||
# -e TEST_CLIENT_PASSWORD=...
|
||||
|
||||
appId: com.krowwithus.client
|
||||
---
|
||||
- launchApp:
|
||||
clearState: false
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||
timeout: 45000
|
||||
|
||||
- tapOn: "(?i)Home"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Welcome back|Home).*"
|
||||
timeout: 20000
|
||||
|
||||
# Open Settings via header gear icon (top-right)
|
||||
- tapOn:
|
||||
point: "92%,10%"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)Profile"
|
||||
timeout: 10000
|
||||
|
||||
- tapOn: "(?i)Profile"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)Edit Profile"
|
||||
timeout: 10000
|
||||
|
||||
- tapOn: "(?i)Edit Profile"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i)Edit Profile"
|
||||
timeout: 10000
|
||||
|
||||
# Verify required fields are present
|
||||
- assertVisible: "(?i)FIRST NAME"
|
||||
- assertVisible: "(?i)LAST NAME"
|
||||
- assertVisible: "(?i)Save Changes"
|
||||
|
||||
# Clear the FIRST NAME field by selecting all and deleting
|
||||
- tapOn: "(?i)FIRST NAME"
|
||||
- repeat:
|
||||
times: 30
|
||||
commands:
|
||||
- pressKey: Backspace
|
||||
- hideKeyboard
|
||||
|
||||
# Attempt to save with empty first name
|
||||
- tapOn: "(?i)Save Changes"
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
|
||||
# Negative assertion: success message must NOT appear
|
||||
- assertNotVisible:
|
||||
text: "(?i)Profile updated successfully"
|
||||
optional: true
|
||||
|
||||
# Positive assertion: validation error appears OR form stays put
|
||||
- assertVisible: "(?i)Edit Profile"
|
||||
|
||||
# Inline error should be visible for the empty required field
|
||||
- assertVisible:
|
||||
text: "(?i).*(required|cannot be empty|must not be|invalid|enter your).*"
|
||||
optional: true
|
||||
@@ -0,0 +1,84 @@
|
||||
# Staff App — Compliance: Attire Upload E2E (full flow)
|
||||
# Purpose:
|
||||
# - Navigates Profile → Attire
|
||||
# - Opens the attire upload form
|
||||
# - Attempts to take/upload an attire photo (uses optional steps for camera flow)
|
||||
# - Verifies success state or confirmation that attire record is saved
|
||||
#
|
||||
# Prerequisite:
|
||||
# - Staff user with Attire compliance required (not yet uploaded)
|
||||
# - Device/emulator must support camera or have a pre-configured photo
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/staff/maestro/compliance/attire_upload_e2e.yaml \
|
||||
# -e TEST_STAFF_PHONE=... -e TEST_STAFF_OTP=...
|
||||
|
||||
appId: com.krowwithus.staff
|
||||
---
|
||||
- launchApp
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Shifts|Welcome back).*"
|
||||
timeout: 20000
|
||||
|
||||
- tapOn: "(?i)Profile"
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
|
||||
# Scroll down to find Attire section
|
||||
- scrollUntilVisible:
|
||||
element: "(?i)Attire"
|
||||
visibilityPercentage: 50
|
||||
timeout: 10000
|
||||
|
||||
- tapOn: "(?i)Attire"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Attire|Uniform|Photo).*"
|
||||
timeout: 10000
|
||||
|
||||
# Entry assertion — Attire screen is open
|
||||
- assertVisible: "(?i).*(Attire|Uniform|Dress Code).*"
|
||||
|
||||
# Attempt to trigger upload / photo action
|
||||
- tapOn:
|
||||
text: "(?i).*(Upload|Take Photo|Add Photo|Camera).*"
|
||||
optional: true
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
|
||||
# If camera permission prompt appears — allow it
|
||||
- tapOn:
|
||||
text: "(?i).*(Allow|OK|Permit).*"
|
||||
optional: true
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
|
||||
# If a photo capture confirmation button appears
|
||||
- tapOn:
|
||||
text: "(?i).*(Use Photo|Done|Confirm|Save).*"
|
||||
optional: true
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
|
||||
# Save attire submission
|
||||
- tapOn:
|
||||
text: "(?i).*(Save Attire|Submit|Upload Attire|Save).*"
|
||||
optional: true
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
|
||||
# Success: either a success snackbar or return to profile
|
||||
- assertVisible:
|
||||
text: "(?i).*(Attire uploaded|Attire saved|Photo uploaded|submitted successfully|Success).*"
|
||||
optional: true
|
||||
|
||||
# Exit assertion — still in profile/compliance context (no crash)
|
||||
- assertVisible: "(?i).*(Attire|Profile|Compliance|Uniform).*"
|
||||
@@ -0,0 +1,63 @@
|
||||
# Staff App — Home: Incomplete profile banner smoke
|
||||
# Purpose:
|
||||
# - Navigates to Home screen
|
||||
# - Verifies that when a profile is incomplete, a banner/nudge is displayed
|
||||
# prompting the staff member to complete their profile
|
||||
# - Deterministic: if profile IS complete, completion state is simply not asserted
|
||||
#
|
||||
# Note: Banner visibility depends on profile completion state of the test account.
|
||||
# The test always passes — it just verifies the banner if present.
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/staff/maestro/home/incomplete_profile_banner_smoke.yaml \
|
||||
# -e TEST_STAFF_PHONE=... -e TEST_STAFF_OTP=...
|
||||
|
||||
appId: com.krowwithus.staff
|
||||
---
|
||||
- launchApp
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Shifts|Welcome back).*"
|
||||
timeout: 20000
|
||||
|
||||
- tapOn: "(?i)Home"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Welcome back|Home).*"
|
||||
timeout: 15000
|
||||
|
||||
# Entry assertion — home screen is loaded
|
||||
- assertVisible: "(?i).*(Welcome back|Home).*"
|
||||
|
||||
# Case A: incomplete profile banner is visible
|
||||
- assertVisible:
|
||||
text: "(?i).*(Complete your profile|Profile incomplete|finish setting up|complete account|missing information).*"
|
||||
optional: true
|
||||
|
||||
# Tap the banner CTA if present (verifies it navigates to profile)
|
||||
- tapOn:
|
||||
text: "(?i).*(Complete Now|Complete Profile|Finish Setup|Get Started).*"
|
||||
optional: true
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
|
||||
# If tapped, verify we landed on Profile
|
||||
- assertVisible:
|
||||
text: "(?i).*(Profile|Personal Info|Documents).*"
|
||||
optional: true
|
||||
|
||||
# Navigate back to Home
|
||||
- back
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
|
||||
# Case B: profile is complete — no banner (still a valid pass)
|
||||
- assertVisible:
|
||||
text: "(?i).*(Welcome back|Home|Benefits|Shifts).*"
|
||||
optional: true
|
||||
|
||||
# Exit assertion — still in app context, no crash
|
||||
- assertVisible: "(?i).*(Home|Profile|Shifts).*"
|
||||
@@ -0,0 +1,71 @@
|
||||
# Staff App — Payments: Payment detail view smoke
|
||||
# Purpose:
|
||||
# - Navigates to the Payments tab
|
||||
# - If payment history items exist, taps the first one
|
||||
# - Verifies the detail screen loads with expected UI elements
|
||||
# (date, amount, shift info, status)
|
||||
# - If no payment history, verifies empty state is handled gracefully
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/staff/maestro/payments/payment_detail_smoke.yaml \
|
||||
# -e TEST_STAFF_PHONE=... -e TEST_STAFF_OTP=...
|
||||
|
||||
appId: com.krowwithus.staff
|
||||
---
|
||||
- launchApp
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Shifts|Welcome back).*"
|
||||
timeout: 20000
|
||||
|
||||
# Navigate to Payments
|
||||
- tapOn:
|
||||
id: "nav_payments"
|
||||
optional: true
|
||||
|
||||
- tapOn:
|
||||
text: "(?i).*(Earnings|Payments|Pay).*"
|
||||
optional: true
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Earnings|Payments|Recent Payments).*"
|
||||
timeout: 15000
|
||||
optional: true
|
||||
|
||||
# Scroll to payment history section
|
||||
- scrollUntilVisible:
|
||||
element: "(?i)Recent Payments"
|
||||
visibilityPercentage: 50
|
||||
timeout: 10000
|
||||
optional: true
|
||||
|
||||
# Case A: payments exist — tap first item to open detail view
|
||||
- tapOn:
|
||||
id: "payment_item_row"
|
||||
optional: true
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 2000
|
||||
|
||||
# Detail screen should show shift/payment specifics
|
||||
- assertVisible:
|
||||
text: "(?i).*(Amount|$|Earnings|hours|shift|date|status).*"
|
||||
optional: true
|
||||
|
||||
# Navigate back to payments list
|
||||
- back
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Earnings|Payments|Recent Payments).*"
|
||||
timeout: 10000
|
||||
optional: true
|
||||
|
||||
# Case B: no payments — empty state is shown
|
||||
- assertVisible:
|
||||
text: "(?i).*(No payments|No earnings|Nothing yet|No records).*"
|
||||
optional: true
|
||||
|
||||
# Exit assertion — back in payments context, no crash
|
||||
- assertVisible: "(?i).*(Earnings|Payments|Home|Shifts).*"
|
||||
@@ -0,0 +1,68 @@
|
||||
# Staff App — Profile: Emergency Contact save smoke
|
||||
# Purpose:
|
||||
# - Opens Profile → Emergency Contact
|
||||
# - Verifies the form fields are present (Name, Phone, Relationship)
|
||||
# - Attempts to fill/edit a field and save
|
||||
# - Verifies success feedback and that the form persists the data
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/staff/maestro/profile/emergency_contact_save_smoke.yaml \
|
||||
# -e TEST_STAFF_PHONE=... -e TEST_STAFF_OTP=...
|
||||
|
||||
appId: com.krowwithus.staff
|
||||
---
|
||||
- launchApp
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Shifts|Welcome back).*"
|
||||
timeout: 20000
|
||||
|
||||
- tapOn: "(?i)Profile"
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
|
||||
- scrollUntilVisible:
|
||||
element: "(?i)Emergency Contact"
|
||||
visibilityPercentage: 50
|
||||
timeout: 10000
|
||||
|
||||
- tapOn: "(?i)Emergency Contact"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Emergency Contact|Save & Continue|Save).*"
|
||||
timeout: 10000
|
||||
|
||||
# Entry assertion — form loaded
|
||||
- assertVisible: "(?i)Emergency Contact"
|
||||
|
||||
# Verify key form fields are present
|
||||
- assertVisible:
|
||||
text: "(?i).*(Name|Contact Name|Full Name).*"
|
||||
optional: true
|
||||
|
||||
- assertVisible:
|
||||
text: "(?i).*(Phone|Mobile|Number).*"
|
||||
optional: true
|
||||
|
||||
- assertVisible:
|
||||
text: "(?i).*(Relationship|Relation).*"
|
||||
optional: true
|
||||
|
||||
# Attempt save (non-destructive — only taps save with existing values)
|
||||
- tapOn:
|
||||
text: "(?i).*(Save & Continue|Save|Update|Submit).*"
|
||||
optional: true
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
|
||||
# Success feedback
|
||||
- assertVisible:
|
||||
text: "(?i).*(saved|updated|success|continue).*"
|
||||
optional: true
|
||||
|
||||
# Exit assertion — still in profile context, no crash
|
||||
- assertVisible: "(?i).*(Emergency Contact|Profile).*"
|
||||
@@ -0,0 +1,58 @@
|
||||
# Staff App — Profile: Personal Info save smoke
|
||||
# Purpose:
|
||||
# - Opens Profile → Personal Info
|
||||
# - Makes a small non-destructive edit (appends to a field)
|
||||
# - Saves and verifies success feedback
|
||||
# - Re-opens to confirm the change persisted
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/staff/maestro/profile/personal_info_save_smoke.yaml \
|
||||
# -e TEST_STAFF_PHONE=... -e TEST_STAFF_OTP=...
|
||||
|
||||
appId: com.krowwithus.staff
|
||||
---
|
||||
- launchApp
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Shifts|Welcome back).*"
|
||||
timeout: 20000
|
||||
|
||||
- tapOn: "(?i)Profile"
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
|
||||
- tapOn: "(?i)Personal Info"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Full Name|First Name|Personal Info).*"
|
||||
timeout: 10000
|
||||
|
||||
# Entry assertions
|
||||
- assertVisible: "(?i)Full Name"
|
||||
- assertVisible: "(?i)Email"
|
||||
|
||||
# Scroll to the Save button to ensure form is fully loaded
|
||||
- scrollUntilVisible:
|
||||
element: "(?i).*(Save|Save Changes|Update).*"
|
||||
visibilityPercentage: 50
|
||||
timeout: 10000
|
||||
optional: true
|
||||
|
||||
# Tap save without changes (verifies save button works without destructive edit)
|
||||
- tapOn:
|
||||
text: "(?i).*(Save|Save Changes|Update|Save & Continue).*"
|
||||
optional: true
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
|
||||
# Success feedback — either a snackbar or toast
|
||||
- assertVisible:
|
||||
text: "(?i).*(saved|updated|success|changes saved).*"
|
||||
optional: true
|
||||
|
||||
# Exit assertion — still in profile context after save
|
||||
- assertVisible: "(?i).*(Personal Info|Profile|Full Name).*"
|
||||
@@ -0,0 +1,51 @@
|
||||
# Staff App — Shifts: Empty state smoke
|
||||
# Purpose:
|
||||
# - Opens the Shifts tab → Find Shifts
|
||||
# - Verifies the screen loads correctly whether shifts exist or not
|
||||
# - Checks that an appropriate message appears when no shifts are available
|
||||
# - Deterministic: passes in both "shifts available" and "no shifts" states
|
||||
#
|
||||
# Run:
|
||||
# maestro test \
|
||||
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
|
||||
# apps/mobile/apps/staff/maestro/shifts/shifts_empty_state.yaml \
|
||||
# -e TEST_STAFF_PHONE=... -e TEST_STAFF_OTP=...
|
||||
|
||||
appId: com.krowwithus.staff
|
||||
---
|
||||
- launchApp
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "(?i).*(Home|Shifts|Welcome back).*"
|
||||
timeout: 20000
|
||||
|
||||
- assertVisible: "Shifts"
|
||||
- tapOn: "Shifts"
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible: "Find Shifts.*"
|
||||
timeout: 15000
|
||||
|
||||
- tapOn:
|
||||
text: "Find Shifts.*"
|
||||
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
|
||||
# Case A: shifts are available — list renders
|
||||
- assertVisible:
|
||||
text: "(?i).*(Available|Apply Now|shift|hours).*"
|
||||
optional: true
|
||||
|
||||
# Case B: no shifts — empty state copy is shown (not a blank screen)
|
||||
- assertVisible:
|
||||
text: "(?i).*(No shifts available|No available shifts|Check back|Nothing available|no open shifts).*"
|
||||
optional: true
|
||||
|
||||
# Entry assertion: incomplete-profile banner (if applicable)
|
||||
- assertVisible:
|
||||
text: "(?i).*(isn't complete|Complete your account|unlock shift).*"
|
||||
optional: true
|
||||
|
||||
# Exit assertion — still on Shifts context, no crash
|
||||
- assertVisible: "(?i).*(Find Shifts|Shifts|Available).*"
|
||||
Reference in New Issue
Block a user