feat: explore tab, React Query data layer, programs, sync, analytics, testing infrastructure
- Replace browse tab with Supabase-connected explore tab with filters - Add React Query for data fetching with loading states - Add 3 structured programs with weekly progression - Add Supabase anonymous auth sync service - Add PostHog analytics with screen tracking and events - Add comprehensive test strategy (Vitest + Maestro E2E) - Add RevenueCat subscription system with DEV simulation - Add i18n translations for new screens (EN/FR/DE/ES) - Add data deletion modal, sync consent modal - Add assessment screen and program routes - Add GitHub Actions CI workflow - Update activity store with sync integration
This commit is contained in:
82
.maestro/flows/activity-tab.yaml
Normal file
82
.maestro/flows/activity-tab.yaml
Normal file
@@ -0,0 +1,82 @@
|
||||
# Activity Tab Flow Test
|
||||
# Tests the activity/stats dashboard screen
|
||||
# Prerequisite: User must have completed onboarding
|
||||
|
||||
appId: com.millianlmx.tabatafit
|
||||
name: Activity Tab
|
||||
|
||||
---
|
||||
# Start from home screen
|
||||
- assertVisible: "program-card-upper-body"
|
||||
|
||||
# Navigate to Activity tab
|
||||
- tapOn:
|
||||
text: "Activity"
|
||||
optional: true
|
||||
- tapOn:
|
||||
id: "activity-tab"
|
||||
optional: true
|
||||
|
||||
# Verify activity screen loaded — check for stats elements
|
||||
- assertVisible:
|
||||
text: ".*Activity.*"
|
||||
timeout: 5000
|
||||
|
||||
# Check for streak display
|
||||
- assertVisible:
|
||||
text: ".*streak.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Check for workout count stats
|
||||
- assertVisible:
|
||||
text: ".*workout.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Check for calories display
|
||||
- assertVisible:
|
||||
text: ".*cal.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Scroll down to see weekly chart or history
|
||||
- scroll:
|
||||
direction: DOWN
|
||||
duration: 500
|
||||
|
||||
# Check for weekly chart or activity history section
|
||||
- assertVisible:
|
||||
text: ".*week.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Scroll down further to see history
|
||||
- scroll:
|
||||
direction: DOWN
|
||||
duration: 500
|
||||
|
||||
# Check for achievement badges if present
|
||||
- assertVisible:
|
||||
text: ".*achievement.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Scroll back to top
|
||||
- scroll:
|
||||
direction: UP
|
||||
duration: 1000
|
||||
|
||||
# Navigate back to Home
|
||||
- tapOn:
|
||||
text: "Home"
|
||||
optional: true
|
||||
- tapOn:
|
||||
id: "home-tab"
|
||||
optional: true
|
||||
|
||||
# Verify home screen
|
||||
- assertVisible:
|
||||
id: "program-card-upper-body"
|
||||
timeout: 5000
|
||||
optional: true
|
||||
27
.maestro/flows/all-tests.yaml
Normal file
27
.maestro/flows/all-tests.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
# All Tests Suite
|
||||
# Run all test flows sequentially
|
||||
|
||||
appId: com.millianlmx.tabatafit
|
||||
name: Full Test Suite
|
||||
|
||||
env:
|
||||
TEST_USER_NAME: Maestro Test User
|
||||
|
||||
---
|
||||
# Run onboarding flow
|
||||
- runFlow: ./onboarding.yaml
|
||||
|
||||
# Run program browsing
|
||||
- runFlow: ./program-browse.yaml
|
||||
|
||||
# Run tab navigation
|
||||
- runFlow: ./tab-navigation.yaml
|
||||
|
||||
# Run workout player
|
||||
- runFlow: ./workout-player.yaml
|
||||
|
||||
# Run activity tab
|
||||
- runFlow: ./activity-tab.yaml
|
||||
|
||||
# Run profile & settings
|
||||
- runFlow: ./profile-settings.yaml
|
||||
16
.maestro/flows/assessment.yaml
Normal file
16
.maestro/flows/assessment.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
# Assessment Flow Test
|
||||
# Tests starting the assessment workout from home screen
|
||||
# Prerequisite: User must have completed onboarding but not assessment
|
||||
|
||||
appId: com.millianlmx.tabatafit
|
||||
name: Assessment Flow
|
||||
|
||||
---
|
||||
# Look for assessment card (only visible if not completed)
|
||||
- assertVisible: "assessment-card"
|
||||
- tapOn: "assessment-card"
|
||||
|
||||
# Verify we're on assessment screen
|
||||
- assertVisible:
|
||||
text: ".*Assessment.*"
|
||||
timeout: 5000
|
||||
46
.maestro/flows/onboarding.yaml
Normal file
46
.maestro/flows/onboarding.yaml
Normal file
@@ -0,0 +1,46 @@
|
||||
# Onboarding Flow Test
|
||||
# Tests the complete 6-step onboarding process
|
||||
|
||||
appId: com.millianlmx.tabatafit
|
||||
name: Onboarding Flow
|
||||
|
||||
---
|
||||
- launchApp
|
||||
# Step 1: Problem Screen
|
||||
- assertVisible: "onboarding-problem-cta"
|
||||
- tapOn: "onboarding-problem-cta"
|
||||
|
||||
# Step 2: Empathy Screen - Select barriers
|
||||
- assertVisible: "barrier-no-time"
|
||||
- tapOn: "barrier-no-time"
|
||||
- tapOn: "barrier-low-motivation"
|
||||
- assertVisible: "onboarding-empathy-continue"
|
||||
- tapOn: "onboarding-empathy-continue"
|
||||
|
||||
# Step 3: Solution Screen
|
||||
- assertVisible: "onboarding-solution-cta"
|
||||
- tapOn: "onboarding-solution-cta"
|
||||
|
||||
# Step 4: Wow Screen (features reveal)
|
||||
- assertVisible: "onboarding-wow-cta"
|
||||
- tapOn: "onboarding-wow-cta"
|
||||
|
||||
# Step 5: Personalization
|
||||
- assertVisible: "name-input"
|
||||
- tapOn: "name-input"
|
||||
- inputText: "Test User"
|
||||
|
||||
- tapOn: "level-intermediate"
|
||||
- tapOn: "goal-strength"
|
||||
- tapOn: "frequency-3x"
|
||||
|
||||
- assertVisible: "onboarding-personalization-continue"
|
||||
- tapOn: "onboarding-personalization-continue"
|
||||
|
||||
# Step 6: Paywall - Skip subscription
|
||||
- assertVisible: "subscribe-button"
|
||||
- assertVisible: "skip-paywall"
|
||||
- tapOn: "skip-paywall"
|
||||
|
||||
# Verify we're on the home screen
|
||||
- assertVisible: "program-card-upper-body"
|
||||
111
.maestro/flows/profile-settings.yaml
Normal file
111
.maestro/flows/profile-settings.yaml
Normal file
@@ -0,0 +1,111 @@
|
||||
# Profile & Settings Flow Test
|
||||
# Tests the profile screen, settings toggles, and navigation
|
||||
# Prerequisite: User must have completed onboarding
|
||||
|
||||
appId: com.millianlmx.tabatafit
|
||||
name: Profile Settings
|
||||
|
||||
---
|
||||
# Start from home screen
|
||||
- assertVisible: "program-card-upper-body"
|
||||
|
||||
# Navigate to Profile tab
|
||||
- tapOn:
|
||||
text: "Profile"
|
||||
optional: true
|
||||
- tapOn:
|
||||
id: "profile-tab"
|
||||
optional: true
|
||||
|
||||
# Verify profile screen loaded
|
||||
- assertVisible:
|
||||
text: ".*Profile.*"
|
||||
timeout: 5000
|
||||
|
||||
# Check user avatar/name is displayed
|
||||
- assertVisible:
|
||||
text: ".*Test User.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Check stats are visible
|
||||
- assertVisible:
|
||||
text: ".*workout.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Scroll to settings section
|
||||
- scroll:
|
||||
direction: DOWN
|
||||
duration: 500
|
||||
|
||||
# Check for Haptic Feedback toggle
|
||||
- assertVisible:
|
||||
text: ".*aptic.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Check for Sound Effects toggle
|
||||
- assertVisible:
|
||||
text: ".*ound.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Check for Voice Coaching toggle
|
||||
- assertVisible:
|
||||
text: ".*oice.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Scroll down to notifications section
|
||||
- scroll:
|
||||
direction: DOWN
|
||||
duration: 500
|
||||
|
||||
# Check for Reminders toggle
|
||||
- assertVisible:
|
||||
text: ".*eminder.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Scroll down to support section
|
||||
- scroll:
|
||||
direction: DOWN
|
||||
duration: 500
|
||||
|
||||
# Check for Rate App option
|
||||
- assertVisible:
|
||||
text: ".*Rate.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Check for Contact Us option
|
||||
- assertVisible:
|
||||
text: ".*Contact.*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Check for app version
|
||||
- assertVisible:
|
||||
text: ".*1\\..*"
|
||||
timeout: 3000
|
||||
optional: true
|
||||
|
||||
# Scroll back to top
|
||||
- scroll:
|
||||
direction: UP
|
||||
duration: 1500
|
||||
|
||||
# Navigate back to Home
|
||||
- tapOn:
|
||||
text: "Home"
|
||||
optional: true
|
||||
- tapOn:
|
||||
id: "home-tab"
|
||||
optional: true
|
||||
|
||||
# Verify home screen
|
||||
- assertVisible:
|
||||
id: "program-card-upper-body"
|
||||
timeout: 5000
|
||||
optional: true
|
||||
42
.maestro/flows/program-browse.yaml
Normal file
42
.maestro/flows/program-browse.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
# Program Browsing Test
|
||||
# Tests navigation through programs from home screen
|
||||
# Prerequisite: User must have completed onboarding
|
||||
|
||||
appId: com.millianlmx.tabatafit
|
||||
name: Program Browsing
|
||||
|
||||
---
|
||||
# Verify home screen loaded
|
||||
- assertVisible: "program-card-upper-body"
|
||||
- assertVisible: "program-card-lower-body"
|
||||
- assertVisible: "program-card-full-body"
|
||||
|
||||
# Tap Upper Body program
|
||||
- tapOn: "program-upper-body-cta"
|
||||
|
||||
# Wait for program detail screen
|
||||
- assertVisible:
|
||||
text: ".*Upper Body.*"
|
||||
timeout: 5000
|
||||
|
||||
# Navigate back
|
||||
- back
|
||||
|
||||
# Tap Lower Body program
|
||||
- assertVisible: "program-card-lower-body"
|
||||
- tapOn: "program-lower-body-cta"
|
||||
- assertVisible:
|
||||
text: ".*Lower Body.*"
|
||||
timeout: 5000
|
||||
- back
|
||||
|
||||
# Tap Full Body program
|
||||
- assertVisible: "program-card-full-body"
|
||||
- tapOn: "program-full-body-cta"
|
||||
- assertVisible:
|
||||
text: ".*Full Body.*"
|
||||
timeout: 5000
|
||||
- back
|
||||
|
||||
# Verify we're back on home
|
||||
- assertVisible: "program-card-upper-body"
|
||||
17
.maestro/flows/reset-state.yaml
Normal file
17
.maestro/flows/reset-state.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
# Reset App State Helper
|
||||
# Use this to reset the app to a fresh state for testing
|
||||
|
||||
appId: com.millianlmx.tabatafit
|
||||
name: Reset App State
|
||||
|
||||
---
|
||||
# Kill the app
|
||||
- killApp
|
||||
|
||||
# Clear app data (iOS Simulator)
|
||||
# Note: On Android, use: adb shell pm clear com.millianlmx.tabatafit
|
||||
- launchApp:
|
||||
clearState: true
|
||||
|
||||
# App should start at onboarding
|
||||
- assertVisible: "onboarding-problem-cta"
|
||||
38
.maestro/flows/subscription.yaml
Normal file
38
.maestro/flows/subscription.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
# Subscription Paywall Test
|
||||
# Tests the paywall subscription flow
|
||||
# This test requires a fresh install (onboarding not completed)
|
||||
|
||||
appId: com.millianlmx.tabatafit
|
||||
name: Subscription Paywall
|
||||
|
||||
---
|
||||
# Navigate through onboarding to paywall (steps 1-5)
|
||||
- tapOn: "onboarding-problem-cta"
|
||||
- tapOn: "barrier-no-time"
|
||||
- tapOn: "onboarding-empathy-continue"
|
||||
- tapOn: "onboarding-solution-cta"
|
||||
- tapOn: "onboarding-wow-cta"
|
||||
|
||||
# Enter name to enable continue
|
||||
- tapOn: "name-input"
|
||||
- inputText: "Premium User"
|
||||
- tapOn: "onboarding-personalization-continue"
|
||||
|
||||
# On paywall screen
|
||||
- assertVisible: "plan-yearly"
|
||||
- assertVisible: "plan-monthly"
|
||||
- assertVisible: "subscribe-button"
|
||||
- assertVisible: "skip-paywall"
|
||||
|
||||
# Test plan selection
|
||||
- tapOn: "plan-monthly"
|
||||
- assertVisible: "subscribe-button"
|
||||
|
||||
# Test restore purchases
|
||||
- tapOn: "restore-purchases"
|
||||
|
||||
# Skip paywall
|
||||
- tapOn: "skip-paywall"
|
||||
|
||||
# Verify home screen
|
||||
- assertVisible: "program-card-upper-body"
|
||||
45
.maestro/flows/tab-navigation.yaml
Normal file
45
.maestro/flows/tab-navigation.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
# Tab Navigation Test
|
||||
# Tests switching between all tabs in the app
|
||||
# Prerequisite: User must have completed onboarding
|
||||
|
||||
appId: com.millianlmx.tabatafit
|
||||
name: Tab Navigation
|
||||
|
||||
---
|
||||
# Start on home tab
|
||||
- assertVisible: "program-card-upper-body"
|
||||
|
||||
# Navigate to Explore tab
|
||||
- tapOn:
|
||||
text: "Explore"
|
||||
optional: true
|
||||
- tapOn:
|
||||
id: "explore-tab"
|
||||
optional: true
|
||||
|
||||
# Navigate to Activity tab
|
||||
- tapOn:
|
||||
text: "Activity"
|
||||
optional: true
|
||||
- tapOn:
|
||||
id: "activity-tab"
|
||||
optional: true
|
||||
|
||||
# Navigate to Profile tab
|
||||
- tapOn:
|
||||
text: "Profile"
|
||||
optional: true
|
||||
- tapOn:
|
||||
id: "profile-tab"
|
||||
optional: true
|
||||
|
||||
# Navigate back to Home
|
||||
- tapOn:
|
||||
text: "Home"
|
||||
optional: true
|
||||
- tapOn:
|
||||
id: "home-tab"
|
||||
optional: true
|
||||
|
||||
# Verify home screen
|
||||
- assertVisible: "program-card-upper-body"
|
||||
102
.maestro/flows/workout-player.yaml
Normal file
102
.maestro/flows/workout-player.yaml
Normal file
@@ -0,0 +1,102 @@
|
||||
# Workout Player Flow Test
|
||||
# Tests starting a workout, timer controls, and completion
|
||||
# Prerequisite: User must have completed onboarding
|
||||
|
||||
appId: com.millianlmx.tabatafit
|
||||
name: Workout Player
|
||||
|
||||
---
|
||||
# Start from home screen
|
||||
- assertVisible: "program-card-upper-body"
|
||||
|
||||
# Open the Upper Body program
|
||||
- tapOn: "program-upper-body-cta"
|
||||
|
||||
# Wait for program detail screen to load
|
||||
- assertVisible:
|
||||
text: ".*Upper Body.*"
|
||||
timeout: 5000
|
||||
|
||||
# Tap on first workout in the program
|
||||
- tapOn:
|
||||
text: ".*Start.*"
|
||||
index: 0
|
||||
optional: true
|
||||
- tapOn:
|
||||
text: ".*Begin.*"
|
||||
index: 0
|
||||
optional: true
|
||||
|
||||
# Wait for player screen to load — look for the play button
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: ".*PREP.*"
|
||||
timeout: 10000
|
||||
optional: true
|
||||
|
||||
# If no PREP text, look for the play icon or workout title
|
||||
- assertVisible:
|
||||
text: ".*Workout.*"
|
||||
timeout: 5000
|
||||
optional: true
|
||||
|
||||
# Start the workout — tap the play button (center of screen)
|
||||
- tapOn:
|
||||
point: "50%,50%"
|
||||
|
||||
# Wait for timer to start — PREP phase should appear
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: ".*PREP.*"
|
||||
timeout: 5000
|
||||
optional: true
|
||||
|
||||
# Wait a few seconds for the timer to tick
|
||||
- swipe:
|
||||
direction: UP
|
||||
duration: 100
|
||||
optional: true
|
||||
|
||||
# Verify timer is running — time display should be visible
|
||||
- assertVisible:
|
||||
text: ".*:.*"
|
||||
timeout: 5000
|
||||
|
||||
# Test pause — tap the pause button (center area)
|
||||
- tapOn:
|
||||
point: "50%,80%"
|
||||
optional: true
|
||||
|
||||
# Wait briefly
|
||||
- swipe:
|
||||
direction: UP
|
||||
duration: 100
|
||||
optional: true
|
||||
|
||||
# Resume — tap again
|
||||
- tapOn:
|
||||
point: "50%,80%"
|
||||
optional: true
|
||||
|
||||
# Close the player — look for close/stop button (top-left area)
|
||||
- tapOn:
|
||||
point: "10%,8%"
|
||||
optional: true
|
||||
|
||||
# If close button was in a different location, try the stop button
|
||||
- tapOn:
|
||||
text: ".*close.*"
|
||||
optional: true
|
||||
|
||||
# Verify we're back on the program screen or home
|
||||
- assertVisible:
|
||||
text: ".*Upper Body.*"
|
||||
timeout: 5000
|
||||
optional: true
|
||||
|
||||
# Go back to home
|
||||
- back
|
||||
- assertVisible:
|
||||
id: "program-card-upper-body"
|
||||
timeout: 5000
|
||||
optional: true
|
||||
Reference in New Issue
Block a user