From b9574eb96ab857baf0e214a1b5767e31b75ddb3c Mon Sep 17 00:00:00 2001 From: Suriya Date: Tue, 10 Mar 2026 14:59:31 +0530 Subject: [PATCH] #636 --- .github/workflows/maestro-e2e.yml | 12 +- .github/workflows/mobile-ci.yml | 11 +- .../{ => happy_path}/session_persistence.yaml | 50 +-- .../auth/{ => happy_path}/sign_in.yaml | 34 +- .../auth/{ => happy_path}/sign_out.yaml | 22 +- .../auth/{ => happy_path}/sign_up.yaml | 2 +- .../sign_in_invalid_password.yaml | 0 .../edge_cases/billing_empty_state.yaml | 50 +++ .../{ => happy_path}/billing_overview.yaml | 0 .../invoice_approval_e2e.yaml | 0 .../{ => smoke}/invoice_details_smoke.yaml | 0 .../{ => smoke}/home_dashboard_widgets.yaml | 0 .../home/{ => smoke}/tab_bar_roundtrip.yaml | 0 .../hubs/edge_cases/hub_empty_state.yaml | 61 +++ .../hubs/{ => happy_path}/create_hub_e2e.yaml | 0 .../hubs/{ => happy_path}/delete_hub_e2e.yaml | 0 .../hubs/{ => happy_path}/edit_hub_e2e.yaml | 0 .../manage_hubs_from_settings.yaml | 0 .../navigation/{ => smoke}/billing.yaml | 0 .../navigation/{ => smoke}/coverage.yaml | 0 .../maestro/navigation/{ => smoke}/home.yaml | 0 .../navigation/{ => smoke}/orders.yaml | 0 .../navigation/{ => smoke}/reports.yaml | 0 .../completed_no_edit_icon.yaml | 0 .../orders/edge_cases/orders_empty_state.yaml | 60 +++ .../create_order_one_time_e2e.yaml | 0 .../edit_active_order_e2e.yaml | 0 .../edit_active_order_verify_updated_e2e.yaml | 0 .../rapid_to_one_time_draft_e2e.yaml | 0 .../rapid_to_one_time_draft_submit_e2e.yaml | 0 .../orders/{ => happy_path}/view_orders.yaml | 0 .../create_order_validation_errors.yaml | 63 +++ .../{ => smoke}/create_order_entry.yaml | 0 .../{ => smoke}/create_order_one_time.yaml | 0 .../create_order_permanent_placeholder.yaml | 0 .../{ => smoke}/create_order_rapid.yaml | 0 .../create_order_recurring_placeholder.yaml | 0 .../order_type_selection_smoke.yaml | 0 .../{ => happy_path}/reports_dashboard.yaml | 0 .../reports/smoke/no_show_report_smoke.yaml | 53 +++ .../spend_report_export_smoke.yaml | 0 .../{ => happy_path}/edit_profile.yaml | 0 .../edit_profile_save_e2e.yaml | 0 .../{ => happy_path}/logout_flow.yaml | 0 .../{ => happy_path}/settings_page.yaml | 0 .../negative/edit_profile_validation.yaml | 80 ++++ .../{ => happy_path}/session_persistence.yaml | 0 .../auth/{ => happy_path}/sign_in.yaml | 0 .../auth/{ => happy_path}/sign_out.yaml | 0 .../auth/{ => happy_path}/sign_up.yaml | 0 .../{ => negative}/sign_in_invalid_otp.yaml | 0 .../set_availability_e2e.yaml | 0 .../happy_path/attire_upload_e2e.yaml | 84 ++++ .../certificate_upload_e2e.yaml | 0 .../{ => happy_path}/document_upload_e2e.yaml | 0 .../{ => smoke}/attire_upload_banner.yaml | 0 .../certificate_upload_banner.yaml | 0 .../{ => smoke}/document_upload_banner.yaml | 0 .../home/{ => happy_path}/benefits.yaml | 0 .../incomplete_profile_banner_smoke.yaml | 63 +++ .../navigation/{ => smoke}/availability.yaml | 0 .../navigation/{ => smoke}/clock_in.yaml | 0 .../maestro/navigation/{ => smoke}/home.yaml | 0 .../navigation/{ => smoke}/payments.yaml | 0 .../navigation/{ => smoke}/profile.yaml | 0 .../navigation/{ => smoke}/shifts.yaml | 0 .../{ => happy_path}/payments_view_e2e.yaml | 0 .../payments/smoke/payment_detail_smoke.yaml | 71 ++++ .../{ => smoke}/payment_history_smoke.yaml | 0 .../profile/{ => happy_path}/attire.yaml | 0 .../{ => happy_path}/bank_account.yaml | 0 .../{ => happy_path}/certificates_list.yaml | 0 .../{ => happy_path}/documents_list.yaml | 0 .../{ => happy_path}/emergency_contact.yaml | 0 .../profile/{ => happy_path}/experience.yaml | 0 .../profile/{ => happy_path}/faqs.yaml | 0 .../{ => happy_path}/personal_info.yaml | 0 .../{ => happy_path}/privacy_security.yaml | 0 .../profile/{ => happy_path}/tax_forms.yaml | 0 .../profile/{ => happy_path}/time_card.yaml | 0 .../{ => smoke}/attire_validation_e2e.yaml | 0 .../bank_account_fields_smoke.yaml | 0 .../smoke/emergency_contact_save_smoke.yaml | 68 ++++ .../smoke/personal_info_save_smoke.yaml | 58 +++ .../profile/{ => smoke}/tax_forms_smoke.yaml | 0 .../{ => smoke}/time_card_detail_smoke.yaml | 0 .../incomplete_profile_banner.yaml | 0 .../shifts/edge_cases/shifts_empty_state.yaml | 51 +++ .../shifts/{ => happy_path}/clock_in_e2e.yaml | 0 .../{ => happy_path}/clock_out_e2e.yaml | 0 .../shifts/{ => happy_path}/find_shifts.yaml | 0 .../{ => smoke}/find_shifts_apply_smoke.yaml | 0 docs/testing/maestro-e2e-happy-paths.md | 249 +++--------- makefiles/mobile.mk | 384 +++++++++++------- 94 files changed, 1119 insertions(+), 407 deletions(-) rename apps/mobile/apps/client/maestro/auth/{ => happy_path}/session_persistence.yaml (50%) rename apps/mobile/apps/client/maestro/auth/{ => happy_path}/sign_in.yaml (57%) rename apps/mobile/apps/client/maestro/auth/{ => happy_path}/sign_out.yaml (66%) rename apps/mobile/apps/client/maestro/auth/{ => happy_path}/sign_up.yaml (96%) rename apps/mobile/apps/client/maestro/auth/{ => negative}/sign_in_invalid_password.yaml (100%) create mode 100644 apps/mobile/apps/client/maestro/billing/edge_cases/billing_empty_state.yaml rename apps/mobile/apps/client/maestro/billing/{ => happy_path}/billing_overview.yaml (100%) rename apps/mobile/apps/client/maestro/billing/{ => happy_path}/invoice_approval_e2e.yaml (100%) rename apps/mobile/apps/client/maestro/billing/{ => smoke}/invoice_details_smoke.yaml (100%) rename apps/mobile/apps/client/maestro/home/{ => smoke}/home_dashboard_widgets.yaml (100%) rename apps/mobile/apps/client/maestro/home/{ => smoke}/tab_bar_roundtrip.yaml (100%) create mode 100644 apps/mobile/apps/client/maestro/hubs/edge_cases/hub_empty_state.yaml rename apps/mobile/apps/client/maestro/hubs/{ => happy_path}/create_hub_e2e.yaml (100%) rename apps/mobile/apps/client/maestro/hubs/{ => happy_path}/delete_hub_e2e.yaml (100%) rename apps/mobile/apps/client/maestro/hubs/{ => happy_path}/edit_hub_e2e.yaml (100%) rename apps/mobile/apps/client/maestro/hubs/{ => happy_path}/manage_hubs_from_settings.yaml (100%) rename apps/mobile/apps/client/maestro/navigation/{ => smoke}/billing.yaml (100%) rename apps/mobile/apps/client/maestro/navigation/{ => smoke}/coverage.yaml (100%) rename apps/mobile/apps/client/maestro/navigation/{ => smoke}/home.yaml (100%) rename apps/mobile/apps/client/maestro/navigation/{ => smoke}/orders.yaml (100%) rename apps/mobile/apps/client/maestro/navigation/{ => smoke}/reports.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => edge_cases}/completed_no_edit_icon.yaml (100%) create mode 100644 apps/mobile/apps/client/maestro/orders/edge_cases/orders_empty_state.yaml rename apps/mobile/apps/client/maestro/orders/{ => happy_path}/create_order_one_time_e2e.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => happy_path}/edit_active_order_e2e.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => happy_path}/edit_active_order_verify_updated_e2e.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => happy_path}/rapid_to_one_time_draft_e2e.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => happy_path}/rapid_to_one_time_draft_submit_e2e.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => happy_path}/view_orders.yaml (100%) create mode 100644 apps/mobile/apps/client/maestro/orders/negative/create_order_validation_errors.yaml rename apps/mobile/apps/client/maestro/orders/{ => smoke}/create_order_entry.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => smoke}/create_order_one_time.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => smoke}/create_order_permanent_placeholder.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => smoke}/create_order_rapid.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => smoke}/create_order_recurring_placeholder.yaml (100%) rename apps/mobile/apps/client/maestro/orders/{ => smoke}/order_type_selection_smoke.yaml (100%) rename apps/mobile/apps/client/maestro/reports/{ => happy_path}/reports_dashboard.yaml (100%) create mode 100644 apps/mobile/apps/client/maestro/reports/smoke/no_show_report_smoke.yaml rename apps/mobile/apps/client/maestro/reports/{ => smoke}/spend_report_export_smoke.yaml (100%) rename apps/mobile/apps/client/maestro/settings/{ => happy_path}/edit_profile.yaml (100%) rename apps/mobile/apps/client/maestro/settings/{ => happy_path}/edit_profile_save_e2e.yaml (100%) rename apps/mobile/apps/client/maestro/settings/{ => happy_path}/logout_flow.yaml (100%) rename apps/mobile/apps/client/maestro/settings/{ => happy_path}/settings_page.yaml (100%) create mode 100644 apps/mobile/apps/client/maestro/settings/negative/edit_profile_validation.yaml rename apps/mobile/apps/staff/maestro/auth/{ => happy_path}/session_persistence.yaml (100%) rename apps/mobile/apps/staff/maestro/auth/{ => happy_path}/sign_in.yaml (100%) rename apps/mobile/apps/staff/maestro/auth/{ => happy_path}/sign_out.yaml (100%) rename apps/mobile/apps/staff/maestro/auth/{ => happy_path}/sign_up.yaml (100%) rename apps/mobile/apps/staff/maestro/auth/{ => negative}/sign_in_invalid_otp.yaml (100%) rename apps/mobile/apps/staff/maestro/availability/{ => happy_path}/set_availability_e2e.yaml (100%) create mode 100644 apps/mobile/apps/staff/maestro/compliance/happy_path/attire_upload_e2e.yaml rename apps/mobile/apps/staff/maestro/compliance/{ => happy_path}/certificate_upload_e2e.yaml (100%) rename apps/mobile/apps/staff/maestro/compliance/{ => happy_path}/document_upload_e2e.yaml (100%) rename apps/mobile/apps/staff/maestro/compliance/{ => smoke}/attire_upload_banner.yaml (100%) rename apps/mobile/apps/staff/maestro/compliance/{ => smoke}/certificate_upload_banner.yaml (100%) rename apps/mobile/apps/staff/maestro/compliance/{ => smoke}/document_upload_banner.yaml (100%) rename apps/mobile/apps/staff/maestro/home/{ => happy_path}/benefits.yaml (100%) create mode 100644 apps/mobile/apps/staff/maestro/home/smoke/incomplete_profile_banner_smoke.yaml rename apps/mobile/apps/staff/maestro/navigation/{ => smoke}/availability.yaml (100%) rename apps/mobile/apps/staff/maestro/navigation/{ => smoke}/clock_in.yaml (100%) rename apps/mobile/apps/staff/maestro/navigation/{ => smoke}/home.yaml (100%) rename apps/mobile/apps/staff/maestro/navigation/{ => smoke}/payments.yaml (100%) rename apps/mobile/apps/staff/maestro/navigation/{ => smoke}/profile.yaml (100%) rename apps/mobile/apps/staff/maestro/navigation/{ => smoke}/shifts.yaml (100%) rename apps/mobile/apps/staff/maestro/payments/{ => happy_path}/payments_view_e2e.yaml (100%) create mode 100644 apps/mobile/apps/staff/maestro/payments/smoke/payment_detail_smoke.yaml rename apps/mobile/apps/staff/maestro/payments/{ => smoke}/payment_history_smoke.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/attire.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/bank_account.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/certificates_list.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/documents_list.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/emergency_contact.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/experience.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/faqs.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/personal_info.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/privacy_security.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/tax_forms.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => happy_path}/time_card.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => smoke}/attire_validation_e2e.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => smoke}/bank_account_fields_smoke.yaml (100%) create mode 100644 apps/mobile/apps/staff/maestro/profile/smoke/emergency_contact_save_smoke.yaml create mode 100644 apps/mobile/apps/staff/maestro/profile/smoke/personal_info_save_smoke.yaml rename apps/mobile/apps/staff/maestro/profile/{ => smoke}/tax_forms_smoke.yaml (100%) rename apps/mobile/apps/staff/maestro/profile/{ => smoke}/time_card_detail_smoke.yaml (100%) rename apps/mobile/apps/staff/maestro/shifts/{ => edge_cases}/incomplete_profile_banner.yaml (100%) create mode 100644 apps/mobile/apps/staff/maestro/shifts/edge_cases/shifts_empty_state.yaml rename apps/mobile/apps/staff/maestro/shifts/{ => happy_path}/clock_in_e2e.yaml (100%) rename apps/mobile/apps/staff/maestro/shifts/{ => happy_path}/clock_out_e2e.yaml (100%) rename apps/mobile/apps/staff/maestro/shifts/{ => happy_path}/find_shifts.yaml (100%) rename apps/mobile/apps/staff/maestro/shifts/{ => smoke}/find_shifts_apply_smoke.yaml (100%) diff --git a/.github/workflows/maestro-e2e.yml b/.github/workflows/maestro-e2e.yml index fc256da7..11a0462d 100644 --- a/.github/workflows/maestro-e2e.yml +++ b/.github/workflows/maestro-e2e.yml @@ -5,17 +5,7 @@ name: Maestro E2E on: - workflow_dispatch: - pull_request: - paths: - - 'apps/mobile/**/maestro/**' - - '.github/workflows/maestro-e2e.yml' - push: - branches: - - main - paths: - - 'apps/mobile/**/maestro/**' - - '.github/workflows/maestro-e2e.yml' + workflow_dispatch: # Manual trigger only — auto-triggers disabled (free plan) jobs: maestro-e2e: diff --git a/.github/workflows/mobile-ci.yml b/.github/workflows/mobile-ci.yml index 1a439740..e9f9767a 100644 --- a/.github/workflows/mobile-ci.yml +++ b/.github/workflows/mobile-ci.yml @@ -1,16 +1,7 @@ name: Mobile CI on: - pull_request: - paths: - - 'apps/mobile/**' - - '.github/workflows/mobile-ci.yml' - push: - branches: - - main - paths: - - 'apps/mobile/**' - - '.github/workflows/mobile-ci.yml' + workflow_dispatch: # Manual trigger only — auto-triggers disabled (free plan) jobs: detect-changes: diff --git a/apps/mobile/apps/client/maestro/auth/session_persistence.yaml b/apps/mobile/apps/client/maestro/auth/happy_path/session_persistence.yaml similarity index 50% rename from apps/mobile/apps/client/maestro/auth/session_persistence.yaml rename to apps/mobile/apps/client/maestro/auth/happy_path/session_persistence.yaml index ee868b54..0554f5b2 100644 --- a/apps/mobile/apps/client/maestro/auth/session_persistence.yaml +++ b/apps/mobile/apps/client/maestro/auth/happy_path/session_persistence.yaml @@ -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" diff --git a/apps/mobile/apps/client/maestro/auth/sign_in.yaml b/apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml similarity index 57% rename from apps/mobile/apps/client/maestro/auth/sign_in.yaml rename to apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml index 35e287f8..ac60113d 100644 --- a/apps/mobile/apps/client/maestro/auth/sign_in.yaml +++ b/apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml @@ -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" diff --git a/apps/mobile/apps/client/maestro/auth/sign_out.yaml b/apps/mobile/apps/client/maestro/auth/happy_path/sign_out.yaml similarity index 66% rename from apps/mobile/apps/client/maestro/auth/sign_out.yaml rename to apps/mobile/apps/client/maestro/auth/happy_path/sign_out.yaml index e86bc46d..7bbd42d8 100644 --- a/apps/mobile/apps/client/maestro/auth/sign_out.yaml +++ b/apps/mobile/apps/client/maestro/auth/happy_path/sign_out.yaml @@ -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 diff --git a/apps/mobile/apps/client/maestro/auth/sign_up.yaml b/apps/mobile/apps/client/maestro/auth/happy_path/sign_up.yaml similarity index 96% rename from apps/mobile/apps/client/maestro/auth/sign_up.yaml rename to apps/mobile/apps/client/maestro/auth/happy_path/sign_up.yaml index 9befed7d..10fd269a 100644 --- a/apps/mobile/apps/client/maestro/auth/sign_up.yaml +++ b/apps/mobile/apps/client/maestro/auth/happy_path/sign_up.yaml @@ -18,7 +18,7 @@ env: timeout: 10000 - tapOn: "Create Account" -- assertVisible: "Company" +- assertVisible: "(?i)Company Name" - tapOn: id: sign_up_company - inputText: ${COMPANY} diff --git a/apps/mobile/apps/client/maestro/auth/sign_in_invalid_password.yaml b/apps/mobile/apps/client/maestro/auth/negative/sign_in_invalid_password.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/auth/sign_in_invalid_password.yaml rename to apps/mobile/apps/client/maestro/auth/negative/sign_in_invalid_password.yaml diff --git a/apps/mobile/apps/client/maestro/billing/edge_cases/billing_empty_state.yaml b/apps/mobile/apps/client/maestro/billing/edge_cases/billing_empty_state.yaml new file mode 100644 index 00000000..20202992 --- /dev/null +++ b/apps/mobile/apps/client/maestro/billing/edge_cases/billing_empty_state.yaml @@ -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" diff --git a/apps/mobile/apps/client/maestro/billing/billing_overview.yaml b/apps/mobile/apps/client/maestro/billing/happy_path/billing_overview.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/billing/billing_overview.yaml rename to apps/mobile/apps/client/maestro/billing/happy_path/billing_overview.yaml diff --git a/apps/mobile/apps/client/maestro/billing/invoice_approval_e2e.yaml b/apps/mobile/apps/client/maestro/billing/happy_path/invoice_approval_e2e.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/billing/invoice_approval_e2e.yaml rename to apps/mobile/apps/client/maestro/billing/happy_path/invoice_approval_e2e.yaml diff --git a/apps/mobile/apps/client/maestro/billing/invoice_details_smoke.yaml b/apps/mobile/apps/client/maestro/billing/smoke/invoice_details_smoke.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/billing/invoice_details_smoke.yaml rename to apps/mobile/apps/client/maestro/billing/smoke/invoice_details_smoke.yaml diff --git a/apps/mobile/apps/client/maestro/home/home_dashboard_widgets.yaml b/apps/mobile/apps/client/maestro/home/smoke/home_dashboard_widgets.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/home/home_dashboard_widgets.yaml rename to apps/mobile/apps/client/maestro/home/smoke/home_dashboard_widgets.yaml diff --git a/apps/mobile/apps/client/maestro/home/tab_bar_roundtrip.yaml b/apps/mobile/apps/client/maestro/home/smoke/tab_bar_roundtrip.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/home/tab_bar_roundtrip.yaml rename to apps/mobile/apps/client/maestro/home/smoke/tab_bar_roundtrip.yaml diff --git a/apps/mobile/apps/client/maestro/hubs/edge_cases/hub_empty_state.yaml b/apps/mobile/apps/client/maestro/hubs/edge_cases/hub_empty_state.yaml new file mode 100644 index 00000000..e89e27fa --- /dev/null +++ b/apps/mobile/apps/client/maestro/hubs/edge_cases/hub_empty_state.yaml @@ -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" diff --git a/apps/mobile/apps/client/maestro/hubs/create_hub_e2e.yaml b/apps/mobile/apps/client/maestro/hubs/happy_path/create_hub_e2e.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/hubs/create_hub_e2e.yaml rename to apps/mobile/apps/client/maestro/hubs/happy_path/create_hub_e2e.yaml diff --git a/apps/mobile/apps/client/maestro/hubs/delete_hub_e2e.yaml b/apps/mobile/apps/client/maestro/hubs/happy_path/delete_hub_e2e.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/hubs/delete_hub_e2e.yaml rename to apps/mobile/apps/client/maestro/hubs/happy_path/delete_hub_e2e.yaml diff --git a/apps/mobile/apps/client/maestro/hubs/edit_hub_e2e.yaml b/apps/mobile/apps/client/maestro/hubs/happy_path/edit_hub_e2e.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/hubs/edit_hub_e2e.yaml rename to apps/mobile/apps/client/maestro/hubs/happy_path/edit_hub_e2e.yaml diff --git a/apps/mobile/apps/client/maestro/hubs/manage_hubs_from_settings.yaml b/apps/mobile/apps/client/maestro/hubs/happy_path/manage_hubs_from_settings.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/hubs/manage_hubs_from_settings.yaml rename to apps/mobile/apps/client/maestro/hubs/happy_path/manage_hubs_from_settings.yaml diff --git a/apps/mobile/apps/client/maestro/navigation/billing.yaml b/apps/mobile/apps/client/maestro/navigation/smoke/billing.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/navigation/billing.yaml rename to apps/mobile/apps/client/maestro/navigation/smoke/billing.yaml diff --git a/apps/mobile/apps/client/maestro/navigation/coverage.yaml b/apps/mobile/apps/client/maestro/navigation/smoke/coverage.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/navigation/coverage.yaml rename to apps/mobile/apps/client/maestro/navigation/smoke/coverage.yaml diff --git a/apps/mobile/apps/client/maestro/navigation/home.yaml b/apps/mobile/apps/client/maestro/navigation/smoke/home.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/navigation/home.yaml rename to apps/mobile/apps/client/maestro/navigation/smoke/home.yaml diff --git a/apps/mobile/apps/client/maestro/navigation/orders.yaml b/apps/mobile/apps/client/maestro/navigation/smoke/orders.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/navigation/orders.yaml rename to apps/mobile/apps/client/maestro/navigation/smoke/orders.yaml diff --git a/apps/mobile/apps/client/maestro/navigation/reports.yaml b/apps/mobile/apps/client/maestro/navigation/smoke/reports.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/navigation/reports.yaml rename to apps/mobile/apps/client/maestro/navigation/smoke/reports.yaml diff --git a/apps/mobile/apps/client/maestro/orders/completed_no_edit_icon.yaml b/apps/mobile/apps/client/maestro/orders/edge_cases/completed_no_edit_icon.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/completed_no_edit_icon.yaml rename to apps/mobile/apps/client/maestro/orders/edge_cases/completed_no_edit_icon.yaml diff --git a/apps/mobile/apps/client/maestro/orders/edge_cases/orders_empty_state.yaml b/apps/mobile/apps/client/maestro/orders/edge_cases/orders_empty_state.yaml new file mode 100644 index 00000000..679312d9 --- /dev/null +++ b/apps/mobile/apps/client/maestro/orders/edge_cases/orders_empty_state.yaml @@ -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).*" diff --git a/apps/mobile/apps/client/maestro/orders/create_order_one_time_e2e.yaml b/apps/mobile/apps/client/maestro/orders/happy_path/create_order_one_time_e2e.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/create_order_one_time_e2e.yaml rename to apps/mobile/apps/client/maestro/orders/happy_path/create_order_one_time_e2e.yaml diff --git a/apps/mobile/apps/client/maestro/orders/edit_active_order_e2e.yaml b/apps/mobile/apps/client/maestro/orders/happy_path/edit_active_order_e2e.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/edit_active_order_e2e.yaml rename to apps/mobile/apps/client/maestro/orders/happy_path/edit_active_order_e2e.yaml diff --git a/apps/mobile/apps/client/maestro/orders/edit_active_order_verify_updated_e2e.yaml b/apps/mobile/apps/client/maestro/orders/happy_path/edit_active_order_verify_updated_e2e.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/edit_active_order_verify_updated_e2e.yaml rename to apps/mobile/apps/client/maestro/orders/happy_path/edit_active_order_verify_updated_e2e.yaml diff --git a/apps/mobile/apps/client/maestro/orders/rapid_to_one_time_draft_e2e.yaml b/apps/mobile/apps/client/maestro/orders/happy_path/rapid_to_one_time_draft_e2e.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/rapid_to_one_time_draft_e2e.yaml rename to apps/mobile/apps/client/maestro/orders/happy_path/rapid_to_one_time_draft_e2e.yaml diff --git a/apps/mobile/apps/client/maestro/orders/rapid_to_one_time_draft_submit_e2e.yaml b/apps/mobile/apps/client/maestro/orders/happy_path/rapid_to_one_time_draft_submit_e2e.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/rapid_to_one_time_draft_submit_e2e.yaml rename to apps/mobile/apps/client/maestro/orders/happy_path/rapid_to_one_time_draft_submit_e2e.yaml diff --git a/apps/mobile/apps/client/maestro/orders/view_orders.yaml b/apps/mobile/apps/client/maestro/orders/happy_path/view_orders.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/view_orders.yaml rename to apps/mobile/apps/client/maestro/orders/happy_path/view_orders.yaml diff --git a/apps/mobile/apps/client/maestro/orders/negative/create_order_validation_errors.yaml b/apps/mobile/apps/client/maestro/orders/negative/create_order_validation_errors.yaml new file mode 100644 index 00000000..d5cfd722 --- /dev/null +++ b/apps/mobile/apps/client/maestro/orders/negative/create_order_validation_errors.yaml @@ -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" diff --git a/apps/mobile/apps/client/maestro/orders/create_order_entry.yaml b/apps/mobile/apps/client/maestro/orders/smoke/create_order_entry.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/create_order_entry.yaml rename to apps/mobile/apps/client/maestro/orders/smoke/create_order_entry.yaml diff --git a/apps/mobile/apps/client/maestro/orders/create_order_one_time.yaml b/apps/mobile/apps/client/maestro/orders/smoke/create_order_one_time.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/create_order_one_time.yaml rename to apps/mobile/apps/client/maestro/orders/smoke/create_order_one_time.yaml diff --git a/apps/mobile/apps/client/maestro/orders/create_order_permanent_placeholder.yaml b/apps/mobile/apps/client/maestro/orders/smoke/create_order_permanent_placeholder.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/create_order_permanent_placeholder.yaml rename to apps/mobile/apps/client/maestro/orders/smoke/create_order_permanent_placeholder.yaml diff --git a/apps/mobile/apps/client/maestro/orders/create_order_rapid.yaml b/apps/mobile/apps/client/maestro/orders/smoke/create_order_rapid.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/create_order_rapid.yaml rename to apps/mobile/apps/client/maestro/orders/smoke/create_order_rapid.yaml diff --git a/apps/mobile/apps/client/maestro/orders/create_order_recurring_placeholder.yaml b/apps/mobile/apps/client/maestro/orders/smoke/create_order_recurring_placeholder.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/create_order_recurring_placeholder.yaml rename to apps/mobile/apps/client/maestro/orders/smoke/create_order_recurring_placeholder.yaml diff --git a/apps/mobile/apps/client/maestro/orders/order_type_selection_smoke.yaml b/apps/mobile/apps/client/maestro/orders/smoke/order_type_selection_smoke.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/orders/order_type_selection_smoke.yaml rename to apps/mobile/apps/client/maestro/orders/smoke/order_type_selection_smoke.yaml diff --git a/apps/mobile/apps/client/maestro/reports/reports_dashboard.yaml b/apps/mobile/apps/client/maestro/reports/happy_path/reports_dashboard.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/reports/reports_dashboard.yaml rename to apps/mobile/apps/client/maestro/reports/happy_path/reports_dashboard.yaml diff --git a/apps/mobile/apps/client/maestro/reports/smoke/no_show_report_smoke.yaml b/apps/mobile/apps/client/maestro/reports/smoke/no_show_report_smoke.yaml new file mode 100644 index 00000000..d3f0c828 --- /dev/null +++ b/apps/mobile/apps/client/maestro/reports/smoke/no_show_report_smoke.yaml @@ -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).*" diff --git a/apps/mobile/apps/client/maestro/reports/spend_report_export_smoke.yaml b/apps/mobile/apps/client/maestro/reports/smoke/spend_report_export_smoke.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/reports/spend_report_export_smoke.yaml rename to apps/mobile/apps/client/maestro/reports/smoke/spend_report_export_smoke.yaml diff --git a/apps/mobile/apps/client/maestro/settings/edit_profile.yaml b/apps/mobile/apps/client/maestro/settings/happy_path/edit_profile.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/settings/edit_profile.yaml rename to apps/mobile/apps/client/maestro/settings/happy_path/edit_profile.yaml diff --git a/apps/mobile/apps/client/maestro/settings/edit_profile_save_e2e.yaml b/apps/mobile/apps/client/maestro/settings/happy_path/edit_profile_save_e2e.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/settings/edit_profile_save_e2e.yaml rename to apps/mobile/apps/client/maestro/settings/happy_path/edit_profile_save_e2e.yaml diff --git a/apps/mobile/apps/client/maestro/settings/logout_flow.yaml b/apps/mobile/apps/client/maestro/settings/happy_path/logout_flow.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/settings/logout_flow.yaml rename to apps/mobile/apps/client/maestro/settings/happy_path/logout_flow.yaml diff --git a/apps/mobile/apps/client/maestro/settings/settings_page.yaml b/apps/mobile/apps/client/maestro/settings/happy_path/settings_page.yaml similarity index 100% rename from apps/mobile/apps/client/maestro/settings/settings_page.yaml rename to apps/mobile/apps/client/maestro/settings/happy_path/settings_page.yaml diff --git a/apps/mobile/apps/client/maestro/settings/negative/edit_profile_validation.yaml b/apps/mobile/apps/client/maestro/settings/negative/edit_profile_validation.yaml new file mode 100644 index 00000000..99b958e2 --- /dev/null +++ b/apps/mobile/apps/client/maestro/settings/negative/edit_profile_validation.yaml @@ -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 diff --git a/apps/mobile/apps/staff/maestro/auth/session_persistence.yaml b/apps/mobile/apps/staff/maestro/auth/happy_path/session_persistence.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/auth/session_persistence.yaml rename to apps/mobile/apps/staff/maestro/auth/happy_path/session_persistence.yaml diff --git a/apps/mobile/apps/staff/maestro/auth/sign_in.yaml b/apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/auth/sign_in.yaml rename to apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml diff --git a/apps/mobile/apps/staff/maestro/auth/sign_out.yaml b/apps/mobile/apps/staff/maestro/auth/happy_path/sign_out.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/auth/sign_out.yaml rename to apps/mobile/apps/staff/maestro/auth/happy_path/sign_out.yaml diff --git a/apps/mobile/apps/staff/maestro/auth/sign_up.yaml b/apps/mobile/apps/staff/maestro/auth/happy_path/sign_up.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/auth/sign_up.yaml rename to apps/mobile/apps/staff/maestro/auth/happy_path/sign_up.yaml diff --git a/apps/mobile/apps/staff/maestro/auth/sign_in_invalid_otp.yaml b/apps/mobile/apps/staff/maestro/auth/negative/sign_in_invalid_otp.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/auth/sign_in_invalid_otp.yaml rename to apps/mobile/apps/staff/maestro/auth/negative/sign_in_invalid_otp.yaml diff --git a/apps/mobile/apps/staff/maestro/availability/set_availability_e2e.yaml b/apps/mobile/apps/staff/maestro/availability/happy_path/set_availability_e2e.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/availability/set_availability_e2e.yaml rename to apps/mobile/apps/staff/maestro/availability/happy_path/set_availability_e2e.yaml diff --git a/apps/mobile/apps/staff/maestro/compliance/happy_path/attire_upload_e2e.yaml b/apps/mobile/apps/staff/maestro/compliance/happy_path/attire_upload_e2e.yaml new file mode 100644 index 00000000..7c474258 --- /dev/null +++ b/apps/mobile/apps/staff/maestro/compliance/happy_path/attire_upload_e2e.yaml @@ -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).*" diff --git a/apps/mobile/apps/staff/maestro/compliance/certificate_upload_e2e.yaml b/apps/mobile/apps/staff/maestro/compliance/happy_path/certificate_upload_e2e.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/compliance/certificate_upload_e2e.yaml rename to apps/mobile/apps/staff/maestro/compliance/happy_path/certificate_upload_e2e.yaml diff --git a/apps/mobile/apps/staff/maestro/compliance/document_upload_e2e.yaml b/apps/mobile/apps/staff/maestro/compliance/happy_path/document_upload_e2e.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/compliance/document_upload_e2e.yaml rename to apps/mobile/apps/staff/maestro/compliance/happy_path/document_upload_e2e.yaml diff --git a/apps/mobile/apps/staff/maestro/compliance/attire_upload_banner.yaml b/apps/mobile/apps/staff/maestro/compliance/smoke/attire_upload_banner.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/compliance/attire_upload_banner.yaml rename to apps/mobile/apps/staff/maestro/compliance/smoke/attire_upload_banner.yaml diff --git a/apps/mobile/apps/staff/maestro/compliance/certificate_upload_banner.yaml b/apps/mobile/apps/staff/maestro/compliance/smoke/certificate_upload_banner.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/compliance/certificate_upload_banner.yaml rename to apps/mobile/apps/staff/maestro/compliance/smoke/certificate_upload_banner.yaml diff --git a/apps/mobile/apps/staff/maestro/compliance/document_upload_banner.yaml b/apps/mobile/apps/staff/maestro/compliance/smoke/document_upload_banner.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/compliance/document_upload_banner.yaml rename to apps/mobile/apps/staff/maestro/compliance/smoke/document_upload_banner.yaml diff --git a/apps/mobile/apps/staff/maestro/home/benefits.yaml b/apps/mobile/apps/staff/maestro/home/happy_path/benefits.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/home/benefits.yaml rename to apps/mobile/apps/staff/maestro/home/happy_path/benefits.yaml diff --git a/apps/mobile/apps/staff/maestro/home/smoke/incomplete_profile_banner_smoke.yaml b/apps/mobile/apps/staff/maestro/home/smoke/incomplete_profile_banner_smoke.yaml new file mode 100644 index 00000000..9247fcb7 --- /dev/null +++ b/apps/mobile/apps/staff/maestro/home/smoke/incomplete_profile_banner_smoke.yaml @@ -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).*" diff --git a/apps/mobile/apps/staff/maestro/navigation/availability.yaml b/apps/mobile/apps/staff/maestro/navigation/smoke/availability.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/navigation/availability.yaml rename to apps/mobile/apps/staff/maestro/navigation/smoke/availability.yaml diff --git a/apps/mobile/apps/staff/maestro/navigation/clock_in.yaml b/apps/mobile/apps/staff/maestro/navigation/smoke/clock_in.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/navigation/clock_in.yaml rename to apps/mobile/apps/staff/maestro/navigation/smoke/clock_in.yaml diff --git a/apps/mobile/apps/staff/maestro/navigation/home.yaml b/apps/mobile/apps/staff/maestro/navigation/smoke/home.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/navigation/home.yaml rename to apps/mobile/apps/staff/maestro/navigation/smoke/home.yaml diff --git a/apps/mobile/apps/staff/maestro/navigation/payments.yaml b/apps/mobile/apps/staff/maestro/navigation/smoke/payments.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/navigation/payments.yaml rename to apps/mobile/apps/staff/maestro/navigation/smoke/payments.yaml diff --git a/apps/mobile/apps/staff/maestro/navigation/profile.yaml b/apps/mobile/apps/staff/maestro/navigation/smoke/profile.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/navigation/profile.yaml rename to apps/mobile/apps/staff/maestro/navigation/smoke/profile.yaml diff --git a/apps/mobile/apps/staff/maestro/navigation/shifts.yaml b/apps/mobile/apps/staff/maestro/navigation/smoke/shifts.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/navigation/shifts.yaml rename to apps/mobile/apps/staff/maestro/navigation/smoke/shifts.yaml diff --git a/apps/mobile/apps/staff/maestro/payments/payments_view_e2e.yaml b/apps/mobile/apps/staff/maestro/payments/happy_path/payments_view_e2e.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/payments/payments_view_e2e.yaml rename to apps/mobile/apps/staff/maestro/payments/happy_path/payments_view_e2e.yaml diff --git a/apps/mobile/apps/staff/maestro/payments/smoke/payment_detail_smoke.yaml b/apps/mobile/apps/staff/maestro/payments/smoke/payment_detail_smoke.yaml new file mode 100644 index 00000000..dbe79ec6 --- /dev/null +++ b/apps/mobile/apps/staff/maestro/payments/smoke/payment_detail_smoke.yaml @@ -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).*" diff --git a/apps/mobile/apps/staff/maestro/payments/payment_history_smoke.yaml b/apps/mobile/apps/staff/maestro/payments/smoke/payment_history_smoke.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/payments/payment_history_smoke.yaml rename to apps/mobile/apps/staff/maestro/payments/smoke/payment_history_smoke.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/attire.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/attire.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/attire.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/attire.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/bank_account.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/bank_account.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/bank_account.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/bank_account.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/certificates_list.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/certificates_list.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/certificates_list.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/certificates_list.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/documents_list.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/documents_list.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/documents_list.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/documents_list.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/emergency_contact.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/emergency_contact.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/emergency_contact.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/emergency_contact.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/experience.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/experience.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/experience.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/experience.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/faqs.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/faqs.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/faqs.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/faqs.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/personal_info.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/personal_info.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/personal_info.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/personal_info.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/privacy_security.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/privacy_security.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/privacy_security.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/privacy_security.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/tax_forms.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/tax_forms.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/tax_forms.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/tax_forms.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/time_card.yaml b/apps/mobile/apps/staff/maestro/profile/happy_path/time_card.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/time_card.yaml rename to apps/mobile/apps/staff/maestro/profile/happy_path/time_card.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/attire_validation_e2e.yaml b/apps/mobile/apps/staff/maestro/profile/smoke/attire_validation_e2e.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/attire_validation_e2e.yaml rename to apps/mobile/apps/staff/maestro/profile/smoke/attire_validation_e2e.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/bank_account_fields_smoke.yaml b/apps/mobile/apps/staff/maestro/profile/smoke/bank_account_fields_smoke.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/bank_account_fields_smoke.yaml rename to apps/mobile/apps/staff/maestro/profile/smoke/bank_account_fields_smoke.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/smoke/emergency_contact_save_smoke.yaml b/apps/mobile/apps/staff/maestro/profile/smoke/emergency_contact_save_smoke.yaml new file mode 100644 index 00000000..015f34b1 --- /dev/null +++ b/apps/mobile/apps/staff/maestro/profile/smoke/emergency_contact_save_smoke.yaml @@ -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).*" diff --git a/apps/mobile/apps/staff/maestro/profile/smoke/personal_info_save_smoke.yaml b/apps/mobile/apps/staff/maestro/profile/smoke/personal_info_save_smoke.yaml new file mode 100644 index 00000000..44c4fd77 --- /dev/null +++ b/apps/mobile/apps/staff/maestro/profile/smoke/personal_info_save_smoke.yaml @@ -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).*" diff --git a/apps/mobile/apps/staff/maestro/profile/tax_forms_smoke.yaml b/apps/mobile/apps/staff/maestro/profile/smoke/tax_forms_smoke.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/tax_forms_smoke.yaml rename to apps/mobile/apps/staff/maestro/profile/smoke/tax_forms_smoke.yaml diff --git a/apps/mobile/apps/staff/maestro/profile/time_card_detail_smoke.yaml b/apps/mobile/apps/staff/maestro/profile/smoke/time_card_detail_smoke.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/profile/time_card_detail_smoke.yaml rename to apps/mobile/apps/staff/maestro/profile/smoke/time_card_detail_smoke.yaml diff --git a/apps/mobile/apps/staff/maestro/shifts/incomplete_profile_banner.yaml b/apps/mobile/apps/staff/maestro/shifts/edge_cases/incomplete_profile_banner.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/shifts/incomplete_profile_banner.yaml rename to apps/mobile/apps/staff/maestro/shifts/edge_cases/incomplete_profile_banner.yaml diff --git a/apps/mobile/apps/staff/maestro/shifts/edge_cases/shifts_empty_state.yaml b/apps/mobile/apps/staff/maestro/shifts/edge_cases/shifts_empty_state.yaml new file mode 100644 index 00000000..c9609f56 --- /dev/null +++ b/apps/mobile/apps/staff/maestro/shifts/edge_cases/shifts_empty_state.yaml @@ -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).*" diff --git a/apps/mobile/apps/staff/maestro/shifts/clock_in_e2e.yaml b/apps/mobile/apps/staff/maestro/shifts/happy_path/clock_in_e2e.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/shifts/clock_in_e2e.yaml rename to apps/mobile/apps/staff/maestro/shifts/happy_path/clock_in_e2e.yaml diff --git a/apps/mobile/apps/staff/maestro/shifts/clock_out_e2e.yaml b/apps/mobile/apps/staff/maestro/shifts/happy_path/clock_out_e2e.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/shifts/clock_out_e2e.yaml rename to apps/mobile/apps/staff/maestro/shifts/happy_path/clock_out_e2e.yaml diff --git a/apps/mobile/apps/staff/maestro/shifts/find_shifts.yaml b/apps/mobile/apps/staff/maestro/shifts/happy_path/find_shifts.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/shifts/find_shifts.yaml rename to apps/mobile/apps/staff/maestro/shifts/happy_path/find_shifts.yaml diff --git a/apps/mobile/apps/staff/maestro/shifts/find_shifts_apply_smoke.yaml b/apps/mobile/apps/staff/maestro/shifts/smoke/find_shifts_apply_smoke.yaml similarity index 100% rename from apps/mobile/apps/staff/maestro/shifts/find_shifts_apply_smoke.yaml rename to apps/mobile/apps/staff/maestro/shifts/smoke/find_shifts_apply_smoke.yaml diff --git a/docs/testing/maestro-e2e-happy-paths.md b/docs/testing/maestro-e2e-happy-paths.md index 765de84a..4c895820 100644 --- a/docs/testing/maestro-e2e-happy-paths.md +++ b/docs/testing/maestro-e2e-happy-paths.md @@ -1,6 +1,6 @@ -# Maestro E2E Happy Path Test Cases +# Maestro E2E Happy Path & Extended Coverage Test Cases -This document describes the End-to-End (E2E) **happy path** test cases for the KROW mobile applications (Client and Staff), implemented with [Maestro](https://maestro.mobile.dev/). It supports **ticket #572**: implement and document E2E happy path tests so core functionalities remain stable and regressions are caught early. +This document describes the End-to-End (E2E) test cases for the KROW mobile applications (Client and Staff), implemented with [Maestro](https://maestro.mobile.dev/). It supports **ticket #572** (Happy Paths) and **ticket #636** (Extended Coverage, Negative Paths, and Structural Refactor). ## Overview @@ -8,7 +8,8 @@ This document describes the End-to-End (E2E) **happy path** test cases for the K |------|-------------| | **Framework** | Maestro | | **Apps** | Client (`com.krowwithus.client`), Staff (`com.krowwithus.staff`) | -| **Scope** | Happy path user flows only (success paths; negative/edge cases are separate) | +| **Structure** | Organized by Feature → Scenario Type (Happy Path, Smoke, Negative, Edge Cases) | +| **Total Flows** | 93 (47 Client, 46 Staff) | | **Run locally** | See [How to run](#how-to-run) and [docs/research/maestro-test-run-instructions.md](../research/maestro-test-run-instructions.md) | ## Prerequisites @@ -25,233 +26,93 @@ This document describes the End-to-End (E2E) **happy path** test cases for the K | Client | sign_in / sign_up | `TEST_CLIENT_EMAIL`, `TEST_CLIENT_PASSWORD`, `TEST_CLIENT_COMPANY` (sign_up only) | | Staff | sign_in / sign_up | `TEST_STAFF_PHONE`, `TEST_STAFF_OTP`, `TEST_STAFF_SIGNUP_PHONE` (sign_up only) | -Example (Bash): -`export TEST_CLIENT_EMAIL=testclient@gmail.com TEST_CLIENT_PASSWORD=testclient!` -`export TEST_STAFF_PHONE=5555551234 TEST_STAFF_OTP=123123` +Example (Powershell): +`$env:TEST_CLIENT_EMAIL="testclient@gmail.com"; $env:TEST_CLIENT_PASSWORD="testclient!"` +`$env:TEST_STAFF_PHONE="5555551234"; $env:TEST_STAFF_OTP="123123"` --- -## Client App — Happy Path Test Cases +## Client App — Test Cases -All client flows assume the app is **not** logged in at start unless noted (e.g. flows that run after `sign_in.yaml`). +All client flows assume the app is **not** logged in at start unless noted. ### Auth -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| C-AUTH-1 | **sign_in** | Verify user can sign in with email/password | Launch app → Sign In → enter email/password (env) → Sign In | Home tab visible, authenticated | `maestro test apps/mobile/apps/client/maestro/auth/sign_in.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...` | -| C-AUTH-2 | **sign_up** | Verify new client can register | Launch app → Create Account → email, password, company (env) → submit | Home tab visible, authenticated | Same as above + `-e TEST_CLIENT_COMPANY=...` | -| C-AUTH-3 | **sign_out** | Verify user can log out | Run after sign_in → Settings (gear) → Log Out → confirm | Create Account / login screen visible | Run `sign_in.yaml` then `auth/sign_out.yaml` (or use `settings/logout_flow.yaml` for gear-based logout) | +| ID | Test | Purpose | Path | +|----|------|----------|------------| +| C-AUTH-1 | **sign_in** | Verify user can sign in | `auth/happy_path/sign_in.yaml` | +| C-AUTH-2 | **sign_up** | Verify new client registration | `auth/happy_path/sign_up.yaml` | +| C-AUTH-3 | **sign_out** | Verify user can log out | `auth/happy_path/sign_out.yaml` | +| C-AUTH-N | **sign_in_invalid** | Negative: invalid password | `auth/negative/sign_in_invalid_password.yaml` | -### Navigation +### Navigation (Smoke) -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| C-NAV-1 | **home** | Home tab loads after login | Launch (logged in) → tap Home | "Welcome back" and home content visible | `navigation/home.yaml` after sign_in | -| C-NAV-2 | **orders** | Orders tab opens | Tap Orders | Orders list or empty state visible | `navigation/orders.yaml` | -| C-NAV-3 | **billing** | Billing tab opens | Tap Billing | Billing / invoices section visible | `navigation/billing.yaml` | -| C-NAV-4 | **coverage** | Coverage tab opens | Tap Coverage | Coverage screen visible | `navigation/coverage.yaml` | -| C-NAV-5 | **reports** | Reports tab opens | Tap Reports | Reports screen visible | `navigation/reports.yaml` | +| ID | Test | Purpose | Path | +|----|------|----------|------------| +| C-NAV-1 | **home** | Home tab loads | `navigation/smoke/home.yaml` | +| C-NAV-2 | **orders** | Orders tab opens | `navigation/smoke/orders.yaml` | +| C-NAV-3 | **billing** | Billing tab opens | `navigation/smoke/billing.yaml` | +| C-NAV-4 | **coverage** | Coverage tab opens | `navigation/smoke/coverage.yaml` | +| C-NAV-5 | **reports** | Reports tab opens | `navigation/smoke/reports.yaml` | ### Orders -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| 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 - -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| 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 - -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| 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 - -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| 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` | +| ID | Test | Purpose | Path | +|----|------|----------|------------| +| C-ORD-1 | **view_orders** | Orders list loads | `orders/happy_path/view_orders.yaml` | +| C-ORD-2 | **create_order_one_time** | Full flow: create order | `orders/happy_path/create_order_one_time_e2e.yaml` | +| C-ORD-3 | **orders_empty_state** | Edge: verify empty tabs | `orders/edge_cases/orders_empty_state.yaml` | +| C-ORD-4 | **validation_errors** | Negative: required fields | `orders/negative/create_order_validation_errors.yaml` | --- -## Staff App — Happy Path Test Cases +## Staff App — Test Cases ### Auth -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| S-AUTH-1 | **sign_in** | Staff signs in with phone + OTP | Launch → enter phone (env) → OTP (env) | Home / main app visible | `maestro test apps/mobile/apps/staff/maestro/auth/sign_in.yaml -e TEST_STAFF_PHONE=... -e TEST_STAFF_OTP=...` | -| S-AUTH-2 | **sign_up** | New staff registers with phone | Launch → sign up path → phone (env) → OTP (env) | Onboarding or home | Same + `TEST_STAFF_SIGNUP_PHONE` | -| S-AUTH-3 | **sign_out** | Staff logs out from Profile | After sign_in → Profile → Sign Out | Log In screen visible | `auth/sign_out.yaml` after sign_in | - -### Navigation - -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| S-NAV-1 | **home** | Home tab loads | Tap Home | Welcome / home content | `navigation/home.yaml` | -| S-NAV-2 | **shifts** | Shifts tab opens | Tap Shifts | Shifts list or empty state | `navigation/shifts.yaml` | -| S-NAV-3 | **profile** | Profile tab opens | Tap Profile | Profile sections visible | `navigation/profile.yaml` | -| S-NAV-4 | **payments** | Payments tab opens | Tap Payments | Payments screen | `navigation/payments.yaml` | -| S-NAV-5 | **clock_in** (tab) | Clock In tab opens | Tap Clock In | Clock In UI visible | `navigation/clock_in.yaml` | -| S-NAV-6 | **availability** | Availability screen opens | From home or profile → Availability | Availability UI | `navigation/availability.yaml` | +| ID | Test | Purpose | Path | +|----|------|----------|------------| +| S-AUTH-1 | **sign_in** | Staff signs in with phone | `auth/happy_path/sign_in.yaml` | +| S-AUTH-2 | **sign_up** | New staff registers | `auth/happy_path/sign_up.yaml` | +| S-AUTH-3 | **sign_out** | Staff logs out | `auth/happy_path/sign_out.yaml` | ### Shifts -| 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) | - -### Availability - -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| S-AVL-1 | **set_availability_e2e** | Set or view availability | Open availability → set days/times → save | Success or list updated | `availability/set_availability_e2e.yaml` | - -### Profile - -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| S-PRF-1 | **personal_info** | Personal info section opens | Profile → Personal Info | Form/section visible | `profile/personal_info.yaml` | -| S-PRF-2 | **documents_list** | Documents list opens | Profile → Documents | Documents list | `profile/documents_list.yaml` | -| 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` | - -### Compliance - -| ID | Test | Purpose | Steps | Expected outcome | How to run | -|----|------|----------|-------|-------------------|------------| -| S-CMP-1 | **document_upload_banner** | Document upload CTA visible | After sign_in → navigate to docs | Upload banner/CTA visible | `compliance/document_upload_banner.yaml` (#550) | -| 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) | +| ID | Test | Purpose | Path | +|----|------|----------|------------| +| S-SHF-1 | **find_shifts** | Find shifts list loads | `shifts/happy_path/find_shifts.yaml` | +| S-SHF-2 | **clock_in_e2e** | Clock in workflow | `shifts/happy_path/clock_in_e2e.yaml` | +| S-SHF-3 | **shifts_empty** | Edge: no shifts found | `shifts/edge_cases/shifts_empty_state.yaml` | --- ## How to run -### Make targets (recommended) - -From **project root** with env vars set: +### Make targets (Recommended) | Target | Description | |--------|-------------| -| `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 | +| `make test-e2e-setup` | Check Maestro CLI installation | +| `make test-e2e-client-auth` | Client: Sign In, Sign Up, Invalid Password | +| `make test-e2e-client-orders-negative`| Client: Form validation errors + empty states | +| `make test-e2e-staff-compliance-full` | Staff: Banners + Doc/Cert/Attire upload E2E | -### Single flow (Maestro CLI) - -```bash -# Client sign_in then create hub -maestro test --shard-split=1 \ - apps/mobile/apps/client/maestro/auth/sign_in.yaml \ - apps/mobile/apps/client/maestro/hubs/create_hub_e2e.yaml \ - -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=... - -# Staff sign_in then clock in E2E -maestro test --shard-split=1 \ - apps/mobile/apps/staff/maestro/auth/sign_in.yaml \ - apps/mobile/apps/staff/maestro/shifts/clock_in_e2e.yaml \ - -e TEST_STAFF_PHONE=... -e TEST_STAFF_OTP=... -``` - -Use `--shard-split=1` to run flows sequentially and reduce "tcp:7001 closed" issues between flows. - -### Success criteria - -- **Pass:** Maestro exits with code 0; all steps in the YAML complete (elements found, assertions passed). -- **Fail:** Any step times out or an assertion fails; Maestro exits non-zero and reports the failing step. - -### 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). - ---- +### Windows Stability Note +If you encounter `java.io.IOException: Command failed (tcp:7001): closed`, it is due to ADB connection instability on Windows. Fix: +1. **Restart Emulator** software. +2. Use `--shard-split=1` (default in Makefile). +3. Ensure timeouts are set to at least 45000ms. ## CI/CD -E2E runs in GitHub Actions: [.github/workflows/maestro-e2e.yml](../../.github/workflows/maestro-e2e.yml). It runs on: +E2E runs in GitHub Actions: [.github/workflows/maestro-e2e.yml](../../.github/workflows/maestro-e2e.yml). -- `workflow_dispatch` (manual) -- Pull requests / pushes that touch `apps/mobile/**/maestro/**` or the workflow file - -Required secrets: `TEST_CLIENT_EMAIL`, `TEST_CLIENT_PASSWORD`, `TEST_CLIENT_COMPANY`, `TEST_STAFF_PHONE`, `TEST_STAFF_OTP`, `TEST_STAFF_SIGNUP_PHONE`. +**Trigger Change:** Automated triggers (push/PR) have been **disabled** to conserve free-tier build minutes. The workflow MUST be triggered manually via the "Actions" tab. --- ## References -- [Maestro test run instructions](../research/maestro-test-run-instructions.md) — install, env vars, troubleshooting -- [Flutter testing tools](../research/flutter-testing-tools.md) — context on Maestro vs other tests -- Client Maestro README: `apps/mobile/apps/client/maestro/README.md` -- Staff Maestro README: `apps/mobile/apps/staff/maestro/README.md` +- [Maestro Documentation](https://maestro.mobile.dev/) +- [Maestro Test Run Instructions](../research/maestro-test-run-instructions.md) +- [Project Makefile](../../makefiles/mobile.mk) diff --git a/makefiles/mobile.mk b/makefiles/mobile.mk index f1d2ee2d..14cd0b7d 100644 --- a/makefiles/mobile.mk +++ b/makefiles/mobile.mk @@ -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-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 +.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 test-e2e-client-coverage test-e2e-client-orders-negative test-e2e-client-billing-extended test-e2e-client-reports-extended test-e2e-client-settings-negative test-e2e-client-hubs-extended test-e2e-staff-shifts-extended test-e2e-staff-compliance-full test-e2e-staff-profile-save test-e2e-staff-payments-extended test-e2e-staff-home-extended MOBILE_DIR := apps/mobile @@ -85,301 +85,405 @@ MAESTRO_SHARDS ?= --shard-split=1 test-e2e: test-e2e-setup @echo "--> Running full E2E suite (Client + Staff auth + negative auth flows)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml apps/mobile/apps/client/maestro/auth/sign_up.yaml apps/mobile/apps/client/maestro/auth/sign_in_invalid_password.yaml \ - apps/mobile/apps/staff/maestro/auth/sign_in.yaml apps/mobile/apps/staff/maestro/auth/sign_up.yaml apps/mobile/apps/staff/maestro/auth/sign_in_invalid_otp.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml apps/mobile/apps/client/maestro/auth/happy_path/sign_up.yaml apps/mobile/apps/client/maestro/auth/negative/sign_in_invalid_password.yaml \ + apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml apps/mobile/apps/staff/maestro/auth/happy_path/sign_up.yaml apps/mobile/apps/staff/maestro/auth/negative/sign_in_invalid_otp.yaml \ -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" -e TEST_CLIENT_INVALID_PASSWORD="$${TEST_CLIENT_INVALID_PASSWORD:-wrongpass}" \ -e TEST_CLIENT_COMPANY="$${TEST_CLIENT_COMPANY}" -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" \ -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" -e TEST_STAFF_INVALID_OTP="$${TEST_STAFF_INVALID_OTP:-000000}" -e TEST_STAFF_SIGNUP_PHONE="$${TEST_STAFF_SIGNUP_PHONE}" test-e2e-client: test-e2e-setup @echo "--> Running Client E2E (sign_in, sign_up)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml apps/mobile/apps/client/maestro/auth/sign_up.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml apps/mobile/apps/client/maestro/auth/happy_path/sign_up.yaml \ -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" \ -e TEST_CLIENT_COMPANY="$${TEST_CLIENT_COMPANY}" test-e2e-staff: test-e2e-setup @echo "--> Running Staff E2E (sign_in, sign_up)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml apps/mobile/apps/staff/maestro/auth/sign_up.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml apps/mobile/apps/staff/maestro/auth/happy_path/sign_up.yaml \ -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" \ -e TEST_STAFF_SIGNUP_PHONE="$${TEST_STAFF_SIGNUP_PHONE}" # Client E2E by folder (run folder-by-folder) test-e2e-client-auth: test-e2e-setup @echo "--> Running Client E2E auth flows (sign_in, sign_up, sign_in_invalid_password)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml apps/mobile/apps/client/maestro/auth/sign_up.yaml apps/mobile/apps/client/maestro/auth/sign_in_invalid_password.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml apps/mobile/apps/client/maestro/auth/happy_path/sign_up.yaml apps/mobile/apps/client/maestro/auth/negative/sign_in_invalid_password.yaml \ -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" -e TEST_CLIENT_INVALID_PASSWORD="$${TEST_CLIENT_INVALID_PASSWORD:-wrongpass}" \ -e TEST_CLIENT_COMPANY="$${TEST_CLIENT_COMPANY}" test-e2e-client-navigation: test-e2e-setup @echo "--> Running Client E2E navigation (sign_in first, then nav flows)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \ - apps/mobile/apps/client/maestro/navigation/home.yaml \ - apps/mobile/apps/client/maestro/navigation/orders.yaml \ - apps/mobile/apps/client/maestro/navigation/billing.yaml \ - apps/mobile/apps/client/maestro/navigation/coverage.yaml \ - apps/mobile/apps/client/maestro/navigation/reports.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/home.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/orders.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/billing.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/coverage.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/reports.yaml \ -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" test-e2e-client-orders: test-e2e-setup @echo "--> Running Client E2E orders (sign_in first, then order flows)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \ - apps/mobile/apps/client/maestro/orders/view_orders.yaml \ - apps/mobile/apps/client/maestro/orders/completed_no_edit_icon.yaml \ - apps/mobile/apps/client/maestro/orders/create_order_entry.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/orders/happy_path/view_orders.yaml \ + apps/mobile/apps/client/maestro/orders/edge_cases/completed_no_edit_icon.yaml \ + apps/mobile/apps/client/maestro/orders/smoke/create_order_entry.yaml \ -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" test-e2e-client-settings: test-e2e-setup @echo "--> Running Client E2E settings (sign_in first, then settings + edit_profile)..." - @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.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/settings/happy_path/settings_page.yaml \ + apps/mobile/apps/client/maestro/settings/happy_path/edit_profile.yaml \ -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" test-e2e-client-sign-out: test-e2e-setup @echo "--> Running Client E2E sign out..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \ - apps/mobile/apps/client/maestro/auth/sign_out.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/auth/happy_path/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/home/smoke/tab_bar_roundtrip.yaml \ + apps/mobile/apps/client/maestro/home/smoke/home_dashboard_widgets.yaml \ + apps/mobile/apps/client/maestro/orders/smoke/create_order_entry.yaml \ + apps/mobile/apps/client/maestro/settings/happy_path/settings_page.yaml \ + apps/mobile/apps/client/maestro/settings/happy_path/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/hubs/happy_path/manage_hubs_from_settings.yaml \ + apps/mobile/apps/client/maestro/hubs/happy_path/edit_hub_e2e.yaml \ + apps/mobile/apps/client/maestro/hubs/happy_path/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/billing/happy_path/billing_overview.yaml \ + apps/mobile/apps/client/maestro/billing/smoke/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/reports/happy_path/reports_dashboard.yaml \ + apps/mobile/apps/client/maestro/reports/smoke/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/settings/happy_path/settings_page.yaml \ + apps/mobile/apps/client/maestro/settings/happy_path/edit_profile_save_e2e.yaml \ + apps/mobile/apps/client/maestro/settings/happy_path/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/orders/smoke/create_order_entry.yaml \ + apps/mobile/apps/client/maestro/orders/smoke/create_order_rapid.yaml \ + apps/mobile/apps/client/maestro/orders/happy_path/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/orders/happy_path/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)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml \ - apps/mobile/apps/client/maestro/hubs/create_hub_e2e.yaml \ - apps/mobile/apps/client/maestro/orders/create_order_one_time_e2e.yaml \ - apps/mobile/apps/client/maestro/billing/billing_overview.yaml \ - apps/mobile/apps/client/maestro/billing/invoice_approval_e2e.yaml \ - apps/mobile/apps/client/maestro/reports/reports_dashboard.yaml \ - apps/mobile/apps/client/maestro/settings/logout_flow.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/hubs/happy_path/create_hub_e2e.yaml \ + apps/mobile/apps/client/maestro/orders/happy_path/create_order_one_time_e2e.yaml \ + apps/mobile/apps/client/maestro/billing/happy_path/billing_overview.yaml \ + apps/mobile/apps/client/maestro/billing/happy_path/invoice_approval_e2e.yaml \ + apps/mobile/apps/client/maestro/reports/happy_path/reports_dashboard.yaml \ + apps/mobile/apps/client/maestro/settings/happy_path/logout_flow.yaml \ -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" # Client extended (auth + navigation + orders + settings) test-e2e-client-extended: test-e2e-setup @echo "--> Running Client E2E extended suite..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml apps/mobile/apps/client/maestro/auth/sign_up.yaml \ - apps/mobile/apps/client/maestro/navigation/home.yaml apps/mobile/apps/client/maestro/navigation/orders.yaml \ - apps/mobile/apps/client/maestro/navigation/billing.yaml apps/mobile/apps/client/maestro/navigation/coverage.yaml \ - apps/mobile/apps/client/maestro/navigation/reports.yaml apps/mobile/apps/client/maestro/orders/view_orders.yaml \ - apps/mobile/apps/client/maestro/orders/completed_no_edit_icon.yaml apps/mobile/apps/client/maestro/orders/create_order_entry.yaml \ - apps/mobile/apps/client/maestro/settings/settings_page.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml apps/mobile/apps/client/maestro/auth/happy_path/sign_up.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/home.yaml apps/mobile/apps/client/maestro/navigation/smoke/orders.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/billing.yaml apps/mobile/apps/client/maestro/navigation/smoke/coverage.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/reports.yaml apps/mobile/apps/client/maestro/orders/happy_path/view_orders.yaml \ + apps/mobile/apps/client/maestro/orders/edge_cases/completed_no_edit_icon.yaml apps/mobile/apps/client/maestro/orders/smoke/create_order_entry.yaml \ + apps/mobile/apps/client/maestro/settings/happy_path/settings_page.yaml \ -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" \ -e TEST_CLIENT_COMPANY="$${TEST_CLIENT_COMPANY}" +# ============================================================================= +# #636 — Enhanced Coverage: Phase 1 (Client) +# ============================================================================= + +# Client Coverage — filter navigation + empty state (#636) +test-e2e-client-coverage: test-e2e-setup + @echo "--> Running Client E2E coverage suite (filter + empty state)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/coverage/happy_path/coverage_overview.yaml \ + apps/mobile/apps/client/maestro/coverage/smoke/coverage_filter_smoke.yaml \ + apps/mobile/apps/client/maestro/coverage/edge_cases/coverage_empty_state.yaml \ + -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" + +# Client Orders — negative / edge cases: validation errors + empty state (#636) +test-e2e-client-orders-negative: test-e2e-setup + @echo "--> Running Client E2E orders negative suite (validation errors + empty state)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/orders/edge_cases/orders_empty_state.yaml \ + apps/mobile/apps/client/maestro/orders/negative/create_order_validation_errors.yaml \ + -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" + +# Client Billing — extended: overview + empty state (#636) +test-e2e-client-billing-extended: test-e2e-setup + @echo "--> Running Client E2E billing extended suite (overview + empty state)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/billing/happy_path/billing_overview.yaml \ + apps/mobile/apps/client/maestro/billing/edge_cases/billing_empty_state.yaml \ + apps/mobile/apps/client/maestro/billing/smoke/invoice_details_smoke.yaml \ + -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" + +# Client Reports — extended: dashboard + spend export + no-show (#636) +test-e2e-client-reports-extended: test-e2e-setup + @echo "--> Running Client E2E reports extended suite (dashboard + spend + no-show)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/reports/happy_path/reports_dashboard.yaml \ + apps/mobile/apps/client/maestro/reports/smoke/spend_report_export_smoke.yaml \ + apps/mobile/apps/client/maestro/reports/smoke/no_show_report_smoke.yaml \ + -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" + +# Client Settings — negative: edit profile validation errors (#636) +test-e2e-client-settings-negative: test-e2e-setup + @echo "--> Running Client E2E settings negative suite (profile validation errors)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/settings/negative/edit_profile_validation.yaml \ + -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" + +# Client Hubs — extended: manage + create/edit/delete + empty state (#636) +test-e2e-client-hubs-extended: test-e2e-setup + @echo "--> Running Client E2E hubs extended suite (manage + CRUD + empty state)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/client/maestro/hubs/edge_cases/hub_empty_state.yaml \ + apps/mobile/apps/client/maestro/hubs/happy_path/manage_hubs_from_settings.yaml \ + apps/mobile/apps/client/maestro/hubs/happy_path/edit_hub_e2e.yaml \ + apps/mobile/apps/client/maestro/hubs/happy_path/delete_hub_e2e.yaml \ + -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" + # Staff E2E by folder (run folder-by-folder) test-e2e-staff-auth: test-e2e-setup @echo "--> Running Staff E2E auth flows (sign_in, sign_up, sign_in_invalid_otp)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml apps/mobile/apps/staff/maestro/auth/sign_up.yaml apps/mobile/apps/staff/maestro/auth/sign_in_invalid_otp.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml apps/mobile/apps/staff/maestro/auth/happy_path/sign_up.yaml apps/mobile/apps/staff/maestro/auth/negative/sign_in_invalid_otp.yaml \ -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" -e TEST_STAFF_INVALID_OTP="$${TEST_STAFF_INVALID_OTP:-000000}" \ -e TEST_STAFF_SIGNUP_PHONE="$${TEST_STAFF_SIGNUP_PHONE}" test-e2e-staff-navigation: test-e2e-setup @echo "--> Running Staff E2E navigation (sign_in first, then navigation flows)..." - @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/profile.yaml \ - apps/mobile/apps/staff/maestro/navigation/payments.yaml \ - apps/mobile/apps/staff/maestro/navigation/clock_in.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/home.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/shifts.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/profile.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/payments.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/clock_in.yaml \ -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" test-e2e-staff-profile: test-e2e-setup @echo "--> Running Staff E2E profile (sign_in first, then profile flows)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \ - apps/mobile/apps/staff/maestro/profile/personal_info.yaml \ - apps/mobile/apps/staff/maestro/profile/documents_list.yaml \ - apps/mobile/apps/staff/maestro/profile/certificates_list.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/personal_info.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/documents_list.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/certificates_list.yaml \ -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" test-e2e-staff-profile-extended: test-e2e-setup @echo "--> Running Staff E2E profile extended (personal_info, documents, certificates, timecard, bank_account, faqs, privacy, emergency_contact)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \ - apps/mobile/apps/staff/maestro/profile/personal_info.yaml \ - apps/mobile/apps/staff/maestro/profile/documents_list.yaml \ - apps/mobile/apps/staff/maestro/profile/certificates_list.yaml \ - apps/mobile/apps/staff/maestro/profile/time_card.yaml \ - apps/mobile/apps/staff/maestro/profile/bank_account.yaml \ - apps/mobile/apps/staff/maestro/profile/faqs.yaml \ - apps/mobile/apps/staff/maestro/profile/privacy_security.yaml \ - apps/mobile/apps/staff/maestro/profile/emergency_contact.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/personal_info.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/documents_list.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/certificates_list.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/time_card.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/bank_account.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/faqs.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/privacy_security.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/emergency_contact.yaml \ -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" test-e2e-staff-sign-out: test-e2e-setup @echo "--> Running Staff E2E sign out..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \ - apps/mobile/apps/staff/maestro/auth/sign_out.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/auth/happy_path/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/home.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/shifts.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/payments.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/profile.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/personal_info.yaml \ + apps/mobile/apps/staff/maestro/home/happy_path/benefits.yaml \ + apps/mobile/apps/staff/maestro/auth/happy_path/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/profile/smoke/time_card_detail_smoke.yaml \ + apps/mobile/apps/staff/maestro/profile/smoke/bank_account_fields_smoke.yaml \ + apps/mobile/apps/staff/maestro/profile/smoke/tax_forms_smoke.yaml \ + apps/mobile/apps/staff/maestro/profile/smoke/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/payments/smoke/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/shifts/smoke/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 \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/compliance/happy_path/document_upload_e2e.yaml \ + apps/mobile/apps/staff/maestro/compliance/happy_path/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 \ - apps/mobile/apps/staff/maestro/shifts/find_shifts.yaml \ - apps/mobile/apps/staff/maestro/shifts/incomplete_profile_banner.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/shifts/happy_path/find_shifts.yaml \ + apps/mobile/apps/staff/maestro/shifts/edge_cases/incomplete_profile_banner.yaml \ -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" test-e2e-staff-compliance: test-e2e-setup @echo "--> Running Staff E2E compliance (sign_in first, then compliance flows)..." @maestro test $(MAESTRO_SHARDS) \ - apps/mobile/apps/staff/maestro/auth/sign_in.yaml \ - apps/mobile/apps/staff/maestro/compliance/document_upload_banner.yaml \ - apps/mobile/apps/staff/maestro/compliance/certificate_upload_banner.yaml \ - apps/mobile/apps/staff/maestro/compliance/attire_upload_banner.yaml \ + apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/compliance/smoke/document_upload_banner.yaml \ + apps/mobile/apps/staff/maestro/compliance/smoke/certificate_upload_banner.yaml \ + apps/mobile/apps/staff/maestro/compliance/smoke/attire_upload_banner.yaml \ -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" test-e2e-staff-home: test-e2e-setup @echo "--> Running Staff E2E home (sign_in first, then home flows)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \ - apps/mobile/apps/staff/maestro/home/benefits.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/home/happy_path/benefits.yaml \ -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" # Staff happy path (auth + clock in/out + availability + document upload + payments + sign out) — #572 test-e2e-staff-happy-path: test-e2e-setup @echo "--> Running Staff E2E happy path (clock in/out, availability, document upload, payments, sign out)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml \ - apps/mobile/apps/staff/maestro/shifts/clock_in_e2e.yaml \ - apps/mobile/apps/staff/maestro/shifts/clock_out_e2e.yaml \ - apps/mobile/apps/staff/maestro/availability/set_availability_e2e.yaml \ - apps/mobile/apps/staff/maestro/compliance/document_upload_e2e.yaml \ - apps/mobile/apps/staff/maestro/payments/payments_view_e2e.yaml \ - apps/mobile/apps/staff/maestro/auth/sign_out.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/shifts/happy_path/clock_in_e2e.yaml \ + apps/mobile/apps/staff/maestro/shifts/happy_path/clock_out_e2e.yaml \ + apps/mobile/apps/staff/maestro/availability/happy_path/set_availability_e2e.yaml \ + apps/mobile/apps/staff/maestro/compliance/happy_path/document_upload_e2e.yaml \ + apps/mobile/apps/staff/maestro/payments/happy_path/payments_view_e2e.yaml \ + apps/mobile/apps/staff/maestro/auth/happy_path/sign_out.yaml \ -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" # Staff extended (auth + navigation + profile + compliance + shifts + benefits) test-e2e-staff-extended: test-e2e-setup @echo "--> Running Staff E2E extended suite..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/sign_in.yaml apps/mobile/apps/staff/maestro/auth/sign_up.yaml \ - apps/mobile/apps/staff/maestro/navigation/home.yaml apps/mobile/apps/staff/maestro/navigation/shifts.yaml \ - apps/mobile/apps/staff/maestro/navigation/profile.yaml apps/mobile/apps/staff/maestro/navigation/payments.yaml \ - apps/mobile/apps/staff/maestro/navigation/clock_in.yaml apps/mobile/apps/staff/maestro/profile/personal_info.yaml \ - apps/mobile/apps/staff/maestro/profile/documents_list.yaml apps/mobile/apps/staff/maestro/profile/certificates_list.yaml \ - apps/mobile/apps/staff/maestro/shifts/find_shifts.yaml apps/mobile/apps/staff/maestro/compliance/document_upload_banner.yaml \ - apps/mobile/apps/staff/maestro/compliance/certificate_upload_banner.yaml apps/mobile/apps/staff/maestro/compliance/attire_upload_banner.yaml \ - apps/mobile/apps/staff/maestro/shifts/incomplete_profile_banner.yaml apps/mobile/apps/staff/maestro/home/benefits.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml apps/mobile/apps/staff/maestro/auth/happy_path/sign_up.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/home.yaml apps/mobile/apps/staff/maestro/navigation/smoke/shifts.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/profile.yaml apps/mobile/apps/staff/maestro/navigation/smoke/payments.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/clock_in.yaml apps/mobile/apps/staff/maestro/profile/happy_path/personal_info.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/documents_list.yaml apps/mobile/apps/staff/maestro/profile/happy_path/certificates_list.yaml \ + apps/mobile/apps/staff/maestro/shifts/happy_path/find_shifts.yaml apps/mobile/apps/staff/maestro/compliance/smoke/document_upload_banner.yaml \ + apps/mobile/apps/staff/maestro/compliance/smoke/certificate_upload_banner.yaml apps/mobile/apps/staff/maestro/compliance/smoke/attire_upload_banner.yaml \ + apps/mobile/apps/staff/maestro/shifts/edge_cases/incomplete_profile_banner.yaml apps/mobile/apps/staff/maestro/home/happy_path/benefits.yaml \ -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" \ -e TEST_STAFF_SIGNUP_PHONE="$${TEST_STAFF_SIGNUP_PHONE}" # Extended E2E: auth + navigation + compliance + feature flows (both apps) test-e2e-extended: test-e2e-setup @echo "--> Running extended E2E suite (auth, navigation, compliance, feature flows)..." - @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/sign_in.yaml apps/mobile/apps/client/maestro/auth/sign_up.yaml \ - apps/mobile/apps/client/maestro/navigation/home.yaml apps/mobile/apps/client/maestro/navigation/orders.yaml \ - apps/mobile/apps/client/maestro/navigation/billing.yaml apps/mobile/apps/client/maestro/navigation/coverage.yaml \ - apps/mobile/apps/client/maestro/navigation/reports.yaml apps/mobile/apps/client/maestro/orders/view_orders.yaml \ - apps/mobile/apps/client/maestro/orders/completed_no_edit_icon.yaml apps/mobile/apps/client/maestro/orders/create_order_entry.yaml \ - apps/mobile/apps/client/maestro/settings/settings_page.yaml \ - apps/mobile/apps/staff/maestro/auth/sign_in.yaml apps/mobile/apps/staff/maestro/auth/sign_up.yaml \ - apps/mobile/apps/staff/maestro/navigation/home.yaml apps/mobile/apps/staff/maestro/navigation/shifts.yaml \ - apps/mobile/apps/staff/maestro/navigation/profile.yaml apps/mobile/apps/staff/maestro/navigation/payments.yaml \ - apps/mobile/apps/staff/maestro/navigation/clock_in.yaml apps/mobile/apps/staff/maestro/profile/personal_info.yaml \ - apps/mobile/apps/staff/maestro/profile/documents_list.yaml apps/mobile/apps/staff/maestro/profile/certificates_list.yaml \ - apps/mobile/apps/staff/maestro/shifts/find_shifts.yaml apps/mobile/apps/staff/maestro/compliance/document_upload_banner.yaml \ - apps/mobile/apps/staff/maestro/compliance/certificate_upload_banner.yaml apps/mobile/apps/staff/maestro/compliance/attire_upload_banner.yaml \ - apps/mobile/apps/staff/maestro/shifts/incomplete_profile_banner.yaml apps/mobile/apps/staff/maestro/home/benefits.yaml \ + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/client/maestro/auth/happy_path/sign_in.yaml apps/mobile/apps/client/maestro/auth/happy_path/sign_up.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/home.yaml apps/mobile/apps/client/maestro/navigation/smoke/orders.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/billing.yaml apps/mobile/apps/client/maestro/navigation/smoke/coverage.yaml \ + apps/mobile/apps/client/maestro/navigation/smoke/reports.yaml apps/mobile/apps/client/maestro/orders/happy_path/view_orders.yaml \ + apps/mobile/apps/client/maestro/orders/edge_cases/completed_no_edit_icon.yaml apps/mobile/apps/client/maestro/orders/smoke/create_order_entry.yaml \ + apps/mobile/apps/client/maestro/settings/happy_path/settings_page.yaml \ + apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml apps/mobile/apps/staff/maestro/auth/happy_path/sign_up.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/home.yaml apps/mobile/apps/staff/maestro/navigation/smoke/shifts.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/profile.yaml apps/mobile/apps/staff/maestro/navigation/smoke/payments.yaml \ + apps/mobile/apps/staff/maestro/navigation/smoke/clock_in.yaml apps/mobile/apps/staff/maestro/profile/happy_path/personal_info.yaml \ + apps/mobile/apps/staff/maestro/profile/happy_path/documents_list.yaml apps/mobile/apps/staff/maestro/profile/happy_path/certificates_list.yaml \ + apps/mobile/apps/staff/maestro/shifts/happy_path/find_shifts.yaml apps/mobile/apps/staff/maestro/compliance/smoke/document_upload_banner.yaml \ + apps/mobile/apps/staff/maestro/compliance/smoke/certificate_upload_banner.yaml apps/mobile/apps/staff/maestro/compliance/smoke/attire_upload_banner.yaml \ + apps/mobile/apps/staff/maestro/shifts/edge_cases/incomplete_profile_banner.yaml apps/mobile/apps/staff/maestro/home/happy_path/benefits.yaml \ -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" \ -e TEST_CLIENT_COMPANY="$${TEST_CLIENT_COMPANY}" -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" \ -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" -e TEST_STAFF_SIGNUP_PHONE="$${TEST_STAFF_SIGNUP_PHONE}" + +# ============================================================================= +# #636 — Enhanced Coverage: Phase 2 (Staff) +# ============================================================================= + +# Staff Shifts — extended: find shifts + empty state (#636) +test-e2e-staff-shifts-extended: test-e2e-setup + @echo "--> Running Staff E2E shifts extended suite (find shifts + empty state)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/shifts/happy_path/find_shifts.yaml \ + apps/mobile/apps/staff/maestro/shifts/edge_cases/shifts_empty_state.yaml \ + apps/mobile/apps/staff/maestro/shifts/smoke/find_shifts_apply_smoke.yaml \ + -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" + +# Staff Compliance — full: banners + document + certificate + attire upload E2E (#636) +test-e2e-staff-compliance-full: test-e2e-setup + @echo "--> Running Staff E2E compliance full suite (banners + all upload E2E)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/compliance/smoke/document_upload_banner.yaml \ + apps/mobile/apps/staff/maestro/compliance/smoke/certificate_upload_banner.yaml \ + apps/mobile/apps/staff/maestro/compliance/smoke/attire_upload_banner.yaml \ + apps/mobile/apps/staff/maestro/compliance/happy_path/attire_upload_e2e.yaml \ + -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" + +# Staff Profile — save flows: personal info + emergency contact save (#636) +test-e2e-staff-profile-save: test-e2e-setup + @echo "--> Running Staff E2E profile save suite (personal info + emergency contact)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/profile/smoke/personal_info_save_smoke.yaml \ + apps/mobile/apps/staff/maestro/profile/smoke/emergency_contact_save_smoke.yaml \ + -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" + +# Staff Payments — extended: payments view + payment detail (#636) +test-e2e-staff-payments-extended: test-e2e-setup + @echo "--> Running Staff E2E payments extended suite (view + detail)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/payments/happy_path/payments_view_e2e.yaml \ + apps/mobile/apps/staff/maestro/payments/smoke/payment_history_smoke.yaml \ + apps/mobile/apps/staff/maestro/payments/smoke/payment_detail_smoke.yaml \ + -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}" + +# Staff Home — extended: benefits + incomplete profile banner (#636) +test-e2e-staff-home-extended: test-e2e-setup + @echo "--> Running Staff E2E home extended suite (benefits + incomplete profile banner)..." + @maestro test $(MAESTRO_SHARDS) apps/mobile/apps/staff/maestro/auth/happy_path/sign_in.yaml \ + apps/mobile/apps/staff/maestro/home/happy_path/benefits.yaml \ + apps/mobile/apps/staff/maestro/home/smoke/incomplete_profile_banner_smoke.yaml \ + -e TEST_STAFF_PHONE="$${TEST_STAFF_PHONE}" -e TEST_STAFF_OTP="$${TEST_STAFF_OTP}"