test: add QA coverage — access unit tests, VideoPlayer snapshots, Maestro E2E flows, testIDs
- Add testIDs to explore, workout detail, and collection detail screens - Add testID prop to VideoPlayer component - Create access service unit tests (isFreeWorkout, canAccessWorkout) - Create VideoPlayer rendering snapshot tests (preview/background modes) - Create Maestro E2E flows: explore-freemium, collection-detail - Update tab-navigation flow with Explore screen assertions - Update profile-settings flow with real activity stat assertions - Update all-tests suite to include new flows
This commit is contained in:
@@ -77,6 +77,7 @@ function CollectionCard({
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
testID={`collection-card-${title.toLowerCase().replace(/\s+/g, '-')}`}
|
||||
style={styles.collectionCard}
|
||||
onPress={() => {
|
||||
haptics.buttonTap()
|
||||
@@ -121,6 +122,7 @@ function WorkoutCard({
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
testID={`workout-card-${workout.id}`}
|
||||
style={[styles.workoutCard, { borderColor: colors.border.glassLight }]}
|
||||
onPress={onPress}
|
||||
>
|
||||
@@ -138,7 +140,7 @@ function WorkoutCard({
|
||||
</View>
|
||||
|
||||
{isLocked && (
|
||||
<View style={styles.lockBadge}>
|
||||
<View testID={`lock-badge-${workout.id}`} style={styles.lockBadge}>
|
||||
<Ionicons name="lock-closed" size={10} color="#FFFFFF" />
|
||||
</View>
|
||||
)}
|
||||
@@ -279,8 +281,9 @@ export default function ExploreScreen() {
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: colors.bg.base, paddingTop: insets.top }]}>
|
||||
<View testID="explore-screen" style={[styles.container, { backgroundColor: colors.bg.base, paddingTop: insets.top }]}>
|
||||
<ScrollView
|
||||
testID="explore-scroll"
|
||||
style={styles.scrollView}
|
||||
contentContainerStyle={[styles.scrollContent, { paddingBottom: insets.bottom + 100 }]}
|
||||
showsVerticalScrollIndicator={false}
|
||||
@@ -295,7 +298,7 @@ export default function ExploreScreen() {
|
||||
</View>
|
||||
|
||||
{collections.length > 0 && (
|
||||
<View style={styles.collectionsSection}>
|
||||
<View testID="collections-section" style={styles.collectionsSection}>
|
||||
<StyledText size={22} weight="bold" color={colors.text.primary}>
|
||||
{t('screens:explore.collections')}
|
||||
</StyledText>
|
||||
@@ -320,7 +323,7 @@ export default function ExploreScreen() {
|
||||
)}
|
||||
|
||||
{featured.length > 0 && (
|
||||
<View style={styles.section}>
|
||||
<View testID="featured-section" style={styles.section}>
|
||||
<StyledText size={22} weight="bold" color={colors.text.primary}>
|
||||
{t('screens:explore.featured')}
|
||||
</StyledText>
|
||||
@@ -337,7 +340,7 @@ export default function ExploreScreen() {
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View style={styles.filtersSection}>
|
||||
<View testID="filters-section" style={styles.filtersSection}>
|
||||
<View style={styles.filterHeader}>
|
||||
<StyledText size={22} weight="bold" color={colors.text.primary}>
|
||||
{t('screens:explore.allWorkouts')}
|
||||
|
||||
@@ -79,10 +79,10 @@ export default function CollectionDetailScreen() {
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { paddingTop: insets.top }]}>
|
||||
<View testID="collection-detail-screen" style={[styles.container, { paddingTop: insets.top }]}>
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<Pressable onPress={handleBack} style={styles.backButton}>
|
||||
<Pressable testID="collection-back-button" onPress={handleBack} style={styles.backButton}>
|
||||
<Ionicons name="chevron-back" size={24} color={colors.text.primary} />
|
||||
</Pressable>
|
||||
<StyledText size={22} weight="bold" color={colors.text.primary} numberOfLines={1} style={{ flex: 1, textAlign: 'center' }}>
|
||||
@@ -97,7 +97,7 @@ export default function CollectionDetailScreen() {
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{/* Hero Card */}
|
||||
<View style={styles.heroCard}>
|
||||
<View testID="collection-hero" style={styles.heroCard}>
|
||||
<LinearGradient
|
||||
colors={collection.gradient ?? [BRAND.PRIMARY, '#FF3B30']}
|
||||
start={{ x: 0, y: 0 }}
|
||||
@@ -133,6 +133,7 @@ export default function CollectionDetailScreen() {
|
||||
{workouts.map((workout) => (
|
||||
<Pressable
|
||||
key={workout.id}
|
||||
testID={`collection-workout-${workout.id}`}
|
||||
style={styles.workoutCard}
|
||||
onPress={() => handleWorkoutPress(workout.id)}
|
||||
>
|
||||
|
||||
@@ -90,7 +90,7 @@ export default function WorkoutDetailScreen() {
|
||||
const repeatCount = Math.max(1, Math.floor(workout.rounds / workout.exercises.length))
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View testID="workout-detail-screen" style={styles.container}>
|
||||
{/* Header with SwiftUI glass button */}
|
||||
<View style={[styles.header, { paddingTop: insets.top + SPACING[3] }]}>
|
||||
<RNText style={styles.headerTitle} numberOfLines={1}>
|
||||
@@ -131,6 +131,7 @@ export default function WorkoutDetailScreen() {
|
||||
mode="preview"
|
||||
isPlaying={true}
|
||||
style={styles.videoPreview}
|
||||
testID="workout-video-preview"
|
||||
/>
|
||||
{/* Quick stats */}
|
||||
<View style={styles.quickStats}>
|
||||
@@ -204,6 +205,7 @@ export default function WorkoutDetailScreen() {
|
||||
<View style={[styles.bottomBar, { paddingBottom: insets.bottom + SPACING[4] }]}>
|
||||
<BlurView intensity={80} tint="dark" style={StyleSheet.absoluteFill} />
|
||||
<Pressable
|
||||
testID={isLocked ? 'workout-unlock-button' : 'workout-start-button'}
|
||||
style={({ pressed }) => [
|
||||
styles.startButton,
|
||||
isLocked && styles.lockedButton,
|
||||
@@ -214,7 +216,7 @@ export default function WorkoutDetailScreen() {
|
||||
{isLocked && (
|
||||
<Ionicons name="lock-closed" size={18} color="#FFFFFF" style={{ marginRight: 8 }} />
|
||||
)}
|
||||
<RNText style={styles.startButtonText}>
|
||||
<RNText testID="workout-cta-text" style={styles.startButtonText}>
|
||||
{isLocked ? t('screens:workout.unlockWithPremium') : t('screens:workout.startWorkout')}
|
||||
</RNText>
|
||||
</Pressable>
|
||||
|
||||
Reference in New Issue
Block a user