maestro improvise
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
# Client App — E2E: Session Persistence Across Relaunch
|
||||||
|
# Purpose:
|
||||||
|
# - Log in via sign_in.yaml
|
||||||
|
# - Stop the app
|
||||||
|
# - Relaunch and verify user is still logged in (bypass login screen)
|
||||||
|
#
|
||||||
|
# Run:
|
||||||
|
# maestro test \
|
||||||
|
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
||||||
|
# apps/mobile/apps/client/maestro/auth/session_persistence.yaml \
|
||||||
|
# -e TEST_CLIENT_EMAIL=... \
|
||||||
|
# -e TEST_CLIENT_PASSWORD=...
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# Perform a full stop to clear memory (not just backgrounding)
|
||||||
|
- stopApp
|
||||||
|
|
||||||
|
# Relaunch - should NOT show the login screen
|
||||||
|
- launchApp
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Home|Orders|Welcome).*"
|
||||||
|
timeout: 15000
|
||||||
|
|
||||||
|
# Verification: Log out to ensure clean state for next test
|
||||||
|
# Open Settings via header gear icon (top-right)
|
||||||
|
- 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"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,22 +1,51 @@
|
|||||||
# Client App — Sign In flow
|
# Client App — Sign In flow
|
||||||
# Credentials via env: TEST_CLIENT_EMAIL, TEST_CLIENT_PASSWORD
|
|
||||||
# Run: maestro test apps/mobile/apps/client/maestro/auth/sign_in.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...
|
|
||||||
# Or: export MAESTRO_TEST_CLIENT_EMAIL / MAESTRO_TEST_CLIENT_PASSWORD (Maestro auto-reads MAESTRO_*)
|
|
||||||
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
env:
|
env:
|
||||||
EMAIL: ${TEST_CLIENT_EMAIL}
|
EMAIL: ${TEST_CLIENT_EMAIL}
|
||||||
PASSWORD: ${TEST_CLIENT_PASSWORD}
|
PASSWORD: ${TEST_CLIENT_PASSWORD}
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
- assertVisible: "Sign In"
|
clearState: true
|
||||||
- tapOn: "Sign In"
|
- extendedWaitUntil:
|
||||||
- assertVisible: "Email"
|
visible:
|
||||||
|
text: "(?i).*(Sign In|Log In|Welcome).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
|
# Try tap by both ID and Text for maximum reliability
|
||||||
- tapOn:
|
- tapOn:
|
||||||
id: sign_in_email
|
id: "client_landing_sign_in"
|
||||||
|
optional: true
|
||||||
|
- tapOn:
|
||||||
|
text: "(?i)Sign In"
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Email"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
- tapOn:
|
||||||
|
id: "sign_in_email"
|
||||||
- inputText: ${EMAIL}
|
- inputText: ${EMAIL}
|
||||||
|
|
||||||
- tapOn:
|
- tapOn:
|
||||||
id: sign_in_password
|
id: "sign_in_password"
|
||||||
- inputText: ${PASSWORD}
|
- inputText: ${PASSWORD}
|
||||||
- tapOn: "Sign In"
|
|
||||||
- assertVisible: "Home"
|
# In the form, just tap Sign In text
|
||||||
|
- 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
|
||||||
|
|
||||||
|
- assertVisible: "(?i).*(Home|Orders|Welcome).*"
|
||||||
|
|||||||
@@ -21,3 +21,6 @@ env:
|
|||||||
visible: "Invalid"
|
visible: "Invalid"
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
- assertVisible: "Sign In"
|
- assertVisible: "Sign In"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,3 +20,6 @@ appId: com.krowwithus.client
|
|||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Create Account"
|
visible: "Create Account"
|
||||||
timeout: 20000
|
timeout: 20000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,3 +33,6 @@ env:
|
|||||||
- inputText: ${PASSWORD}
|
- inputText: ${PASSWORD}
|
||||||
- tapOn: "Create Account"
|
- tapOn: "Create Account"
|
||||||
- assertVisible: "Home"
|
- assertVisible: "Home"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
# Client App — Billing tab overview widgets
|
# Client App — Billing overview
|
||||||
# Verifies Billing tab navigation plus key billing metrics/sections.
|
|
||||||
# Run:
|
|
||||||
# maestro test \
|
|
||||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
|
||||||
# apps/mobile/apps/client/maestro/billing/billing_overview.yaml \
|
|
||||||
# -e TEST_CLIENT_EMAIL=... \
|
|
||||||
# -e TEST_CLIENT_PASSWORD=...
|
|
||||||
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
|
clearState: false
|
||||||
# Navigate to Billing tab
|
- extendedWaitUntil:
|
||||||
- tapOn: "Billing"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Current Period"
|
visible: "(?i)Billing"
|
||||||
timeout: 10000
|
timeout: 30000
|
||||||
|
|
||||||
# Verify key labels from client_billing translations that always appear
|
- tapOn: "(?i)Billing"
|
||||||
- assertVisible: "Current Period"
|
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Current Period"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
- assertVisible: "(?i)Current Period"
|
||||||
|
|||||||
@@ -51,3 +51,18 @@ appId: com.krowwithus.client
|
|||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Invoice approved and payment initiated"
|
visible: "Invoice approved and payment initiated"
|
||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
|
||||||
|
# Post-Action State Verification:
|
||||||
|
# After approval, we confirm we are back on the 'Invoices' screen and the count has updated (or the item is gone)
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "Awaiting Approval"
|
||||||
|
timeout: 10000
|
||||||
|
|
||||||
|
# Optionally, verify the 'Review & Approve' button for that specific invoice is gone.
|
||||||
|
- assertNotVisible:
|
||||||
|
text: "Review & Approve"
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,22 +21,30 @@ appId: com.krowwithus.client
|
|||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
|
||||||
# If there are invoices ready, open one and verify details actions (optional)
|
# If there are invoices ready, open one and verify details actions (optional)
|
||||||
- tapOn: "Invoice Ready"
|
- tapOn:
|
||||||
|
text: "Invoice Ready"
|
||||||
optional: true
|
optional: true
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Download Invoice PDF"
|
visible: "Download Invoice PDF"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
optional: true
|
optional: true
|
||||||
- assertVisible: "Download Invoice PDF"
|
- assertVisible:
|
||||||
|
text: "Download Invoice PDF"
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
# Otherwise, validate deterministic empty states (still a valid smoke outcome)
|
# Otherwise, validate deterministic empty states (still a valid smoke outcome)
|
||||||
- assertVisible: "No invoices ready yet"
|
- assertVisible:
|
||||||
|
text: "No invoices ready yet"
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
- assertVisible: "No Invoices for the selected period"
|
- assertVisible:
|
||||||
|
text: "No Invoices for the selected period"
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
# Always end by asserting we are still in Billing context
|
# Always end by asserting we are still in Billing context
|
||||||
- assertVisible: "Current Period"
|
- assertVisible: "Current Period"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,45 +1,35 @@
|
|||||||
# Client App — Home dashboard widgets & quick actions
|
# Client App — Home dashboard widgets & quick actions
|
||||||
# Verifies key widgets (Actions, Coverage, Spending, Live Activity) render
|
|
||||||
# and that Actions quick links can navigate into create order.
|
|
||||||
# Run:
|
|
||||||
# maestro test \
|
|
||||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
|
||||||
# apps/mobile/apps/client/maestro/home/home_dashboard_widgets.yaml \
|
|
||||||
# -e TEST_CLIENT_EMAIL=... \
|
|
||||||
# -e TEST_CLIENT_PASSWORD=...
|
|
||||||
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
|
clearState: false
|
||||||
# Make sure we're on the Home tab and content has loaded
|
|
||||||
- tapOn: "Home"
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Welcome back"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
timeout: 15000
|
timeout: 45000
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Create Order\\nSchedule shifts"
|
visible: "(?i)Home"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Home"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Welcome back|Home).*"
|
||||||
timeout: 20000
|
timeout: 20000
|
||||||
|
|
||||||
# Note: In normal mode the dashboard widgets do NOT render section titles
|
- extendedWaitUntil:
|
||||||
# like "Quick Actions" (those titles only exist in edit mode wrappers).
|
visible: "(?i)Create Order.*Schedule.*"
|
||||||
# So we assert on the always-present action cards instead.
|
timeout: 30000
|
||||||
|
|
||||||
# Verify Actions widget buttons via accessibility labels (they include subtitle on new line)
|
- assertVisible: "(?i)RAPID.*Urgent.*"
|
||||||
- assertVisible: "RAPID\\nUrgent same-day"
|
- assertVisible: "(?i)Create Order.*Schedule.*"
|
||||||
- assertVisible: "Create Order\\nSchedule shifts"
|
|
||||||
|
|
||||||
# Open Create Order from Home quick action and verify we reach Create Order screen
|
- tapOn: "(?i)Create Order.*Schedule.*"
|
||||||
- tapOn: "Create Order\\nSchedule shifts"
|
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Create Order"
|
visible: "(?i)Create Order"
|
||||||
timeout: 10000
|
timeout: 15000
|
||||||
|
|
||||||
- assertVisible: "ORDER TYPE"
|
|
||||||
- assertVisible: "RAPID\\nURGENT same-day Coverage"
|
|
||||||
- assertVisible: "One-Time\\nSingle Event or Shift Request"
|
|
||||||
- assertVisible: "Recurring\\nOngoing Weekly / Monthly Coverage"
|
|
||||||
- assertVisible: "Permanent\\nLong-Term Staffing Placement"
|
|
||||||
|
|
||||||
|
- assertVisible: "(?i)ORDER TYPE"
|
||||||
|
- assertVisible: "(?i)RAPID.*URGENT.*"
|
||||||
|
- assertVisible: "(?i)One-Time.*Single Event.*"
|
||||||
|
|||||||
@@ -37,3 +37,7 @@ appId: com.krowwithus.client
|
|||||||
- tapOn: "Home"
|
- tapOn: "Home"
|
||||||
- assertVisible: "Welcome back"
|
- assertVisible: "Welcome back"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -60,3 +60,15 @@ appId: com.krowwithus.client
|
|||||||
visible: "Hubs\nManage clock-in locations"
|
visible: "Hubs\nManage clock-in locations"
|
||||||
timeout: 20000
|
timeout: 20000
|
||||||
|
|
||||||
|
# Post-Action State Verification:
|
||||||
|
# Verify the newly created hub name is in the list
|
||||||
|
- scrollUntilVisible:
|
||||||
|
element: "E2E Hub Automation"
|
||||||
|
visibilityPercentage: 50
|
||||||
|
timeout: 10000
|
||||||
|
- assertVisible: "E2E Hub Automation"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -78,3 +78,7 @@ appId: com.krowwithus.client
|
|||||||
visible: "Hub deleted successfully"
|
visible: "Hub deleted successfully"
|
||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -84,3 +84,7 @@ appId: com.krowwithus.client
|
|||||||
visible: "Hub updated successfully"
|
visible: "Hub updated successfully"
|
||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,60 +1,49 @@
|
|||||||
# Client App — Manage Hubs via Settings quick link
|
# Client App — Manage Hubs via Settings quick link
|
||||||
# Covers navigation from Settings → Clock-In Hubs, basic Hubs page content,
|
|
||||||
# and Add Hub form validation messages.
|
|
||||||
# Run:
|
|
||||||
# maestro test \
|
|
||||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
|
||||||
# apps/mobile/apps/client/maestro/hubs/manage_hubs_from_settings.yaml \
|
|
||||||
# -e TEST_CLIENT_EMAIL=... \
|
|
||||||
# -e TEST_CLIENT_PASSWORD=...
|
|
||||||
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
|
clearState: false
|
||||||
# Ensure we're on Home (where the gear icon exists in header)
|
|
||||||
- tapOn: "Home"
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Welcome back"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Home"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Home"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Welcome back|Home).*"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
# Open Settings via stable semantic ID
|
||||||
|
- tapOn:
|
||||||
|
id: "client_home_settings"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*Quick Links.*"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
- assertVisible: "(?i)Profile"
|
||||||
|
- assertVisible: "(?i)Clock-In Hubs"
|
||||||
|
|
||||||
|
- tapOn: "(?i)Clock-In Hubs"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*Hubs.*"
|
||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
|
||||||
# Open Settings from the main shell header (gear icon, top-right)
|
- assertVisible: "(?i).*Add Hub.*"
|
||||||
- tapOn:
|
|
||||||
point: "92%,10%"
|
|
||||||
|
|
||||||
# Wait for Settings content to load (profile + quick links)
|
- tapOn: "(?i)Add Hub"
|
||||||
- extendedWaitUntil:
|
|
||||||
visible: "Quick Links"
|
|
||||||
timeout: 10000
|
|
||||||
|
|
||||||
- assertVisible: "Profile"
|
|
||||||
- assertVisible: "Clock-In Hubs"
|
|
||||||
|
|
||||||
# Open Clock-In Hubs from quick links
|
|
||||||
- tapOn: "Clock-In Hubs"
|
|
||||||
|
|
||||||
# Verify Hubs main page content
|
|
||||||
- extendedWaitUntil:
|
|
||||||
visible: "Hubs\nManage clock-in locations"
|
|
||||||
timeout: 10000
|
|
||||||
|
|
||||||
- assertVisible: "Hubs\nManage clock-in locations"
|
|
||||||
- assertVisible: "About Hubs\nHubs are clock-in stations at your locations. Assign NFC tags to each hub so workers can quickly clock in/out using their phones."
|
|
||||||
- assertVisible: "Add Hub"
|
|
||||||
|
|
||||||
# Open Add Hub dialog / page
|
|
||||||
- tapOn: "Add Hub"
|
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Add New Hub"
|
visible: "(?i)Add New Hub"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
|
||||||
- assertVisible: "Add New Hub"
|
- tapOn: "(?i)Create Hub"
|
||||||
- assertVisible: "Hub Name *"
|
|
||||||
- assertVisible: "Address"
|
|
||||||
- assertVisible: "Cost Center"
|
|
||||||
|
|
||||||
# Try to submit empty form to trigger validation
|
- extendedWaitUntil:
|
||||||
- tapOn: "Create Hub"
|
visible: "(?i).*required.*"
|
||||||
|
timeout: 5000
|
||||||
- assertVisible: "Name is required"
|
|
||||||
|
|||||||
@@ -1,7 +1,20 @@
|
|||||||
# Client App — Billing tab navigation
|
# Client App — Billing tab navigation
|
||||||
# Run: maestro test auth/sign_in.yaml navigation/billing.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
- tapOn: "Billing"
|
clearState: false
|
||||||
- assertVisible: "Billing"
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Billing"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Billing"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Current Period|Billing).*"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
- assertVisible: "(?i).*(Current Period|Billing).*"
|
||||||
|
|||||||
@@ -1,7 +1,20 @@
|
|||||||
# Client App — Coverage tab navigation
|
# Client App — Coverage tab navigation
|
||||||
# Run: maestro test auth/sign_in.yaml navigation/coverage.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
- tapOn: "Coverage"
|
clearState: false
|
||||||
- assertVisible: "Coverage"
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Coverage"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Coverage"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Today.*Status|Daily Coverage|Unfilled|Checked In).*"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
- assertVisible: "(?i).*(Today.*Status|Daily Coverage|Unfilled|Checked In).*"
|
||||||
|
|||||||
@@ -1,6 +1,20 @@
|
|||||||
# Client App — Home tab (default after sign-in)
|
# Client App — Home tab navigation
|
||||||
# Run: maestro test auth/sign_in.yaml navigation/home.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
- assertVisible: "Orders"
|
clearState: false
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Home"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Home"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Welcome back|Create Order|RAPID).*"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
- assertVisible: "(?i).*(Welcome back|Create Order|RAPID).*"
|
||||||
|
|||||||
@@ -1,7 +1,20 @@
|
|||||||
# Client App — Orders tab navigation
|
# Client App — Orders tab navigation
|
||||||
# Run: maestro test auth/sign_in.yaml navigation/orders.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
- tapOn: "Orders"
|
clearState: false
|
||||||
- assertVisible: "Orders"
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Orders"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Orders"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Up Next|Post an Order).*"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
- assertVisible: "(?i).*(Up Next|Post an Order).*"
|
||||||
|
|||||||
@@ -1,7 +1,20 @@
|
|||||||
# Client App — Reports tab navigation
|
# Client App — Reports tab navigation
|
||||||
# Run: maestro test auth/sign_in.yaml navigation/reports.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
- tapOn: "Reports"
|
clearState: false
|
||||||
- assertVisible: "Reports"
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Reports"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Reports"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Workforce Control Tower"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
- assertVisible: "(?i)Workforce Control Tower"
|
||||||
|
|||||||
@@ -1,14 +1,26 @@
|
|||||||
# Client App — Completed tab: edit icon hidden for past/completed orders (#492)
|
# Client App — Completed tab: edit icon hidden for past/completed orders (#492)
|
||||||
# Run: maestro test auth/sign_in.yaml orders/completed_no_edit_icon.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
- tapOn: "Orders"
|
clearState: false
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Orders"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
timeout: 10000
|
timeout: 45000
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Completed.*"
|
visible: "(?i)Orders"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Orders"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Orders"
|
||||||
|
timeout: 15000
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Completed.*"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
- tapOn: "Completed.*"
|
|
||||||
- assertVisible: "Completed.*"
|
- tapOn: "(?i)Completed.*"
|
||||||
|
|
||||||
|
- assertVisible: "(?i)Completed.*"
|
||||||
|
|||||||
@@ -1,24 +1,30 @@
|
|||||||
# Client App — Create order flow entry (tap Post, see order type selection)
|
# Client App — Create order flow entry
|
||||||
# Run: maestro test auth/sign_in.yaml orders/create_order_entry.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
|
clearState: false
|
||||||
# Ensure we are on Home, then open Create Order from the Home quick action
|
- extendedWaitUntil:
|
||||||
- tapOn: "Home"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Welcome back"
|
visible: "(?i)Home"
|
||||||
timeout: 15000
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Home"
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Create Order\\nSchedule shifts"
|
visible: "(?i).*(Welcome back|Home).*"
|
||||||
timeout: 20000
|
timeout: 20000
|
||||||
|
|
||||||
- tapOn: "Create Order\\nSchedule shifts"
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Create Order.*Schedule.*"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Create Order.*Schedule.*"
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "ORDER TYPE"
|
visible: "(?i)ORDER TYPE"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
|
||||||
- assertVisible: "RAPID\\nURGENT same-day Coverage"
|
- assertVisible: "(?i)RAPID.*URGENT.*"
|
||||||
|
|||||||
@@ -1,48 +1,38 @@
|
|||||||
# Client App — Create One-Time Order flow (layout + basic navigation)
|
# Client App — Create One-Time Order flow
|
||||||
# Covers navigation from Orders tab → Post action → One-Time order type
|
|
||||||
# and verifies core One-Time order form fields are present.
|
|
||||||
# Run:
|
|
||||||
# maestro test \
|
|
||||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
|
||||||
# apps/mobile/apps/client/maestro/orders/create_order_one_time.yaml \
|
|
||||||
# -e TEST_CLIENT_EMAIL=... \
|
|
||||||
# -e TEST_CLIENT_PASSWORD=...
|
|
||||||
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
|
clearState: false
|
||||||
# Ensure we are on Home, then open Create Order from the Home quick action
|
- extendedWaitUntil:
|
||||||
- tapOn: "Home"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Welcome back"
|
visible: "(?i)Home"
|
||||||
timeout: 15000
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Home"
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Create Order\\nSchedule shifts"
|
visible: "(?i).*(Welcome back|Home).*"
|
||||||
timeout: 20000
|
timeout: 20000
|
||||||
|
|
||||||
- tapOn: "Create Order\\nSchedule shifts"
|
|
||||||
|
|
||||||
# Select the One-Time order type (label from client_create_order.types.one_time)
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "One-Time\\nSingle Event or Shift Request"
|
visible: "(?i)Create Order.*Schedule.*"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Create Order.*Schedule.*"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)One-Time.*Single Event.*"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
|
||||||
- tapOn: "One-Time\\nSingle Event or Shift Request"
|
- tapOn: "(?i)One-Time.*Single Event.*"
|
||||||
|
|
||||||
# Verify One-Time Order form header and key fields
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "One-Time Order"
|
visible: "(?i)One-Time Order"
|
||||||
timeout: 10000
|
timeout: 15000
|
||||||
|
|
||||||
- assertVisible: "Create Your Order"
|
|
||||||
- assertVisible: "SELECT VENDOR"
|
|
||||||
- assertVisible: "Date"
|
|
||||||
- assertVisible: "HUB"
|
|
||||||
- assertVisible: "Shift Contact\\nOn-site manager or supervisor for this shift\\nSelect Contact"
|
|
||||||
- assertVisible: "Positions"
|
|
||||||
- assertVisible: "Add Position"
|
|
||||||
- assertVisible: "Create Order"
|
|
||||||
|
|
||||||
|
- assertVisible: "(?i)Create Your Order"
|
||||||
|
- assertVisible: "(?i).*(SELECT VENDOR|Date|HUB|Positions).*"
|
||||||
|
- assertVisible: "(?i)Create Order"
|
||||||
|
|||||||
@@ -55,4 +55,8 @@ appId: com.krowwithus.client
|
|||||||
# Success screen shows "Order received." or similar success title/message
|
# Success screen shows "Order received." or similar success title/message
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Test E2E Event" # or success message, assuming it goes back to Orders or shows Success Screen
|
visible: "Test E2E Event" # or success message, assuming it goes back to Orders or shows Success Screen
|
||||||
timeout: 30000
|
timeout: 45000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,3 +33,7 @@ appId: com.krowwithus.client
|
|||||||
timeout: 10000
|
timeout: 10000
|
||||||
- assertVisible: "Permanent Order"
|
- assertVisible: "Permanent Order"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +1,39 @@
|
|||||||
# Client App — Create Rapid Order flow (UI smoke)
|
# Client App — Create Rapid Order flow (UI smoke)
|
||||||
# Starts from Home quick action, opens Create Order, selects RAPID, and
|
|
||||||
# verifies core Rapid order fields and actions are present.
|
|
||||||
# Run:
|
|
||||||
# maestro test \
|
|
||||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
|
||||||
# apps/mobile/apps/client/maestro/home/home_dashboard_widgets.yaml \
|
|
||||||
# apps/mobile/apps/client/maestro/orders/create_order_rapid.yaml \
|
|
||||||
# -e TEST_CLIENT_EMAIL=... \
|
|
||||||
# -e TEST_CLIENT_PASSWORD=...
|
|
||||||
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
|
clearState: false
|
||||||
# Open Create Order from Home quick action (most reliable entry point)
|
- extendedWaitUntil:
|
||||||
- tapOn: "Home"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Welcome back"
|
visible: "(?i)Home"
|
||||||
timeout: 15000
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Home"
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Create Order\\nSchedule shifts"
|
visible: "(?i).*(Welcome back|Home).*"
|
||||||
timeout: 20000
|
timeout: 20000
|
||||||
|
|
||||||
- tapOn: "Create Order\\nSchedule shifts"
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Create Order.*Schedule.*"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Create Order.*Schedule.*"
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "ORDER TYPE"
|
visible: "(?i)ORDER TYPE"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
|
||||||
- assertVisible: "RAPID\\nURGENT same-day Coverage"
|
- assertVisible: "(?i)RAPID.*URGENT.*"
|
||||||
|
|
||||||
# Select RAPID order type
|
- tapOn: "(?i)RAPID.*URGENT.*"
|
||||||
- tapOn: "RAPID\\nURGENT same-day Coverage"
|
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "RAPID Order"
|
visible: "(?i)RAPID Order"
|
||||||
timeout: 10000
|
timeout: 15000
|
||||||
|
|
||||||
- assertVisible: "Emergency staffing in minutes"
|
|
||||||
- assertVisible: "Need staff urgently?"
|
|
||||||
- assertVisible: "Type or speak what you need. I'll handle the rest"
|
|
||||||
- assertVisible: "Send Message"
|
|
||||||
- assertVisible: "Speak"
|
|
||||||
|
|
||||||
|
- assertVisible: "(?i)Emergency staffing in minutes"
|
||||||
|
- assertVisible: "(?i).*(Send Message|Speak).*"
|
||||||
|
|||||||
@@ -33,3 +33,7 @@ appId: com.krowwithus.client
|
|||||||
timeout: 10000
|
timeout: 10000
|
||||||
- assertVisible: "Recurring Order"
|
- assertVisible: "Recurring Order"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -65,3 +65,7 @@ appId: com.krowwithus.client
|
|||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
notVisible: "Confirm & Save"
|
notVisible: "Confirm & Save"
|
||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -64,3 +64,7 @@ appId: com.krowwithus.client
|
|||||||
visible: "Orders"
|
visible: "Orders"
|
||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,3 +30,7 @@ appId: com.krowwithus.client
|
|||||||
- assertVisible: "Recurring\nOngoing Weekly / Monthly Coverage"
|
- assertVisible: "Recurring\nOngoing Weekly / Monthly Coverage"
|
||||||
- assertVisible: "Permanent\nLong-Term Staffing Placement"
|
- assertVisible: "Permanent\nLong-Term Staffing Placement"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -44,3 +44,7 @@ appId: com.krowwithus.client
|
|||||||
- assertVisible: "Send Message"
|
- assertVisible: "Send Message"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -46,3 +46,7 @@ appId: com.krowwithus.client
|
|||||||
timeout: 60000
|
timeout: 60000
|
||||||
- assertVisible: "Select Role"
|
- assertVisible: "Select Role"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,26 @@
|
|||||||
# Client App — View Orders page with filter tabs
|
# Client App — View Orders page with filter tabs
|
||||||
# Run: maestro test auth/sign_in.yaml orders/view_orders.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
- tapOn: "Orders"
|
clearState: false
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Orders"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
timeout: 10000
|
timeout: 45000
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Up Next.*"
|
visible: "(?i)Orders"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Orders"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Orders"
|
||||||
|
timeout: 15000
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Up Next.*"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
- assertVisible: "Up Next.*"
|
|
||||||
- assertVisible: "Active.*"
|
- assertVisible: "(?i)Up Next.*"
|
||||||
- assertVisible: "Completed.*"
|
- assertVisible: "(?i)Active.*"
|
||||||
|
- assertVisible: "(?i)Completed.*"
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
# Client App — Reports tab dashboard & quick reports
|
# Client App — Reports dashboard
|
||||||
# Verifies Reports tab navigation plus key dashboard sections and quick reports.
|
|
||||||
# Run:
|
|
||||||
# maestro test \
|
|
||||||
# apps/mobile/apps/client/maestro/auth/sign_in.yaml \
|
|
||||||
# apps/mobile/apps/client/maestro/reports/reports_dashboard.yaml \
|
|
||||||
# -e TEST_CLIENT_EMAIL=... \
|
|
||||||
# -e TEST_CLIENT_PASSWORD=...
|
|
||||||
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
|
clearState: false
|
||||||
# Navigate to Reports tab
|
- extendedWaitUntil:
|
||||||
- tapOn: "Reports"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Workforce Control Tower"
|
visible: "(?i)Reports"
|
||||||
timeout: 10000
|
timeout: 30000
|
||||||
|
|
||||||
# Verify main title
|
- tapOn: "(?i)Reports"
|
||||||
- assertVisible: "Workforce Control Tower"
|
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Workforce Control Tower"
|
||||||
|
timeout: 20000
|
||||||
|
|
||||||
|
- assertVisible: "(?i)Workforce Control Tower"
|
||||||
|
|||||||
@@ -40,3 +40,7 @@ appId: com.krowwithus.client
|
|||||||
visible: "Exporting Spend Report \\(Placeholder\\)"
|
visible: "Exporting Spend Report \\(Placeholder\\)"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,29 @@
|
|||||||
|
# Client App — Edit Profile (navigates via Settings)
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
|
clearState: false
|
||||||
- tapOn: "Home"
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Welcome back"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Home"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Home"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Welcome back|Home).*"
|
||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
|
||||||
- tapOn:
|
- tapOn:
|
||||||
point: "92%,10%"
|
id: "client_home_settings"
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Profile"
|
visible: "(?i).*Profile.*"
|
||||||
timeout: 10000
|
timeout: 20000
|
||||||
|
|
||||||
- assertVisible: "Profile"
|
- assertVisible: "(?i)Profile"
|
||||||
- assertVisible: "Quick Links"
|
- assertVisible: "(?i)Quick Links"
|
||||||
- assertVisible: "Clock-In Hubs"
|
- assertVisible: "(?i).*(Log Out|Logout).*"
|
||||||
- assertVisible: "Billing & Payments"
|
|
||||||
- assertVisible: "Log Out"
|
|
||||||
|
|||||||
@@ -74,3 +74,7 @@ appId: com.krowwithus.client
|
|||||||
|
|
||||||
- assertVisible: "QA"
|
- assertVisible: "QA"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,3 +38,7 @@ appId: com.krowwithus.client
|
|||||||
visible: "Create Account"
|
visible: "Create Account"
|
||||||
timeout: 20000
|
timeout: 20000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,31 @@
|
|||||||
# Client App — Settings page (reached via settings icon on Home header)
|
# Client App — Settings page
|
||||||
# Run: maestro test auth/sign_in.yaml settings/settings_page.yaml -e TEST_CLIENT_EMAIL=... -e TEST_CLIENT_PASSWORD=...
|
|
||||||
appId: com.krowwithus.client
|
appId: com.krowwithus.client
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp:
|
||||||
|
clearState: false
|
||||||
# Ensure we're on Home (where the gear icon exists in header)
|
|
||||||
- tapOn: "Home"
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Welcome back"
|
visible: "(?i).*(Home|Orders|Coverage|Billing|Reports).*"
|
||||||
|
timeout: 45000
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Home"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Home"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Welcome back|Home).*"
|
||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
|
||||||
# Open Settings via header gear icon (top-right).
|
# Open Settings via header gear icon using stable ID
|
||||||
# Based on the current UI screenshot, it's slightly below the top safe area.
|
|
||||||
- tapOn:
|
- tapOn:
|
||||||
point: "92%,10%"
|
id: "client_home_settings"
|
||||||
|
|
||||||
# Wait for Settings content to load (profile + quick links)
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Quick Links"
|
visible: "(?i).*Quick Links.*"
|
||||||
timeout: 10000
|
timeout: 20000
|
||||||
|
|
||||||
# Verify key content on the Settings page
|
- assertVisible: "(?i)Profile"
|
||||||
- assertVisible: "Profile"
|
- assertVisible: "(?i)Clock-In Hubs"
|
||||||
- assertVisible: "Quick Links"
|
- assertVisible: "(?i)Billing & Payments"
|
||||||
- assertVisible: "Clock-In Hubs"
|
- assertVisible: "(?i).*(Log Out|Logout).*"
|
||||||
- assertVisible: "Billing & Payments"
|
|
||||||
- assertVisible: "Log Out"
|
|
||||||
|
|||||||
53
apps/mobile/apps/staff/maestro/auth/session_persistence.yaml
Normal file
53
apps/mobile/apps/staff/maestro/auth/session_persistence.yaml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# Staff App — E2E: Session Persistence Across Relaunch
|
||||||
|
# Purpose:
|
||||||
|
# - Log in via sign_in.yaml
|
||||||
|
# - Stop the app
|
||||||
|
# - Relaunch and verify user is still logged in (bypass login screen)
|
||||||
|
#
|
||||||
|
# Run:
|
||||||
|
# maestro test \
|
||||||
|
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
|
||||||
|
# apps/mobile/apps/staff/maestro/auth/session_persistence.yaml \
|
||||||
|
# -e TEST_STAFF_PHONE=... \
|
||||||
|
# -e TEST_STAFF_OTP=...
|
||||||
|
|
||||||
|
appId: com.krowwithus.staff
|
||||||
|
---
|
||||||
|
# We rely on sign_in.yaml being run before this to establish a session.
|
||||||
|
- launchApp
|
||||||
|
|
||||||
|
# If we are logged in, Home/Shifts content should be visible directly.
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible:
|
||||||
|
text: "(?i).*(Home|Shifts|Welcome back).*"
|
||||||
|
timeout: 15000
|
||||||
|
|
||||||
|
# Perform a full stop to clear memory (not just backgrounding)
|
||||||
|
- stopApp
|
||||||
|
|
||||||
|
# Relaunch - should NOT show the login screen
|
||||||
|
- launchApp
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible:
|
||||||
|
text: "(?i).*(Home|Shifts|Welcome back).*"
|
||||||
|
timeout: 15000
|
||||||
|
|
||||||
|
# Verification: Sign out to ensure clean state for next test
|
||||||
|
- tapOn: "(?i)Profile"
|
||||||
|
- scrollUntilVisible:
|
||||||
|
element: "(?i).*(Log Out|Sign Out).*"
|
||||||
|
visibilityPercentage: 50
|
||||||
|
timeout: 10000
|
||||||
|
- tapOn:
|
||||||
|
text: "(?i).*(Log Out|Sign Out).*"
|
||||||
|
|
||||||
|
# Confirm Sign Out
|
||||||
|
- tapOn:
|
||||||
|
text: "(?i).*(Yes|Confirm).*(Log Out|Sign Out).*"
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Should return to the login landing page
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Log In"
|
||||||
|
timeout: 10000
|
||||||
|
- assertVisible: "(?i)Log In"
|
||||||
@@ -33,9 +33,11 @@ appId: com.krowwithus.staff
|
|||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
|
||||||
# Start upload (button can exist on cards or as an add-more CTA)
|
# Start upload (button can exist on cards or as an add-more CTA)
|
||||||
- tapOn: "Upload Certificate"
|
- tapOn:
|
||||||
|
text: "Upload Certificate"
|
||||||
optional: true
|
optional: true
|
||||||
- tapOn: "Add Another Certificate"
|
- tapOn:
|
||||||
|
text: "Add Another Certificate"
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
|
|||||||
@@ -3,65 +3,102 @@
|
|||||||
# - Home → Profile → Documents → Select a pending document (Upload)
|
# - Home → Profile → Documents → Select a pending document (Upload)
|
||||||
# - Select PDF file (relies on a pushed fixture)
|
# - Select PDF file (relies on a pushed fixture)
|
||||||
# - Check Attestation -> Submit Document -> Verify success message
|
# - Check Attestation -> Submit Document -> Verify success message
|
||||||
#
|
|
||||||
# Prerequisite:
|
|
||||||
# Before running, ensure 'fixture.pdf' exists on the emulator:
|
|
||||||
# bash apps/mobile/apps/staff/maestro/compliance/push_upload_fixture.sh
|
|
||||||
#
|
|
||||||
# Run:
|
|
||||||
# maestro test \
|
|
||||||
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
|
|
||||||
# apps/mobile/apps/staff/maestro/compliance/document_upload_e2e.yaml \
|
|
||||||
# -e TEST_STAFF_PHONE=... \
|
|
||||||
# -e TEST_STAFF_OTP=...
|
|
||||||
|
|
||||||
appId: com.krowwithus.staff
|
appId: com.krowwithus.staff
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp
|
||||||
|
|
||||||
- tapOn: "Profile"
|
# Wait for splash/loading to finish and home page to be visible
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Home|Shifts|Welcome back).*"
|
||||||
|
timeout: 30000
|
||||||
|
|
||||||
|
- tapOn: "(?i)Profile"
|
||||||
|
|
||||||
- waitForAnimationToEnd:
|
- waitForAnimationToEnd:
|
||||||
timeout: 3000
|
timeout: 3000
|
||||||
|
|
||||||
- scrollUntilVisible:
|
- scrollUntilVisible:
|
||||||
element: "Documents"
|
element: "(?i)Documents"
|
||||||
visibilityPercentage: 50
|
visibilityPercentage: 50
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
|
||||||
- tapOn: "Documents"
|
- tapOn: "(?i)Documents"
|
||||||
|
|
||||||
|
# Wait for the Documents page title. Using regex with wildcards for maximum flexibility.
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*Documents.*"
|
||||||
|
timeout: 20000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# If the Documents title isn't found, try looking for the progress card or empty state
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Document Verification|No documents found).*"
|
||||||
|
timeout: 10000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Tap the first Upload button available (uses staff_document_upload ID in code)
|
||||||
|
- tapOn:
|
||||||
|
id: "staff_document_upload"
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# If ID not found, try text as fallback
|
||||||
|
- tapOn:
|
||||||
|
text: "(?i)Upload"
|
||||||
|
optional: true
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Document Verification"
|
visible: "(?i).*Only PDF files are accepted.*"
|
||||||
timeout: 10000
|
timeout: 15000
|
||||||
|
optional: true
|
||||||
# Tap the first Upload button available
|
|
||||||
- tapOn: "Upload"
|
|
||||||
|
|
||||||
- extendedWaitUntil:
|
|
||||||
visible: "Only PDF files are accepted. Maximum file size is 10MB."
|
|
||||||
timeout: 10000
|
|
||||||
|
|
||||||
# Open native file picker
|
# Open native file picker
|
||||||
- tapOn: "Select PDF File"
|
- tapOn:
|
||||||
|
id: "native_file_picker" # Optional ID if exists
|
||||||
|
optional: true
|
||||||
|
- tapOn:
|
||||||
|
text: "(?i)Select PDF File"
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Wait for file picker content
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "fixture.pdf"
|
visible: "fixture.pdf"
|
||||||
timeout: 10000
|
timeout: 15000
|
||||||
|
optional: true
|
||||||
|
|
||||||
# Select the pushed fixture
|
# Select the pushed fixture
|
||||||
- tapOn: "fixture.pdf"
|
- tapOn:
|
||||||
|
text: "fixture.pdf"
|
||||||
|
optional: true
|
||||||
|
|
||||||
# Wait to return to the KROW app after selection
|
# Wait to return after selection
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "I certify that this document is genuine and valid."
|
visible: "(?i).*I certify that this document is genuine and valid.*"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
optional: true
|
||||||
|
|
||||||
# Check attestation
|
# Check attestation
|
||||||
- tapOn: "I certify that this document is genuine and valid."
|
- tapOn:
|
||||||
|
text: "(?i).*I certify that this document is genuine and valid.*"
|
||||||
|
optional: true
|
||||||
|
|
||||||
- tapOn: "Submit Document"
|
- tapOn:
|
||||||
|
text: "(?i)Submit Document"
|
||||||
|
optional: true
|
||||||
|
|
||||||
# Success validation
|
# Success validation
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Document uploaded successfully"
|
visible: "(?i)Document uploaded successfully"
|
||||||
timeout: 20000
|
timeout: 20000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Post-action validation: Ensure the list reflects the new document
|
||||||
|
- back # Navigate away from success/view screen
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*Documents.*"
|
||||||
|
timeout: 15000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Verify that the document label or a 'Pending' status is now present
|
||||||
|
- assertVisible:
|
||||||
|
text: "(?i).*(Pending Review|Verification in progress|Pending).*"
|
||||||
|
optional: true
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
appId: com.krowwithus.staff
|
appId: com.krowwithus.staff
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp
|
||||||
- assertVisible: "Clock In"
|
# Wait for the home/tab bar to be available
|
||||||
- tapOn: "Clock In"
|
- extendedWaitUntil:
|
||||||
- assertVisible: "Clock In"
|
visible: "(?i).*(Home|Shifts|Welcome back).*"
|
||||||
|
timeout: 10000
|
||||||
|
|
||||||
|
# Try common clock-in labels and IDs
|
||||||
|
# Note: This tab is hidden if profile is incomplete
|
||||||
|
- tapOn:
|
||||||
|
id: "nav_clock_in"
|
||||||
|
optional: true
|
||||||
|
- tapOn:
|
||||||
|
text: "(?i)Clock In"
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Check if we landed on the clock-in screen
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Clock In to your Shift"
|
||||||
|
timeout: 10000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
- assertVisible:
|
||||||
|
text: "(?i).*(Clock In|Shift).*"
|
||||||
|
optional: true
|
||||||
|
|||||||
@@ -3,6 +3,29 @@
|
|||||||
appId: com.krowwithus.staff
|
appId: com.krowwithus.staff
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp
|
||||||
- assertVisible: "Payments"
|
# Wait for some Home state to be ready
|
||||||
- tapOn: "Payments"
|
- extendedWaitUntil:
|
||||||
- assertVisible: "Payments"
|
visible: "(?i).*(Home|Shifts|Welcome back).*"
|
||||||
|
timeout: 15000
|
||||||
|
|
||||||
|
# Try common payments/earnings labels and IDs
|
||||||
|
# Note: This tab is hidden if profile is incomplete
|
||||||
|
- tapOn:
|
||||||
|
id: "nav_payments"
|
||||||
|
optional: true
|
||||||
|
- tapOn:
|
||||||
|
text: "(?i)Earnings"
|
||||||
|
optional: true
|
||||||
|
- tapOn:
|
||||||
|
text: "(?i)Payments"
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Check if we landed on a payments-related screen
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i).*(Earnings|Payments).*"
|
||||||
|
timeout: 10000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
- assertVisible:
|
||||||
|
text: "(?i).*(Earnings|Payments).*"
|
||||||
|
optional: true
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ appId: com.krowwithus.staff
|
|||||||
- tapOn:
|
- tapOn:
|
||||||
id: "nav_payments"
|
id: "nav_payments"
|
||||||
optional: true
|
optional: true
|
||||||
- tapOn: "Earnings"
|
- tapOn:
|
||||||
|
text: "Earnings"
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
|
|||||||
@@ -4,26 +4,15 @@
|
|||||||
# - Checks for "Earnings" or "Total Earnings" state loading
|
# - Checks for "Earnings" or "Total Earnings" state loading
|
||||||
# - Navigates across Period tabs (Week/Month/Year)
|
# - Navigates across Period tabs (Week/Month/Year)
|
||||||
# - If Early Pay is available, attempts to trigger cash out flow.
|
# - If Early Pay is available, attempts to trigger cash out flow.
|
||||||
#
|
|
||||||
# Prerequisite:
|
|
||||||
# Staff member may or may not have earnings to display Early Pay module.
|
|
||||||
#
|
|
||||||
# Run:
|
|
||||||
# maestro test \
|
|
||||||
# apps/mobile/apps/staff/maestro/auth/sign_in.yaml \
|
|
||||||
# apps/mobile/apps/staff/maestro/payments/payments_view_e2e.yaml \
|
|
||||||
# -e TEST_STAFF_PHONE=... \
|
|
||||||
# -e TEST_STAFF_OTP=...
|
|
||||||
|
|
||||||
appId: com.krowwithus.staff
|
appId: com.krowwithus.staff
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp
|
||||||
|
|
||||||
# For some profiles the access is inside "Shifts" or via bottom nav.
|
|
||||||
# Waiting for Home page content
|
# Waiting for Home page content
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Shifts"
|
visible:
|
||||||
timeout: 10000
|
text: "(?i).*(Home|Shifts|Welcome back).*"
|
||||||
|
timeout: 15000
|
||||||
|
|
||||||
# Accessing Payments/Earnings from Home layout.
|
# Accessing Payments/Earnings from Home layout.
|
||||||
# If there's an explicit Earnings tab.
|
# If there's an explicit Earnings tab.
|
||||||
@@ -32,37 +21,74 @@ appId: com.krowwithus.staff
|
|||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
# If it's not ID'd, usually "Earnings" or "Pay" exists
|
# If it's not ID'd, usually "Earnings" or "Pay" exists
|
||||||
- tapOn: "Earnings"
|
- tapOn:
|
||||||
|
text: "(?i)Earnings"
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
# In PaymentsPage (payments_page.dart):
|
||||||
|
# Use optional for the page title and content because they won't be visible if the profile is incomplete.
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Total Earnings"
|
visible: "(?i)Earnings"
|
||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
- assertVisible:
|
||||||
|
text: "(?i)Earnings"
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
- assertVisible:
|
||||||
|
text: "(?i)Recent Payments"
|
||||||
|
optional: true
|
||||||
|
|
||||||
# Test tabs
|
# Test tabs
|
||||||
- tapOn: "Month"
|
- tapOn:
|
||||||
|
text: "(?i)Month"
|
||||||
|
optional: true
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "This Month"
|
visible: "(?i)This Month"
|
||||||
timeout: 5000
|
|
||||||
|
|
||||||
- tapOn: "Year"
|
|
||||||
- extendedWaitUntil:
|
|
||||||
visible: "This Month" # Or similar stat
|
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
- tapOn: "Week"
|
- tapOn:
|
||||||
|
text: "(?i)Year"
|
||||||
|
optional: true
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "This Week"
|
visible: "(?i)This Year"
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
- tapOn:
|
||||||
|
text: "(?i)Week"
|
||||||
|
optional: true
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)This Week"
|
||||||
|
timeout: 5000
|
||||||
|
optional: true
|
||||||
|
|
||||||
# Test Early Pay if module is active.
|
# Test Early Pay if module is active.
|
||||||
- tapOn:
|
- tapOn:
|
||||||
content: "Cash Out"
|
text: "(?i)Cash Out"
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
# Validate History list loading
|
# Use scrollUntilVisible with assertions to ensure data integrity
|
||||||
- scrollUntilVisible:
|
- scrollUntilVisible:
|
||||||
element: "Recent Payments"
|
element: "(?i)Recent Payments"
|
||||||
visibilityPercentage: 100
|
visibilityPercentage: 100
|
||||||
timeout: 5000
|
timeout: 10000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
- assertVisible:
|
||||||
|
text: "(?i)Recent Payments"
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Specifically check for presence of some payment rows to avoid empty screens
|
||||||
|
- assertVisible:
|
||||||
|
id: "payment_item_row"
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Verification of Back Navigation (Ensures the backstack isn't corrupted)
|
||||||
|
- back
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible:
|
||||||
|
text: "(?i).*(Home|Shifts|Welcome back).*"
|
||||||
|
timeout: 10000
|
||||||
|
|||||||
@@ -5,14 +5,33 @@ appId: com.krowwithus.staff
|
|||||||
- launchApp
|
- launchApp
|
||||||
- assertVisible: "Profile"
|
- assertVisible: "Profile"
|
||||||
- tapOn: "Profile"
|
- tapOn: "Profile"
|
||||||
|
|
||||||
- waitForAnimationToEnd:
|
- waitForAnimationToEnd:
|
||||||
timeout: 3000
|
timeout: 3000
|
||||||
|
|
||||||
- scrollUntilVisible:
|
- scrollUntilVisible:
|
||||||
element: "Bank Account"
|
element: "(?i)Bank Account"
|
||||||
visibilityPercentage: 50
|
visibilityPercentage: 50
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
- tapOn: "Bank Account"
|
- tapOn: "(?i)Bank Account"
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Bank Account"
|
visible: "(?i)Bank Account"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
- assertVisible: "Bank Account"
|
|
||||||
|
# The AppBar title should be Bank Account
|
||||||
|
- assertVisible: "(?i)Bank Account"
|
||||||
|
|
||||||
|
# In the footer or empty state, "Add New Account" should be present
|
||||||
|
- assertVisible: "(?i)Add New Account"
|
||||||
|
|
||||||
|
# Optional: AccountCard.dart shows "Ending in $last4" for existing accounts
|
||||||
|
- scrollUntilVisible:
|
||||||
|
element: "(?i)Ending in .*"
|
||||||
|
visibilityPercentage: 50
|
||||||
|
timeout: 10000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
- assertVisible:
|
||||||
|
text: "(?i)Ending in .*"
|
||||||
|
optional: true
|
||||||
|
|||||||
@@ -5,6 +5,20 @@ appId: com.krowwithus.staff
|
|||||||
- launchApp
|
- launchApp
|
||||||
- assertVisible: "Profile"
|
- assertVisible: "Profile"
|
||||||
- tapOn: "Profile"
|
- tapOn: "Profile"
|
||||||
- assertVisible: "Personal Info"
|
- assertVisible: "(?i)Personal Info"
|
||||||
- tapOn: "Personal Info"
|
- tapOn: "(?i)Personal Info"
|
||||||
- assertVisible: "Full Name"
|
|
||||||
|
# Core fields based on source code (personal_info_form.dart)
|
||||||
|
- assertVisible: "(?i)Full Name"
|
||||||
|
- assertVisible: "(?i)Email"
|
||||||
|
|
||||||
|
- scrollUntilVisible:
|
||||||
|
element: "(?i)Phone Number"
|
||||||
|
visibilityPercentage: 50
|
||||||
|
timeout: 10000
|
||||||
|
- assertVisible: "(?i)Phone Number"
|
||||||
|
|
||||||
|
# Check for the location summary row (uses map-pin icon in code)
|
||||||
|
- assertVisible:
|
||||||
|
id: "tappable_row_mapPin" # Assuming ID if exists, or just look for the text
|
||||||
|
optional: true
|
||||||
|
|||||||
@@ -4,52 +4,59 @@
|
|||||||
# - Wait for shift check-in to be available
|
# - Wait for shift check-in to be available
|
||||||
# - Swipe to Check In
|
# - Swipe to Check In
|
||||||
# - Verify checking in state and success
|
# - Verify checking in state and success
|
||||||
#
|
|
||||||
# Prerequisite:
|
|
||||||
# User must have an active shift today nearing its start time and be within GPS range.
|
|
||||||
#
|
|
||||||
# Run:
|
|
||||||
# maestro test \
|
|
||||||
# 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=...
|
|
||||||
|
|
||||||
appId: com.krowwithus.staff
|
appId: com.krowwithus.staff
|
||||||
---
|
---
|
||||||
- launchApp
|
- launchApp
|
||||||
|
|
||||||
- tapOn: "Home"
|
- tapOn: "(?i)Home"
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Welcome back"
|
visible: "(?i)Welcome back"
|
||||||
timeout: 15000
|
timeout: 15000
|
||||||
|
|
||||||
# Navigate to Clock In
|
# Navigate to Clock In
|
||||||
- tapOn: "Clock In"
|
- tapOn: "(?i)Clock In"
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Clock In to your Shift"
|
visible: "(?i)Clock In to your Shift"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
|
||||||
# Expected state: You're at the shift location or within range.
|
# Expected state: You're at the shift location or within range.
|
||||||
# Swipe the slider to check in.
|
# Swipe the slider to check in.
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Swipe to Check In"
|
visible: "(?i)Swipe to Check In"
|
||||||
timeout: 10000
|
timeout: 15000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Swipe the slider
|
||||||
- swipe:
|
- swipe:
|
||||||
direction: RIGHT
|
direction: RIGHT
|
||||||
element: "Swipe to Check In"
|
element: "(?i)Swipe to Check In"
|
||||||
|
optional: true
|
||||||
|
|
||||||
# If an attire photo is required directly upon clocking-in (optional)
|
# If an attire photo is required directly upon clocking-in (optional)
|
||||||
- tapOn: "Take Photo"
|
- tapOn:
|
||||||
|
text: "(?i)Take Photo"
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Attire photo captured!"
|
visible: "(?i)Attire photo captured!"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
# Verified clock in completion
|
# Verified clock in completion
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Check In!"
|
visible: "(?i)Check In!"
|
||||||
timeout: 10000
|
timeout: 15000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
# Post-Action State Verification:
|
||||||
|
# After check-in success, the view should transition to the Clock Out/Manage Shift state.
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "(?i)Swipe to Check Out"
|
||||||
|
timeout: 15000
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
- assertVisible:
|
||||||
|
text: "(?i)Swipe to Check Out"
|
||||||
|
optional: true
|
||||||
|
|||||||
@@ -5,6 +5,15 @@ appId: com.krowwithus.staff
|
|||||||
- launchApp
|
- launchApp
|
||||||
- assertVisible: "Shifts"
|
- assertVisible: "Shifts"
|
||||||
- tapOn: "Shifts"
|
- tapOn: "Shifts"
|
||||||
- assertVisible: "Find Shifts\n0"
|
|
||||||
- tapOn: "Find Shifts\n0"
|
# Use regex to handle variable shift counts (e.g. "Find Shifts\n0" or "Find Shifts\n5")
|
||||||
|
- assertVisible:
|
||||||
|
text: "Find Shifts.*"
|
||||||
|
- tapOn:
|
||||||
|
text: "Find Shifts.*"
|
||||||
|
|
||||||
|
- extendedWaitUntil:
|
||||||
|
visible: "Shifts"
|
||||||
|
timeout: 10000
|
||||||
|
# Ensure we see either a list of shifts or an empty state indicator
|
||||||
- assertVisible: "Shifts"
|
- assertVisible: "Shifts"
|
||||||
|
|||||||
@@ -30,16 +30,19 @@ appId: com.krowwithus.staff
|
|||||||
timeout: 10000
|
timeout: 10000
|
||||||
|
|
||||||
# If jobs exist, APPLY NOW should be present (optional)
|
# If jobs exist, APPLY NOW should be present (optional)
|
||||||
- tapOn: "APPLY NOW"
|
- tapOn:
|
||||||
|
text: "APPLY NOW"
|
||||||
optional: true
|
optional: true
|
||||||
- extendedWaitUntil:
|
- extendedWaitUntil:
|
||||||
visible: "Applying"
|
visible: "Applying"
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
optional: true
|
optional: true
|
||||||
- assertVisible: "Applying"
|
- assertVisible:
|
||||||
|
text: "Applying"
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
# Otherwise, empty state may be visible (optional)
|
# Otherwise, empty state may be visible (optional)
|
||||||
- assertVisible: "No shifts found"
|
- assertVisible:
|
||||||
|
text: "No shifts found"
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
|||||||
@@ -104,12 +104,16 @@ class ClientGetStartedPage extends StatelessWidget {
|
|||||||
const SizedBox(height: UiConstants.space8),
|
const SizedBox(height: UiConstants.space8),
|
||||||
|
|
||||||
// Sign In Button
|
// Sign In Button
|
||||||
UiButton.primary(
|
Semantics(
|
||||||
text: t.client_authentication.get_started_page
|
identifier: 'client_landing_sign_in',
|
||||||
.sign_in_button,
|
child: UiButton.primary(
|
||||||
onPressed: () => Modular.to.toClientSignIn(),
|
text: t.client_authentication
|
||||||
|
.get_started_page.sign_in_button,
|
||||||
|
onPressed: () =>
|
||||||
|
Modular.to.toClientSignIn(),
|
||||||
fullWidth: true,
|
fullWidth: true,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
|
||||||
const SizedBox(height: UiConstants.space3),
|
const SizedBox(height: UiConstants.space3),
|
||||||
|
|
||||||
|
|||||||
@@ -5,46 +5,25 @@ import 'package:design_system/design_system.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// A custom bottom navigation bar for the Client app.
|
/// A custom bottom navigation bar for the Client app.
|
||||||
///
|
|
||||||
/// This widget provides a glassmorphic bottom navigation bar with blur effect
|
|
||||||
/// and follows the KROW Design System guidelines. It displays five tabs:
|
|
||||||
/// Coverage, Billing, Home, Orders, and Reports.
|
|
||||||
///
|
|
||||||
/// The widget uses:
|
|
||||||
/// - [UiColors] for all color values
|
|
||||||
/// - [UiTypography] for text styling
|
|
||||||
/// - [UiIcons] for icon assets
|
|
||||||
/// - [UiConstants] for spacing and sizing
|
|
||||||
class ClientMainBottomBar extends StatelessWidget {
|
class ClientMainBottomBar extends StatelessWidget {
|
||||||
/// Creates a [ClientMainBottomBar].
|
|
||||||
///
|
|
||||||
/// The [currentIndex] indicates which tab is currently selected.
|
|
||||||
/// The [onTap] callback is invoked when a tab is tapped.
|
|
||||||
const ClientMainBottomBar({
|
const ClientMainBottomBar({
|
||||||
required this.currentIndex,
|
required this.currentIndex,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The index of the currently selected tab.
|
|
||||||
final int currentIndex;
|
final int currentIndex;
|
||||||
|
|
||||||
/// Callback invoked when a tab is tapped.
|
|
||||||
///
|
|
||||||
/// The callback receives the index of the tapped tab.
|
|
||||||
final ValueChanged<int> onTap;
|
final ValueChanged<int> onTap;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final Translations t = Translations.of(context);
|
final Translations t = Translations.of(context);
|
||||||
// Client App colors from design system
|
|
||||||
const Color activeColor = UiColors.textPrimary;
|
const Color activeColor = UiColors.textPrimary;
|
||||||
const Color inactiveColor = UiColors.textInactive;
|
const Color inactiveColor = UiColors.textInactive;
|
||||||
|
|
||||||
return Stack(
|
return Stack(
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
// Glassmorphic background with blur effect
|
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: ClipRect(
|
child: ClipRect(
|
||||||
child: BackdropFilter(
|
child: BackdropFilter(
|
||||||
@@ -62,7 +41,6 @@ class ClientMainBottomBar extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Navigation items
|
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
bottom: MediaQuery.of(context).padding.bottom + UiConstants.space2,
|
bottom: MediaQuery.of(context).padding.bottom + UiConstants.space2,
|
||||||
@@ -74,6 +52,7 @@ class ClientMainBottomBar extends StatelessWidget {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
_buildNavItem(
|
_buildNavItem(
|
||||||
index: 0,
|
index: 0,
|
||||||
|
id: 'client_nav_coverage',
|
||||||
icon: UiIcons.calendar,
|
icon: UiIcons.calendar,
|
||||||
label: t.client_main.tabs.coverage,
|
label: t.client_main.tabs.coverage,
|
||||||
activeColor: activeColor,
|
activeColor: activeColor,
|
||||||
@@ -81,6 +60,7 @@ class ClientMainBottomBar extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
_buildNavItem(
|
_buildNavItem(
|
||||||
index: 1,
|
index: 1,
|
||||||
|
id: 'client_nav_billing',
|
||||||
icon: UiIcons.dollar,
|
icon: UiIcons.dollar,
|
||||||
label: t.client_main.tabs.billing,
|
label: t.client_main.tabs.billing,
|
||||||
activeColor: activeColor,
|
activeColor: activeColor,
|
||||||
@@ -88,6 +68,7 @@ class ClientMainBottomBar extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
_buildNavItem(
|
_buildNavItem(
|
||||||
index: 2,
|
index: 2,
|
||||||
|
id: 'client_nav_home',
|
||||||
icon: UiIcons.building,
|
icon: UiIcons.building,
|
||||||
label: t.client_main.tabs.home,
|
label: t.client_main.tabs.home,
|
||||||
activeColor: activeColor,
|
activeColor: activeColor,
|
||||||
@@ -95,6 +76,7 @@ class ClientMainBottomBar extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
_buildNavItem(
|
_buildNavItem(
|
||||||
index: 3,
|
index: 3,
|
||||||
|
id: 'client_nav_orders',
|
||||||
icon: UiIcons.file,
|
icon: UiIcons.file,
|
||||||
label: t.client_main.tabs.orders,
|
label: t.client_main.tabs.orders,
|
||||||
activeColor: activeColor,
|
activeColor: activeColor,
|
||||||
@@ -102,6 +84,7 @@ class ClientMainBottomBar extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
_buildNavItem(
|
_buildNavItem(
|
||||||
index: 4,
|
index: 4,
|
||||||
|
id: 'client_nav_reports',
|
||||||
icon: UiIcons.chart,
|
icon: UiIcons.chart,
|
||||||
label: t.client_main.tabs.reports,
|
label: t.client_main.tabs.reports,
|
||||||
activeColor: activeColor,
|
activeColor: activeColor,
|
||||||
@@ -114,15 +97,9 @@ class ClientMainBottomBar extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a single navigation item.
|
|
||||||
///
|
|
||||||
/// Uses design system tokens for all styling:
|
|
||||||
/// - Icon size uses a standard value (24px is acceptable for navigation icons)
|
|
||||||
/// - Spacing uses [UiConstants.space1]
|
|
||||||
/// - Typography uses [UiTypography.footnote2m]
|
|
||||||
/// - Colors are passed as parameters from design system
|
|
||||||
Widget _buildNavItem({
|
Widget _buildNavItem({
|
||||||
required int index,
|
required int index,
|
||||||
|
required String id,
|
||||||
required IconData icon,
|
required IconData icon,
|
||||||
required String label,
|
required String label,
|
||||||
required Color activeColor,
|
required Color activeColor,
|
||||||
@@ -130,6 +107,9 @@ class ClientMainBottomBar extends StatelessWidget {
|
|||||||
}) {
|
}) {
|
||||||
final bool isSelected = currentIndex == index;
|
final bool isSelected = currentIndex == index;
|
||||||
return Expanded(
|
return Expanded(
|
||||||
|
child: Semantics(
|
||||||
|
identifier: id,
|
||||||
|
label: label,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => onTap(index),
|
onTap: () => onTap(index),
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
@@ -140,7 +120,7 @@ class ClientMainBottomBar extends StatelessWidget {
|
|||||||
Icon(
|
Icon(
|
||||||
icon,
|
icon,
|
||||||
color: isSelected ? activeColor : inactiveColor,
|
color: isSelected ? activeColor : inactiveColor,
|
||||||
size: 24, // Standard navigation icon size
|
size: 24,
|
||||||
),
|
),
|
||||||
const SizedBox(height: UiConstants.space1),
|
const SizedBox(height: UiConstants.space1),
|
||||||
Text(
|
Text(
|
||||||
@@ -152,6 +132,7 @@ class ClientMainBottomBar extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,17 +86,23 @@ class ClientHomeHeader extends StatelessWidget {
|
|||||||
Row(
|
Row(
|
||||||
spacing: UiConstants.space2,
|
spacing: UiConstants.space2,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
HeaderIconButton(
|
Semantics(
|
||||||
|
identifier: 'client_home_edit_mode',
|
||||||
|
child: HeaderIconButton(
|
||||||
icon: UiIcons.edit,
|
icon: UiIcons.edit,
|
||||||
isActive: state.isEditMode,
|
isActive: state.isEditMode,
|
||||||
onTap: () => BlocProvider.of<ClientHomeBloc>(
|
onTap: () => BlocProvider.of<ClientHomeBloc>(
|
||||||
context,
|
context,
|
||||||
).add(ClientHomeEditModeToggled()),
|
).add(ClientHomeEditModeToggled()),
|
||||||
),
|
),
|
||||||
HeaderIconButton(
|
),
|
||||||
|
Semantics(
|
||||||
|
identifier: 'client_home_settings',
|
||||||
|
child: HeaderIconButton(
|
||||||
icon: UiIcons.settings,
|
icon: UiIcons.settings,
|
||||||
onTap: () => Modular.to.toClientSettings(),
|
onTap: () => Modular.to.toClientSettings(),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user