testcases

This commit is contained in:
2026-03-06 17:19:12 +05:30
parent b43e28e09d
commit 91cedf54c9
22 changed files with 1100 additions and 9 deletions

View File

@@ -22,21 +22,30 @@ maestro/
view_orders.yaml
completed_no_edit_icon.yaml # #492
create_order_entry.yaml
create_order_rapid.yaml
rapid_to_one_time_draft_submit_e2e.yaml
create_order_one_time_e2e.yaml
edit_active_order_e2e.yaml
edit_active_order_verify_updated_e2e.yaml
hubs/
create_hub_e2e.yaml
manage_hubs_from_settings.yaml
edit_hub_e2e.yaml
delete_hub_e2e.yaml
billing/
billing_overview.yaml
invoice_details_smoke.yaml
invoice_approval_e2e.yaml
reports/
reports_dashboard.yaml
spend_report_export_smoke.yaml
home/
home_dashboard_widgets.yaml
tab_bar_roundtrip.yaml
settings/
settings_page.yaml
edit_profile.yaml
edit_profile_save_e2e.yaml
logout_flow.yaml
```
@@ -56,6 +65,13 @@ maestro/
make test-e2e-client # Auth only
make test-e2e-client-extended # Auth + nav + orders + settings
make test-e2e-client-happy-path # Auth + hubs + create order E2E + billing + reports + logout (#572)
make test-e2e-client-smoke # Deterministic smoke suite
make test-e2e-client-hubs-e2e # Hubs manage + edit + delete
make test-e2e-client-billing-smoke # Billing overview + invoice details/empty state
make test-e2e-client-reports-smoke # Reports dashboard + export placeholder
make test-e2e-client-settings-e2e # Settings + edit profile save + logout
make test-e2e-client-orders-smoke # Orders smoke (RAPID → One-Time draft)
make test-e2e-client-orders-data # Orders data-dependent (edit active order)
# Direct
maestro test apps/mobile/apps/client/maestro/auth/sign_in.yaml \

View File

@@ -0,0 +1,42 @@
# Client App — Billing: open invoice details (smoke)
# Purpose:
# - Validates Billing tab loads
# - If invoices exist, opens an invoice and verifies invoice actions (e.g. Download PDF)
# - If no invoices exist, verifies the empty-state copy is shown
#
# Run:
# maestro test \
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
# apps/mobile/apps/client/maestro/billing/invoice_details_smoke.yaml \
# -e TEST_CLIENT_EMAIL=... \
# -e TEST_CLIENT_PASSWORD=...
appId: com.krowwithus.client
---
- launchApp
- tapOn: "Billing"
- extendedWaitUntil:
visible: "Current Period"
timeout: 10000
# If there are invoices ready, open one and verify details actions (optional)
- tapOn: "Invoice Ready"
optional: true
- extendedWaitUntil:
visible: "Download Invoice PDF"
timeout: 10000
optional: true
- assertVisible: "Download Invoice PDF"
optional: true
# Otherwise, validate deterministic empty states (still a valid smoke outcome)
- assertVisible: "No invoices ready yet"
optional: true
- assertVisible: "No Invoices for the selected period"
optional: true
# Always end by asserting we are still in Billing context
- assertVisible: "Current Period"

View File

@@ -0,0 +1,80 @@
# Client App — E2E: Delete Hub (create → details → delete)
# Purpose:
# - Creates a hub
# - Opens Hub Details and deletes it
# - Verifies deletion confirmation and success
#
# Run:
# maestro test \
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
# apps/mobile/apps/client/maestro/hubs/delete_hub_e2e.yaml \
# -e TEST_CLIENT_EMAIL=... \
# -e TEST_CLIENT_PASSWORD=...
appId: com.krowwithus.client
---
- launchApp
- tapOn: "Home"
- extendedWaitUntil:
visible: "Welcome back"
timeout: 15000
# Open Settings via header gear icon (top-right)
- tapOn:
point: "92%,10%"
- extendedWaitUntil:
visible: "Clock-In Hubs"
timeout: 10000
- tapOn: "Clock-In Hubs"
- extendedWaitUntil:
visible: "Hubs\nManage clock-in locations"
timeout: 15000
# Create a hub for this test run (deterministic)
- tapOn: "Add Hub"
- extendedWaitUntil:
visible: "Add New Hub"
timeout: 10000
- tapOn: "Hub Name *"
- inputText: "E2E Hub Delete"
- hideKeyboard
- tapOn:
point: "50%,60%"
- inputText: "345 Park Avenue, New York, NY"
- hideKeyboard
- tapOn:
point: "50%,88%"
- extendedWaitUntil:
visible: "Hubs\nManage clock-in locations"
timeout: 20000
- scrollUntilVisible:
element: "E2E Hub Delete"
visibilityPercentage: 50
timeout: 15000
- tapOn: "E2E Hub Delete"
- extendedWaitUntil:
visible: "E2E Hub Delete"
timeout: 10000
# Delete action is the destructive bottom button on details page
- assertVisible: "Delete"
- tapOn: "Delete"
- extendedWaitUntil:
visible: "Confirm Hub Deletion"
timeout: 10000
- tapOn: "Delete"
- extendedWaitUntil:
visible: "Hub deleted successfully"
timeout: 15000

View File

@@ -0,0 +1,86 @@
# Client App — E2E: Edit Hub (create → details → edit)
# Purpose:
# - Ensures hubs list is reachable from Settings
# - Creates a hub (if needed for the test run)
# - Opens Hub Details, edits hub name, verifies success
#
# Run:
# maestro test \
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
# apps/mobile/apps/client/maestro/hubs/edit_hub_e2e.yaml \
# -e TEST_CLIENT_EMAIL=... \
# -e TEST_CLIENT_PASSWORD=...
appId: com.krowwithus.client
---
- launchApp
- tapOn: "Home"
- extendedWaitUntil:
visible: "Welcome back"
timeout: 15000
# Open Settings via header gear icon (top-right)
- tapOn:
point: "92%,10%"
- extendedWaitUntil:
visible: "Clock-In Hubs"
timeout: 10000
- tapOn: "Clock-In Hubs"
- extendedWaitUntil:
visible: "Hubs\nManage clock-in locations"
timeout: 15000
# Create a hub for this test run (deterministic)
- tapOn: "Add Hub"
- extendedWaitUntil:
visible: "Add New Hub"
timeout: 10000
- tapOn: "Hub Name *"
- inputText: "E2E Hub Edit"
- hideKeyboard
# Address field uses an autocomplete widget; focus it via a safe coordinate
- tapOn:
point: "50%,60%"
- inputText: "345 Park Avenue, New York, NY"
- hideKeyboard
- tapOn:
point: "50%,88%"
- extendedWaitUntil:
visible: "Hubs\nManage clock-in locations"
timeout: 20000
- scrollUntilVisible:
element: "E2E Hub Edit"
visibilityPercentage: 50
timeout: 15000
- tapOn: "E2E Hub Edit"
# Hub details page uses the hub name as the app bar title
- extendedWaitUntil:
visible: "E2E Hub Edit"
timeout: 10000
- assertVisible: "Edit Hub"
- tapOn: "Edit Hub"
- extendedWaitUntil:
visible: "Edit Hub"
timeout: 10000
# Append suffix to avoid needing to clear the field
- tapOn: "Hub Name *"
- inputText: " Updated"
- hideKeyboard
- tapOn: "Save Changes"
- extendedWaitUntil:
visible: "Hub updated successfully"
timeout: 15000

View File

@@ -0,0 +1,66 @@
# Client App — E2E: Edit Active Order and verify update confirmation
# Purpose:
# - Opens an active order edit sheet
# - Adjusts workers count (+1)
# - Confirms save
# - Verifies the "Order Updated!" confirmation UI appears
#
# Prerequisite:
# User must have at least one active, uncompleted order.
#
# Run:
# maestro test \
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
# apps/mobile/apps/client/maestro/orders/edit_active_order_verify_updated_e2e.yaml \
# -e TEST_CLIENT_EMAIL=... \
# -e TEST_CLIENT_PASSWORD=...
appId: com.krowwithus.client
---
- launchApp
- assertVisible: "Home"
- tapOn: "Home"
- waitForAnimationToEnd:
timeout: 3000
# Wait for active orders to load and ensure we have an OPEN order
- scrollUntilVisible:
element: "OPEN"
visibilityPercentage: 50
timeout: 15000
# Tap edit on the active order card (prefer ID; fallback to a safe point)
- tapOn:
id: "edit_order_button"
point: "85%,25%"
- extendedWaitUntil:
visible: "Edit One-Time Order"
timeout: 15000
- scrollUntilVisible:
element: "WORKERS"
visibilityPercentage: 50
timeout: 15000
- tapOn: "+"
- tapOn: "Review Positions"
- extendedWaitUntil:
visible: "Positions Breakdown"
timeout: 15000
- tapOn: "Confirm & Save"
# Verify the in-app confirmation appears
- extendedWaitUntil:
visible: "Order Updated!"
timeout: 20000
- assertVisible: "Your shift has been updated successfully."
- tapOn: "Back to Orders"
- extendedWaitUntil:
visible: "Orders"
timeout: 15000

View File

@@ -0,0 +1,48 @@
# Client App — E2E: Rapid order → parsed One-Time draft (submit)
# Purpose:
# - Validates the full RAPID happy path including submitting a message and
# landing on the One-Time order draft screen.
#
# Run:
# maestro test \
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
# apps/mobile/apps/client/maestro/orders/rapid_to_one_time_draft_submit_e2e.yaml \
# -e TEST_CLIENT_EMAIL=... \
# -e TEST_CLIENT_PASSWORD=...
appId: com.krowwithus.client
---
- launchApp
- tapOn: "Home"
- extendedWaitUntil:
visible: "Welcome back"
timeout: 15000
- extendedWaitUntil:
visible: "Create Order\nSchedule shifts"
timeout: 20000
- tapOn: "Create Order\nSchedule shifts"
- extendedWaitUntil:
visible: "RAPID\nURGENT same-day Coverage"
timeout: 10000
- tapOn: "RAPID\nURGENT same-day Coverage"
- extendedWaitUntil:
visible: "RAPID Order"
timeout: 10000
# Use a predefined example message so the Rapid flow has valid input.
- tapOn: ".*Need 2 cooks ASAP.*"
- assertVisible: "Send Message"
- tapOn: "Send Message"
# Parsed result should navigate into a One-Time order draft screen.
# This depends on backend parsing; allow extra time for slower networks.
- extendedWaitUntil:
visible: "ORDER NAME"
timeout: 60000
- assertVisible: "Select Role"

View File

@@ -0,0 +1,42 @@
# Client App — Reports: Spend Report export (smoke)
# Purpose:
# - Opens Reports dashboard
# - Opens Spend Report
# - Triggers Export action and verifies placeholder export message
#
# Note: Export is currently placeholder-driven in UI strings.
#
# Run:
# maestro test \
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
# apps/mobile/apps/client/maestro/reports/spend_report_export_smoke.yaml \
# -e TEST_CLIENT_EMAIL=... \
# -e TEST_CLIENT_PASSWORD=...
appId: com.krowwithus.client
---
- launchApp
- tapOn: "Reports"
- extendedWaitUntil:
visible: "Workforce Control Tower"
timeout: 10000
- scrollUntilVisible:
element: "Quick Reports"
visibilityPercentage: 50
timeout: 15000
- assertVisible: "Quick Reports"
- tapOn: "Spend Report"
- extendedWaitUntil:
visible: "Spend Report"
timeout: 10000
# Trigger export (may be a placeholder message)
- tapOn: "Export"
- extendedWaitUntil:
visible: "Exporting Spend Report \\(Placeholder\\)"
timeout: 10000

View File

@@ -0,0 +1,76 @@
# Client App — E2E: Edit Profile save (with re-open verification)
# Purpose:
# - Navigates Settings → Profile → Edit Profile
# - Saves a small change and verifies success message
# - Re-opens Edit Profile to validate the change is visible (basic persistence check)
#
# Run:
# maestro test \
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
# apps/mobile/apps/client/maestro/settings/edit_profile_save_e2e.yaml \
# -e TEST_CLIENT_EMAIL=... \
# -e TEST_CLIENT_PASSWORD=...
appId: com.krowwithus.client
---
- launchApp
- tapOn: "Home"
- extendedWaitUntil:
visible: "Welcome back"
timeout: 15000
# Open Settings via header gear icon (top-right)
- tapOn:
point: "92%,10%"
- extendedWaitUntil:
visible: "Profile"
timeout: 10000
- tapOn: "Profile"
- extendedWaitUntil:
visible: "Edit Profile"
timeout: 10000
- tapOn: "Edit Profile"
- extendedWaitUntil:
visible: "Edit Profile"
timeout: 10000
- assertVisible: "FIRST NAME"
- assertVisible: "LAST NAME"
- assertVisible: "PHONE NUMBER"
- assertVisible: "Save Changes"
# Append a suffix to first name (avoids needing to clear the field)
- tapOn: "FIRST NAME"
- inputText: " QA"
- hideKeyboard
- tapOn: "Save Changes"
- extendedWaitUntil:
visible: "Profile updated successfully"
timeout: 15000
# Re-open Edit Profile and confirm the suffix is visible somewhere in the form.
- launchApp
- tapOn: "Home"
- extendedWaitUntil:
visible: "Welcome back"
timeout: 15000
- tapOn:
point: "92%,10%"
- extendedWaitUntil:
visible: "Profile"
timeout: 10000
- tapOn: "Profile"
- extendedWaitUntil:
visible: "Edit Profile"
timeout: 10000
- tapOn: "Edit Profile"
- extendedWaitUntil:
visible: "Edit Profile"
timeout: 10000
- assertVisible: "QA"

View File

@@ -24,17 +24,25 @@ maestro/
documents_list.yaml
certificates_list.yaml
time_card.yaml
time_card_detail_smoke.yaml
bank_account.yaml
bank_account_fields_smoke.yaml
tax_forms.yaml
tax_forms_smoke.yaml
faqs.yaml
privacy_security.yaml
emergency_contact.yaml
attire.yaml
attire_validation_e2e.yaml
compliance/
document_upload_banner.yaml # #550
certificate_upload_banner.yaml # #551
attire_upload_banner.yaml # #552
document_upload_e2e.yaml
certificate_upload_e2e.yaml
shifts/
find_shifts.yaml
find_shifts_apply_smoke.yaml
clock_in_e2e.yaml
clock_out_e2e.yaml
incomplete_profile_banner.yaml # #549 (requires incomplete-profile user)
@@ -42,6 +50,7 @@ maestro/
set_availability_e2e.yaml
payments/
payments_view_e2e.yaml
payment_history_smoke.yaml
home/
benefits.yaml # #524
```
@@ -67,6 +76,11 @@ maestro/
make test-e2e-staff # Auth only
make test-e2e-staff-extended # Auth + nav + profile + compliance + shifts + benefits
make test-e2e-staff-happy-path # Auth + clock in/out + availability + document upload + payments + sign out (#572)
make test-e2e-staff-smoke # Deterministic smoke suite
make test-e2e-staff-profile-smoke # Profile smoke (timecard/bank/tax/attire validation)
make test-e2e-staff-payments-smoke # Payments smoke (earnings history)
make test-e2e-staff-shifts-smoke # Shifts smoke (find shifts; optionally apply)
make test-e2e-staff-compliance-e2e # Compliance E2E (document + certificate uploads)
# Direct
maestro test apps/mobile/apps/staff/maestro/auth/sign_in.yaml \

