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:
Millian Lamiaux
2026-03-24 12:04:48 +01:00
parent 8703c484e8
commit cd065d07c3
138 changed files with 26819 additions and 1043 deletions

View 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

View 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

View 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

View 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"

View 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

View 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"

View 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"

View 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"

View 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"

View 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