# --- Mobile App Development --- .PHONY: mobile-install mobile-info mobile-analyze mobile-client-dev-android mobile-staff-dev-android mobile-client-build mobile-staff-build mobile-hot-reload mobile-hot-restart test-e2e test-e2e-setup test-e2e-client test-e2e-staff test-e2e-client-happy-path test-e2e-staff-happy-path test-e2e-staff-auth test-e2e-staff-navigation test-e2e-staff-profile test-e2e-staff-profile-extended test-e2e-staff-shifts test-e2e-staff-compliance test-e2e-staff-home test-e2e-staff-sign-out test-e2e-client-auth test-e2e-client-navigation test-e2e-client-orders test-e2e-client-settings test-e2e-client-sign-out MOBILE_DIR := apps/mobile # Device ID for running mobile apps (override with DEVICE=) # Find your device ID with: flutter devices DEVICE ?= android # --- General --- mobile-install: install-melos dataconnect-generate-sdk @echo "--> Bootstrapping mobile workspace (Melos)..." @cd $(MOBILE_DIR) && melos bootstrap @echo "--> Generating localization files..." @cd $(MOBILE_DIR) && melos run gen:l10n mobile-info: @echo "--> Fetching mobile command info..." @cd $(MOBILE_DIR) && melos run info mobile-analyze: @echo "--> Analyzing mobile workspace for compile-time errors..." @cd $(MOBILE_DIR) && flutter analyze # --- Hot Reload & Restart --- mobile-hot-reload: @echo "--> Triggering hot reload for running Flutter app..." @cd $(MOBILE_DIR) && echo "r" | nc localhost 54321 2>/dev/null || \ (cd apps/client && flutter attach --pid-file /tmp/flutter_client.pid && echo "r") || \ (cd apps/staff && flutter attach --pid-file /tmp/flutter_staff.pid && echo "r") || \ echo "❌ No running Flutter app found. Start an app first with mobile-client-dev-android or mobile-staff-dev-android" mobile-hot-restart: @echo "--> Triggering hot restart for running Flutter app..." @cd $(MOBILE_DIR) && echo "R" | nc localhost 54321 2>/dev/null || \ (cd apps/client && flutter attach --pid-file /tmp/flutter_client.pid && echo "R") || \ (cd apps/staff && flutter attach --pid-file /tmp/flutter_staff.pid && echo "R") || \ echo "❌ No running Flutter app found. Start an app first with mobile-client-dev-android or mobile-staff-dev-android" # --- Client App --- mobile-client-dev-android: dataconnect-generate-sdk @echo "--> Running client app on Android (device: $(DEVICE))..." @cd $(MOBILE_DIR) && melos run start:client -- -d $(DEVICE) --dart-define-from-file=../../config.dev.json mobile-client-build: dataconnect-generate-sdk @if [ -z "$(PLATFORM)" ]; then \ echo "ERROR: PLATFORM is required (e.g. make mobile-client-build PLATFORM=apk)"; exit 1; \ fi $(eval MODE ?= release) @echo "--> Building client app for $(PLATFORM) in $(MODE) mode..." @cd $(MOBILE_DIR) && \ melos exec --scope="core_localization" -- "dart run slang" && \ melos exec --scope="core_localization" -- "dart run build_runner build --delete-conflicting-outputs" && \ melos exec --scope="krowwithus_client" -- "flutter build $(PLATFORM) --$(MODE) --dart-define-from-file=../../config.dev.json" # --- Staff App --- mobile-staff-dev-android: dataconnect-generate-sdk @echo "--> Running staff app on Android (device: $(DEVICE))..." @cd $(MOBILE_DIR) && melos run start:staff -- -d $(DEVICE) --dart-define-from-file=../../config.dev.json mobile-staff-build: dataconnect-generate-sdk @if [ -z "$(PLATFORM)" ]; then \ echo "ERROR: PLATFORM is required (e.g. make mobile-staff-build PLATFORM=apk)"; exit 1; \ fi $(eval MODE ?= release) @echo "--> Building staff app for $(PLATFORM) in $(MODE) mode..." @cd $(MOBILE_DIR) && \ melos exec --scope="core_localization" -- "dart run slang" && \ melos exec --scope="core_localization" -- "dart run build_runner build --delete-conflicting-outputs" && \ melos exec --scope="krowwithus_staff" -- "flutter build $(PLATFORM) --$(MODE) --dart-define-from-file=../../config.dev.json" # --- E2E (Maestro) --- # Set env before running: TEST_CLIENT_EMAIL, TEST_CLIENT_PASSWORD, TEST_CLIENT_COMPANY, TEST_STAFF_PHONE, TEST_STAFF_OTP, TEST_STAFF_SIGNUP_PHONE # Client: testclient@gmail.com / testclient! # Staff: TEST_STAFF_PHONE=5555551234 TEST_STAFF_OTP=123123 (+1 555-555-1234 in Firebase) test-e2e-setup: @echo "--> Checking Maestro CLI..." @maestro --version @echo "--> Maestro OK. Ensure apps are built & installed (see docs/research/maestro-test-run-instructions.md)" # Maestro runs flows in parallel by default; --shard-split=1 forces sequential (avoids tcp:7001 closed) # Note: -s/--shards is deprecated, use --shard-split instead 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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -e TEST_CLIENT_EMAIL="$${TEST_CLIENT_EMAIL}" -e TEST_CLIENT_PASSWORD="$${TEST_CLIENT_PASSWORD}" \ -e TEST_CLIENT_COMPANY="$${TEST_CLIENT_COMPANY}" # 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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -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 \ -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}"