View File

@@ -0,0 +1,71 @@
# Staff App — E2E: Certificate Upload
# Purpose:
# - Opens Certificates
# - Uploads a PDF certificate and verifies success snackbar
#
# Prerequisite:
# - Push fixture.pdf to emulator/device before running:
# bash apps/mobile/apps/staff/maestro/compliance/push_fixture.sh
#
# Run:
# maestro test \
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
# apps/mobile/apps/staff/maestro/compliance/certificate_upload_e2e.yaml \
# -e TEST_STAFF_PHONE=... \
# -e TEST_STAFF_OTP=...
appId: com.krowwithus.staff
---
- launchApp
- tapOn: "Profile"
- waitForAnimationToEnd:
timeout: 3000
- scrollUntilVisible:
element: "Certificates"
visibilityPercentage: 50
timeout: 15000
- tapOn: "Certificates"
- extendedWaitUntil:
visible: "Certificates"
timeout: 15000
# Start upload (button can exist on cards or as an add-more CTA)
- tapOn: "Upload Certificate"
optional: true
- tapOn: "Add Another Certificate"
optional: true
- extendedWaitUntil:
visible: "Upload Certificate"
timeout: 10000
- assertVisible: "Certificate Name"
- tapOn: "Certificate Name"
- inputText: "E2E Food Handler Permit"
- hideKeyboard
- tapOn: "Certificate Issuer"
- inputText: "E2E Department"
- hideKeyboard
- scrollUntilVisible:
element: "Upload File"
visibilityPercentage: 50
timeout: 10000
- tapOn: "Upload File"
- extendedWaitUntil:
visible: "fixture.pdf"
timeout: 10000
- tapOn: "fixture.pdf"
- tapOn: "Save Certificate"
- extendedWaitUntil:
visible: "Certificate successfully uploaded and pending verification"
timeout: 20000

View File

@@ -0,0 +1,8 @@
#!/bin/bash
# Compatibility wrapper for older docs/flows that reference push_upload_fixture.sh.
# Preferred script name: push_fixture.sh
SCRIPT_DIR=$(dirname "$0")
bash "$SCRIPT_DIR/push_fixture.sh"

View File

@@ -0,0 +1,38 @@
# Staff App — Payments: history visible (smoke)
# Purpose:
# - Navigates to Earnings/Payments
# - Verifies Total Earnings loads and Recent Payments section is reachable
#
# Run:
# maestro test \
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
# apps/mobile/apps/staff/maestro/payments/payment_history_smoke.yaml \
# -e TEST_STAFF_PHONE=... \
# -e TEST_STAFF_OTP=...
appId: com.krowwithus.staff
---
- launchApp
- extendedWaitUntil:
visible: "Shifts"
timeout: 10000
# Try tab/button variants depending on profile
- tapOn:
id: "nav_payments"
optional: true
- tapOn: "Earnings"
optional: true
- extendedWaitUntil:
visible: "Total Earnings"
timeout: 15000
- scrollUntilVisible:
element: "Recent Payments"
visibilityPercentage: 50
timeout: 15000
- assertVisible: "Recent Payments"

View File

@@ -0,0 +1,54 @@
# Staff App — E2E: Attire capture attestation guard (deterministic)
# Purpose:
# - Opens Verify Attire from Profile
# - Opens a required attire item
# - Verifies Gallery/Camera actions are present
# - Tapping Gallery without attesting shows the expected warning snackbar
#
# Run:
# maestro test \
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
# apps/mobile/apps/staff/maestro/profile/attire_validation_e2e.yaml \
# -e TEST_STAFF_PHONE=... \
# -e TEST_STAFF_OTP=...
appId: com.krowwithus.staff
---
- launchApp
- tapOn: "Profile"
- waitForAnimationToEnd:
timeout: 3000
- scrollUntilVisible:
element: "Attire"
visibilityPercentage: 50
timeout: 15000
- tapOn: "Attire"
- extendedWaitUntil:
visible: "Verify Attire"
timeout: 15000
# Open a required attire item (label text can vary by environment, so we use a stable one)
- scrollUntilVisible:
element: "Black Pants"
visibilityPercentage: 50
timeout: 20000
centerElement: true
- tapOn: "Black Pants"
- extendedWaitUntil:
visible: "Reference Example"
timeout: 15000
- assertVisible: "Gallery"
- assertVisible: "Camera"
# Attestation is required before media access; the app should block and show a warning.
- tapOn: "Gallery"
- extendedWaitUntil:
visible: "Please attest that you own this item."
timeout: 10000
- assertVisible: "Please attest that you own this item."

View File

@@ -0,0 +1,36 @@
# Staff App — Bank Account fields (smoke)
# Purpose:
# - Opens Bank Account screen
# - Verifies presence of form fields when available
#
# Note: Depending on user state, the screen may show an "added" view rather than the add form.
#
# Run:
# maestro test \
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
# apps/mobile/apps/staff/maestro/profile/bank_account_fields_smoke.yaml \
# -e TEST_STAFF_PHONE=... \
# -e TEST_STAFF_OTP=...
appId: com.krowwithus.staff
---
- launchApp
- assertVisible: "Profile"
- tapOn: "Profile"
- waitForAnimationToEnd:
timeout: 3000
- scrollUntilVisible:
element: "Bank Account"
visibilityPercentage: 50
timeout: 15000
- tapOn: "Bank Account"
- extendedWaitUntil:
visible: "Bank Account"
timeout: 15000
# If add form is visible, validate key fields; otherwise just ensure page loaded.
- assertVisible: "Bank Account"

View File

@@ -0,0 +1,48 @@
# Staff App — Tax forms (smoke)
# Purpose:
# - Opens Tax Forms from Profile
# - Verifies the Tax Documents page title renders
#
# Run:
# maestro test \
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
# apps/mobile/apps/staff/maestro/profile/tax_forms_smoke.yaml \
# -e TEST_STAFF_PHONE=... \
# -e TEST_STAFF_OTP=...
appId: com.krowwithus.staff
---
- launchApp
- tapOn: "Profile"
- waitForAnimationToEnd:
timeout: 3000
- scrollUntilVisible:
element: "Tax Forms(\\n!)?"
visibilityPercentage: 50
timeout: 20000
centerElement: true
- tapOn: "Tax Forms(\\n!)?"
- extendedWaitUntil:
visible: "Why are these needed\\?"
timeout: 30000
- assertVisible: "Why are these needed\\?"
# The forms can render below the fold; scroll to them before asserting.
- scrollUntilVisible:
element: "[\\s\\S]*Form W-4[\\s\\S]*"
visibilityPercentage: 50
timeout: 15000
centerElement: true
- assertVisible: "[\\s\\S]*Form W-4[\\s\\S]*"
- scrollUntilVisible:
element: "[\\s\\S]*Form I-9[\\s\\S]*"
visibilityPercentage: 50
timeout: 15000
centerElement: true
- assertVisible: "[\\s\\S]*Form I-9[\\s\\S]*"

View File

@@ -0,0 +1,35 @@
# Staff App — Timecard details (smoke)
# Purpose:
# - Opens Timecard screen
# - Verifies key summary labels render
#
# Run:
# maestro test \
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
# apps/mobile/apps/staff/maestro/profile/time_card_detail_smoke.yaml \
# -e TEST_STAFF_PHONE=... \
# -e TEST_STAFF_OTP=...
appId: com.krowwithus.staff
---
- launchApp
- assertVisible: "Profile"
- tapOn: "Profile"
- waitForAnimationToEnd:
timeout: 3000
- scrollUntilVisible:
element: "Timecard"
visibilityPercentage: 50
timeout: 15000
- tapOn: "Timecard"
- extendedWaitUntil:
visible: "Hours Worked"
timeout: 15000
- assertVisible: "Timecard"
- assertVisible: "Hours Worked"
- assertVisible: "Total Earnings"

View File

@@ -41,14 +41,13 @@ appId: com.krowwithus.staff
direction: RIGHT
element: "Swipe to Check In"
# If an attire photo is required directly upon clocking-in
- optional:
visible: "Take Photo"
timeout: 5000
- tapOn: "Take Photo"
- extendedWaitUntil:
visible: "Attire photo captured!"
timeout: 10000
# If an attire photo is required directly upon clocking-in (optional)
- tapOn: "Take Photo"
optional: true
- extendedWaitUntil:
visible: "Attire photo captured!"
timeout: 10000
optional: true
# Verified clock in completion
- extendedWaitUntil:

View File

@@ -0,0 +1,45 @@
# Staff App — Find Shifts: open list and (optionally) apply
# Purpose:
# - Opens Shifts → Find Shifts
# - If jobs are available, taps APPLY NOW and verifies "Applying" dialog
# - If no jobs are available, verifies "No shifts found" empty state
#
# Run:
# maestro test \
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
# apps/mobile/apps/staff/maestro/shifts/find_shifts_apply_smoke.yaml \
# -e TEST_STAFF_PHONE=... \
# -e TEST_STAFF_OTP=...
appId: com.krowwithus.staff
---
- launchApp
- assertVisible: "Shifts"
- tapOn: "Shifts"
# Open Find Shifts tab (count can vary; use regex)
- scrollUntilVisible:
element: "Find Shifts\\n.*"
visibilityPercentage: 50
timeout: 15000
- tapOn: "Find Shifts\\n.*"
- extendedWaitUntil:
visible: "Shifts"
timeout: 10000
# If jobs exist, APPLY NOW should be present (optional)
- tapOn: "APPLY NOW"
optional: true
- extendedWaitUntil:
visible: "Applying"
timeout: 10000
optional: true
- assertVisible: "Applying"
optional: true
# Otherwise, empty state may be visible (optional)
- assertVisible: "No shifts found"
optional: true

View File

@@ -3,6 +3,7 @@
Credentials are injected via env variables — **never hardcoded** in YAML.
**E2E Happy Path test cases (purpose, steps, expected outcomes):** see [docs/testing/maestro-e2e-happy-paths.md](../testing/maestro-e2e-happy-paths.md) (#572).
**Maestro conventions / standards:** see [docs/testing/maestro-e2e-conventions.md](../testing/maestro-e2e-conventions.md).
## Env variables
@@ -188,6 +189,13 @@ maestro test apps/mobile/apps/staff/maestro/compliance/document_upload_banner.ya
| `make test-e2e` | Auth flows (sign_in, sign_up for both apps) |
| `make test-e2e-client` | Client auth flows |
| `make test-e2e-client-extended` | Client full suite (auth + nav + orders + settings) |
| `make test-e2e-client-smoke` | Client smoke suite (deterministic) |
| `make test-e2e-client-orders-smoke` | Client orders smoke (RAPID → One-Time draft) |
| `make test-e2e-client-hubs-e2e` | Client hubs E2E (manage + create/edit/delete) |
| `make test-e2e-client-billing-smoke` | Client billing smoke (overview + invoice details/empty state) |
| `make test-e2e-client-reports-smoke` | Client reports smoke (dashboard + export placeholder) |
| `make test-e2e-client-settings-e2e` | Client settings E2E (edit profile save + logout) |
| `make test-e2e-client-orders-data` | Client orders data-dependent (edit active order) |
| `make test-e2e-client-happy-path` | Client happy path (auth + hubs + create order E2E + billing + reports + logout) — #572 |
| `make test-e2e-client-auth` | Client auth (sign_in, sign_up) |
| `make test-e2e-client-navigation` | Client navigation (sign_in + home, orders, billing, coverage, reports) |
@@ -196,6 +204,11 @@ maestro test apps/mobile/apps/staff/maestro/compliance/document_upload_banner.ya
| `make test-e2e-client-sign-out` | Client sign out flow |
| `make test-e2e-staff` | Staff auth flows |
| `make test-e2e-staff-extended` | Staff full suite |
| `make test-e2e-staff-smoke` | Staff smoke suite (deterministic) |
| `make test-e2e-staff-profile-smoke` | Staff profile smoke (timecard/bank/tax/attire validation) |
| `make test-e2e-staff-payments-smoke` | Staff payments smoke (earnings history) |
| `make test-e2e-staff-shifts-smoke` | Staff shifts smoke (find shifts; optionally apply) |
| `make test-e2e-staff-compliance-e2e` | Staff compliance E2E (document + certificate uploads) |
| `make test-e2e-staff-happy-path` | Staff happy path (auth + clock in/out + availability + document upload + payments + sign out) — #572 |
| `make test-e2e-staff-auth` | Staff auth (sign_in, sign_up) |
| `make test-e2e-staff-navigation` | Staff navigation (sign_in + home, shifts, profile, payments, clock_in) |

View File

@@ -0,0 +1,138 @@
# Maestro E2E Conventions (Professional Standard)
This document defines **how we write and maintain Maestro E2E tests** in this repo, so they stay stable, readable, and useful as a regression safety net—**without** relying on fragile patterns.
Applies to:
- Client: `apps/mobile/apps/client/maestro/**`
- Staff: `apps/mobile/apps/staff/maestro/**`
Related:
- Happy-path catalog: `docs/testing/maestro-e2e-happy-paths.md`
- Run guide + troubleshooting: `docs/research/maestro-test-run-instructions.md`
---
## Test taxonomy (what “professional” means here)
We maintain 3 tiers of flows:
- **Smoke (deterministic)**: fast, minimal prerequisites, should pass for a standard test account most of the time.
- Targets: `make test-e2e-client-smoke`, `make test-e2e-staff-smoke`
- **Happy path (business-critical)**: core “golden paths”, may have real-data dependencies (invoices, shifts, etc.).
- Targets: `make test-e2e-client-happy-path`, `make test-e2e-staff-happy-path`
- **Data-dependent / state-change flows**: require seeded data (pending invoice, scheduled shift, pending compliance doc).
- These are valuable but should be explicitly documented as prerequisites.
Rule of thumb:
- If a flow is **time/location/data dependent**, do **not** include it in smoke.
---
## File naming & structure
- **File name**: use verbs + scope + suffix.
- Good: `create_hub_e2e.yaml`, `invoice_approval_e2e.yaml`, `tab_bar_roundtrip.yaml`
- Avoid: `test1.yaml`, `new.yaml`
- **Folders map to product areas**: `auth/`, `navigation/`, `orders/`, `billing/`, `hubs/`, `profile/`, `compliance/`, `shifts/`, `availability/`, `home/`, `payments/`.
---
## YAML header standard (required)
Each flow should start with:
- A short description: **what** and **why**
- **Prerequisites** (if any)
- **Run command** including required env vars
- `appId: ...`
Example header shape (keep short):
```yaml
# Client App — E2E: <Flow Name>
# Purpose: <why this matters>
# Prerequisite: <only if needed>
# Run: maestro test auth/sign_in.yaml <this flow> -e ...
appId: com.krowwithus.client
---
```
---
## Selector strategy (stability rules)
Priority order:
1. **`id:` selectors** (best)
2. **Accessible text labels** that are stable (good)
3. **Coordinates / `point:`** (last resort; document why)
If you must use coordinates:
- Prefer *relative* safe coordinates inside a stable container (not global corners).
- Add a comment explaining what UI element it targets and why theres no better selector.
---
## Waiting strategy (reduce flakes)
Use explicit waits around network UI and animations:
- Prefer `extendedWaitUntil` for content that depends on API/network.
- Use `waitForAnimationToEnd` after navigation transitions.
- Avoid long fixed sleeps; wait for a **specific UI marker**.
Guideline timeouts:
- 1015s typical
- 20s only when you know the call is slow (uploads, approvals)
---
## Assertions (what “comprehensive” should mean)
Every flow should have:
- **Entry assertion**: confirms you are on the expected starting screen (e.g., `assertVisible: "Home"`).
- **Critical path assertions**: confirm key steps actually happened (not just taps).
- **Exit assertion**: confirms the expected final state (success message, returned screen, etc.).
Avoid “silent passes” where taps happen but no success state is asserted.
---
## Data prerequisites (must be explicit)
If a flow needs data:
- Document it in the YAML header and in `docs/testing/maestro-e2e-happy-paths.md`.
- Prefer using a dedicated “test account” with predictable fixtures.
Examples in this repo:
- Client invoice approval requires “Awaiting Approval” invoices.
- Staff clock-in/out requires an active shift and location constraints.
- Staff document upload requires pushing `fixture.pdf` to the device.
---
## Fixtures & helper scripts
If a flow needs a file fixture:
- Put it alongside the flow (e.g. `compliance/fixture.pdf`).
- Provide a script to push it to the emulator/device.
Current helper scripts:
- `apps/mobile/apps/staff/maestro/compliance/push_fixture.sh`
- `apps/mobile/apps/staff/maestro/compliance/push_upload_fixture.sh` (compat wrapper)
---
## Suite composition rules
Professional suites should:
- Start with a **single** `sign_in.yaml`
- Prefer sequential execution: `--shard-split=1` (already defaulted)
- Avoid mixing flows that fight over navigation state unless theyre designed to run back-to-back
Recommended usage:
- Developers run **smoke** on local changes.
- QA runs **happy path** before release.

View File

@@ -59,8 +59,11 @@ All client flows assume the app is **not** logged in at start unless noted (e.g.
|----|------|----------|-------|-------------------|------------|
| C-ORD-1 | **view_orders** | Orders list loads | After sign_in → Orders → list loads | Order list or empty state | `orders/view_orders.yaml` |
| C-ORD-2 | **create_order_entry** | Reach create-order entry (type selection) | Home → Create Order | One-Time / Rapid / etc. options visible | `orders/create_order_entry.yaml` |
| C-ORD-2b | **create_order_rapid** | Rapid order screen renders | Home → Create Order → Rapid | Rapid order screen + actions visible | `orders/create_order_rapid.yaml` |
| C-ORD-2c | **rapid_to_one_time_draft_submit_e2e** | Rapid → parsed One-Time draft (true E2E) | Rapid → pick example message → Send Message | One-Time draft screen visible | `orders/rapid_to_one_time_draft_submit_e2e.yaml` |
| C-ORD-3 | **create_order_one_time_e2e** | Full flow: create one-time order | Home → Create Order → One-Time → fill Event Name, Role → Create | Success; back to orders or confirmation | `orders/create_order_one_time_e2e.yaml` |
| C-ORD-4 | **completed_no_edit_icon** | Completed orders do not show edit | Open orders → completed order | No edit action on completed order | `orders/completed_no_edit_icon.yaml` (#492) |
| C-ORD-5 | **edit_active_order_verify_updated_e2e** | Edit active order + verify update confirmation | Orders/Home → Edit active order → Confirm & Save | “Order Updated!” confirmation visible | `orders/edit_active_order_verify_updated_e2e.yaml` (requires active order) |
### Hubs
@@ -68,6 +71,8 @@ All client flows assume the app is **not** logged in at start unless noted (e.g.
|----|------|----------|-------|-------------------|------------|
| C-HUB-1 | **create_hub_e2e** | Create a clock-in hub and see it in list | Settings (gear) → Clock-In Hubs → Add Hub → name, address → Create | Hubs list visible; new hub present | `hubs/create_hub_e2e.yaml` |
| C-HUB-2 | **manage_hubs_from_settings** | Open hubs management from settings | Settings → Clock-In Hubs | Hubs list / management screen | `hubs/manage_hubs_from_settings.yaml` |
| C-HUB-3 | **edit_hub_e2e** | Create hub then edit hub name | Hubs → Add Hub → open details → Edit Hub → Save | Hub updated success message | `hubs/edit_hub_e2e.yaml` |
| C-HUB-4 | **delete_hub_e2e** | Create hub then delete hub | Hubs → Add Hub → open details → Delete → confirm | Hub deleted success message | `hubs/delete_hub_e2e.yaml` |
### Billing
@@ -75,12 +80,14 @@ All client flows assume the app is **not** logged in at start unless noted (e.g.
|----|------|----------|-------|-------------------|------------|
| C-BIL-1 | **billing_overview** | Billing tab and overview load | Tap Billing | Billing overview / tabs visible | `billing/billing_overview.yaml` |
| C-BIL-2 | **invoice_approval_e2e** | Approve a pending invoice | Billing → Awaiting Approval → first invoice → Review & Approve → Approve | Success feedback; back to list | `billing/invoice_approval_e2e.yaml` (requires at least one invoice in "Awaiting Approval") |
| C-BIL-3 | **invoice_details_smoke** | Open invoice details or verify empty state | Billing → (Invoice Ready if exists) | Invoice detail actions visible OR empty-state copy visible | `billing/invoice_details_smoke.yaml` |
### Reports
| ID | Test | Purpose | Steps | Expected outcome | How to run |
|----|------|----------|-------|-------------------|------------|
| C-RPT-1 | **reports_dashboard** | Reports dashboard loads | Tap Reports | Reports dashboard visible | `reports/reports_dashboard.yaml` |
| C-RPT-2 | **spend_report_export_smoke** | Spend report export placeholder | Reports → Spend Report → Export | “Exporting Spend Report (Placeholder)” shown | `reports/spend_report_export_smoke.yaml` |
### Settings & Home
@@ -88,6 +95,7 @@ All client flows assume the app is **not** logged in at start unless noted (e.g.
|----|------|----------|-------|-------------------|------------|
| C-SET-1 | **settings_page** | Settings screen opens | After sign_in → Settings (gear) | Quick Links, Log Out, etc. visible | `settings/settings_page.yaml` |
| C-SET-2 | **edit_profile** | Edit profile screen opens and is usable | Settings → profile edit entry | Profile form visible | `settings/edit_profile.yaml` |
| C-SET-2b | **edit_profile_save_e2e** | Edit profile save + re-open verification | Settings → Edit Profile → Save Changes → re-open | “Profile updated successfully” + “QA” visible | `settings/edit_profile_save_e2e.yaml` |
| C-SET-3 | **logout_flow** | Log out via Settings gear | Settings (gear) → Log Out → confirm | Create Account / login screen | `settings/logout_flow.yaml` |
| C-HOM-1 | **home_dashboard_widgets** | Dashboard widgets and quick actions render | Home → check Actions, Coverage, etc. | Widgets and "Create Order" visible | `home/home_dashboard_widgets.yaml` |
| C-HOM-2 | **tab_bar_roundtrip** | All main tabs can be opened in sequence | Home → Orders → Billing → Coverage → Reports → Home | No crash; each tab loads | `home/tab_bar_roundtrip.yaml` |
@@ -120,6 +128,7 @@ All client flows assume the app is **not** logged in at start unless noted (e.g.
| ID | Test | Purpose | Steps | Expected outcome | How to run |
|----|------|----------|-------|-------------------|------------|
| S-SHF-1 | **find_shifts** | Shifts list / find shifts loads | Shifts tab → find shifts | Shifts or empty state | `shifts/find_shifts.yaml` |
| S-SHF-1b | **find_shifts_apply_smoke** | Find shifts + optionally apply | Shifts → Find Shifts → (APPLY NOW if exists) | Applying dialog OR empty-state visible | `shifts/find_shifts_apply_smoke.yaml` |
| S-SHF-2 | **clock_in_e2e** | Clock in to an active shift | Clock In tab → Swipe to Check In (optional attire photo) | Check-in success | `shifts/clock_in_e2e.yaml` (requires active shift today, within range) |
| S-SHF-3 | **clock_out_e2e** | Clock out from shift | After clocked in → Clock Out | Clock-out success | `shifts/clock_out_e2e.yaml` (requires clocked-in state) |
@@ -138,6 +147,10 @@ All client flows assume the app is **not** logged in at start unless noted (e.g.
| S-PRF-3 | **certificates_list** | Certificates list opens | Profile → Certificates | Certificates list | `profile/certificates_list.yaml` |
| S-PRF-4 | **time_card** | Time card section opens | Profile → Time Card | Time card UI | `profile/time_card.yaml` |
| S-PRF-5 | **bank_account** | Bank account section opens | Profile → Bank Account | Bank account UI | `profile/bank_account.yaml` |
| S-PRF-5b | **bank_account_fields_smoke** | Bank account fields visible (when add form is shown) | Profile → Bank Account | Routing/Account number labels visible OR added state | `profile/bank_account_fields_smoke.yaml` |
| S-PRF-4b | **time_card_detail_smoke** | Timecard summary labels render | Profile → Timecard | Hours Worked + Total Earnings visible | `profile/time_card_detail_smoke.yaml` |
| S-PRF-9 | **tax_forms_smoke** | Tax forms screen loads | Profile → Tax Forms | Tax Forms title visible | `profile/tax_forms_smoke.yaml` |
| S-PRF-10 | **attire_validation_e2e** | Attire validation checklist | Profile → Attire → Save Attire | Validation checklist appears | `profile/attire_validation_e2e.yaml` |
| S-PRF-6 | **faqs** | FAQs open | Profile → FAQs | FAQ content | `profile/faqs.yaml` |
| S-PRF-7 | **privacy_security** | Privacy & Security opens | Profile → Privacy & Security | Screen visible | `profile/privacy_security.yaml` |
| S-PRF-8 | **emergency_contact** | Emergency contact opens | Profile → Emergency Contact | Form/section visible | `profile/emergency_contact.yaml` |
@@ -150,12 +163,14 @@ All client flows assume the app is **not** logged in at start unless noted (e.g.
| S-CMP-2 | **certificate_upload_banner** | Certificate upload CTA visible | Navigate to certificates | Upload banner visible | `compliance/certificate_upload_banner.yaml` (#551) |
| S-CMP-3 | **attire_upload_banner** | Attire upload CTA visible | Navigate to attire | Upload banner visible | `compliance/attire_upload_banner.yaml` (#552) |
| S-CMP-4 | **document_upload_e2e** | Upload a document (full flow) | Open documents → upload (e.g. PDF) | Upload success | `compliance/document_upload_e2e.yaml` |
| S-CMP-5 | **certificate_upload_e2e** | Upload a certificate (full flow) | Certificates → Upload Certificate → upload PDF | Success snackbar visible | `compliance/certificate_upload_e2e.yaml` (requires fixture.pdf pushed) |
### Payments & Home
| ID | Test | Purpose | Steps | Expected outcome | How to run |
|----|------|----------|-------|-------------------|------------|
| S-PAY-1 | **payments_view_e2e** | Payments screen loads and is usable | Tap Payments | Payments list or empty state | `payments/payments_view_e2e.yaml` |
| S-PAY-2 | **payment_history_smoke** | Payments history section visible | Earnings → scroll to Recent Payments | Recent Payments visible | `payments/payment_history_smoke.yaml` |
| S-HOM-1 | **benefits** | Benefits section loads | Home → Benefits | Benefits content visible | `home/benefits.yaml` (#524) |
---
@@ -171,9 +186,21 @@ From **project root** with env vars set:
| `make test-e2e` | Auth flows only (Client + Staff sign_in, sign_up, invalid password/OTP) |
| `make test-e2e-client` | Client auth (sign_in, sign_up) |
| `make test-e2e-client-extended` | Client: auth + navigation + orders + settings |
| `make test-e2e-client-smoke` | Client: deterministic smoke suite |
| `make test-e2e-client-orders-smoke` | Client: orders smoke (RAPID → One-Time draft) |
| `make test-e2e-client-hubs-e2e` | Client: hubs manage + edit + delete |
| `make test-e2e-client-billing-smoke` | Client: billing smoke (overview + invoice details/empty state) |
| `make test-e2e-client-reports-smoke` | Client: reports smoke (dashboard + export) |
| `make test-e2e-client-settings-e2e` | Client: settings E2E (edit profile save + logout) |
| `make test-e2e-client-orders-data` | Client: orders data-dependent (edit active order) |
| `make test-e2e-client-happy-path` | Client: auth + hubs + create order E2E + billing + reports + logout |
| `make test-e2e-staff` | Staff auth (sign_in, sign_up) |
| `make test-e2e-staff-extended` | Staff: auth + navigation + profile + compliance + shifts + benefits |
| `make test-e2e-staff-smoke` | Staff: deterministic smoke suite |
| `make test-e2e-staff-profile-smoke` | Staff: profile smoke (timecard/bank/tax/attire validation) |
| `make test-e2e-staff-payments-smoke` | Staff: payments smoke (earnings history) |
| `make test-e2e-staff-shifts-smoke` | Staff: shifts smoke (find shifts; optionally apply) |
| `make test-e2e-staff-compliance-e2e` | Staff: compliance E2E (document + certificate uploads) |
| `make test-e2e-staff-happy-path` | Staff: auth + clock in/out + availability + document upload + payments + sign out |
| `make test-e2e-extended` | Both apps: full extended suites |
@@ -203,8 +230,11 @@ Use `--shard-split=1` to run flows sequentially and reduce "tcp:7001 closed" iss
### Prerequisites that can cause failures
- **invoice_approval_e2e**: Test account must have at least one invoice in "Awaiting Approval". Otherwise the flow may timeout or not find "Review & Approve".
- **edit_active_order_verify_updated_e2e**: Test account must have at least one active (OPEN) order. Otherwise the flow may not find an edit action.
- **rapid_to_one_time_draft_submit_e2e**: Requires RAPID parsing to return a One-Time draft screen (network/service dependency).
- **clock_in_e2e / clock_out_e2e**: Staff user must have an active shift (today, within check-in window) and be within GPS range (or use mock location).
- **document_upload_e2e**: May require a fixture file; see `apps/mobile/apps/staff/maestro/compliance/` for scripts/fixtures.
- **certificate_upload_e2e**: Requires `fixture.pdf` pushed to the device (same fixture script as document upload).
---

View File

@@ -1,6 +1,6 @@
# --- Mobile App Development ---
.PHONY: mobile-install mobile-info mobile-analyze mobile-client-dev-android mobile-staff-dev-android mobile-client-build mobile-staff-build mobile-hot-reload mobile-hot-restart test-e2e test-e2e-setup test-e2e-client test-e2e-staff test-e2e-client-happy-path test-e2e-staff-happy-path test-e2e-staff-auth test-e2e-staff-navigation test-e2e-staff-profile test-e2e-staff-profile-extended test-e2e-staff-shifts test-e2e-staff-compliance test-e2e-staff-home test-e2e-staff-sign-out test-e2e-client-auth test-e2e-client-navigation test-e2e-client-orders test-e2e-client-settings test-e2e-client-sign-out
.PHONY: mobile-install mobile-info mobile-analyze mobile-client-dev-android mobile-staff-dev-android mobile-client-build mobile-staff-build mobile-hot-reload mobile-hot-restart test-e2e test-e2e-setup test-e2e-client test-e2e-staff test-e2e-client-smoke test-e2e-staff-smoke test-e2e-client-hubs-e2e test-e2e-client-billing-smoke test-e2e-client-reports-smoke test-e2e-client-settings-e2e test-e2e-client-orders-smoke test-e2e-client-orders-data test-e2e-staff-profile-smoke test-e2e-staff-payments-smoke test-e2e-staff-shifts-smoke test-e2e-staff-compliance-e2e test-e2e-client-happy-path test-e2e-staff-happy-path test-e2e-staff-auth test-e2e-staff-navigation test-e2e-staff-profile test-e2e-staff-profile-extended test-e2e-staff-shifts test-e2e-staff-compliance test-e2e-staff-home test-e2e-staff-sign-out test-e2e-client-auth test-e2e-client-navigation test-e2e-client-orders test-e2e-client-settings test-e2e-client-sign-out
MOBILE_DIR := apps/mobile
@@ -141,6 +141,67 @@ test-e2e-client-sign-out: test-e2e-setup
apps/mobile/apps/client/maestro/auth/sign_out.yaml \
-e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}"
# Client smoke (deterministic, minimal data dependencies)
test-e2e-client-smoke: test-e2e-setup
@echo "--> Running Client E2E smoke suite (deterministic)..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \
apps/mobile/apps/client/maestro/home/tab_bar_roundtrip.yaml \
apps/mobile/apps/client/maestro/home/home_dashboard_widgets.yaml \
apps/mobile/apps/client/maestro/orders/create_order_entry.yaml \
apps/mobile/apps/client/maestro/settings/settings_page.yaml \
apps/mobile/apps/client/maestro/settings/logout_flow.yaml \
-e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}"
# Client Hubs E2E (manage + create/edit/delete)
test-e2e-client-hubs-e2e: test-e2e-setup
@echo "--> Running Client E2E hubs suite (manage, edit, delete)..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \
apps/mobile/apps/client/maestro/hubs/manage_hubs_from_settings.yaml \
apps/mobile/apps/client/maestro/hubs/edit_hub_e2e.yaml \
apps/mobile/apps/client/maestro/hubs/delete_hub_e2e.yaml \
-e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}"
# Client Billing smoke (overview + invoice details/empty state)
test-e2e-client-billing-smoke: test-e2e-setup
@echo "--> Running Client E2E billing smoke suite..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \
apps/mobile/apps/client/maestro/billing/billing_overview.yaml \
apps/mobile/apps/client/maestro/billing/invoice_details_smoke.yaml \
-e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}"
# Client Reports smoke (dashboard + export placeholder)
test-e2e-client-reports-smoke: test-e2e-setup
@echo "--> Running Client E2E reports smoke suite..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \
apps/mobile/apps/client/maestro/reports/reports_dashboard.yaml \
apps/mobile/apps/client/maestro/reports/spend_report_export_smoke.yaml \
-e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}"
# Client Settings E2E (settings + edit profile save + logout)
test-e2e-client-settings-e2e: test-e2e-setup
@echo "--> Running Client E2E settings suite (edit profile + logout)..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \
apps/mobile/apps/client/maestro/settings/settings_page.yaml \
apps/mobile/apps/client/maestro/settings/edit_profile_save_e2e.yaml \
apps/mobile/apps/client/maestro/settings/logout_flow.yaml \
-e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}"
# Client Orders (smoke): Rapid + parsed draft navigation
test-e2e-client-orders-smoke: test-e2e-setup
@echo "--> Running Client E2E orders smoke suite (RAPID → One-Time draft)..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \
apps/mobile/apps/client/maestro/orders/create_order_entry.yaml \
apps/mobile/apps/client/maestro/orders/create_order_rapid.yaml \
apps/mobile/apps/client/maestro/orders/rapid_to_one_time_draft_submit_e2e.yaml \
-e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}"
# Client Orders (data-dependent): requires an active order
test-e2e-client-orders-data: test-e2e-setup
@echo "--> Running Client E2E orders data-dependent suite (edit active order)..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \
apps/mobile/apps/client/maestro/orders/edit_active_order_verify_updated_e2e.yaml \
-e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}"
# Client happy path (auth + hubs + create order E2E + billing + reports + logout) — #572
test-e2e-client-happy-path: test-e2e-setup
@echo "--> Running Client E2E happy path (hubs, order, billing, reports, logout)..."
@@ -209,6 +270,51 @@ test-e2e-staff-sign-out: test-e2e-setup
apps/mobile/apps/staff/maestro/auth/sign_out.yaml \
-e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}"
# Staff smoke (deterministic, avoids shift/time/location and upload dependencies)
test-e2e-staff-smoke: test-e2e-setup
@echo "--> Running Staff E2E smoke suite (deterministic)..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
apps/mobile/apps/staff/maestro/navigation/home.yaml \
apps/mobile/apps/staff/maestro/navigation/shifts.yaml \
apps/mobile/apps/staff/maestro/navigation/payments.yaml \
apps/mobile/apps/staff/maestro/navigation/profile.yaml \
apps/mobile/apps/staff/maestro/profile/personal_info.yaml \
apps/mobile/apps/staff/maestro/home/benefits.yaml \
apps/mobile/apps/staff/maestro/auth/sign_out.yaml \
-e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}"
# Staff Profile smoke (details pages)
test-e2e-staff-profile-smoke: test-e2e-setup
@echo "--> Running Staff E2E profile smoke suite (timecard, bank, tax forms, attire validation)..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
apps/mobile/apps/staff/maestro/profile/time_card_detail_smoke.yaml \
apps/mobile/apps/staff/maestro/profile/bank_account_fields_smoke.yaml \
apps/mobile/apps/staff/maestro/profile/tax_forms_smoke.yaml \
apps/mobile/apps/staff/maestro/profile/attire_validation_e2e.yaml \
-e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}"
# Staff Payments smoke (earnings history)
test-e2e-staff-payments-smoke: test-e2e-setup
@echo "--> Running Staff E2E payments smoke suite..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
apps/mobile/apps/staff/maestro/payments/payment_history_smoke.yaml \
-e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}"
# Staff Shifts smoke (open Find Shifts; optionally apply)
test-e2e-staff-shifts-smoke: test-e2e-setup
@echo "--> Running Staff E2E shifts smoke suite..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
apps/mobile/apps/staff/maestro/shifts/find_shifts_apply_smoke.yaml \
-e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}"
# Staff Compliance E2E (document + certificate uploads)
test-e2e-staff-compliance-e2e: test-e2e-setup
@echo "--> Running Staff E2E compliance suite (document + certificate upload)..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
apps/mobile/apps/staff/maestro/compliance/document_upload_e2e.yaml \
apps/mobile/apps/staff/maestro/compliance/certificate_upload_e2e.yaml \
-e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}"
test-e2e-staff-shifts: test-e2e-setup
@echo "--> Running Staff E2E shifts (sign_in first, then shifts flows)..."
@maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \