Initial commit

This commit is contained in:
jpgiannetti
2026-01-31 11:45:11 +01:00
commit f99fb3c614
166 changed files with 115155 additions and 0 deletions

View File

@@ -0,0 +1,425 @@
# language: fr
Fonctionnalité: Synchronisation actions offline
En tant qu'utilisateur
Je veux que mes actions offline soient synchronisées quand je me reconnecte
Afin de ne perdre aucune interaction même sans connexion
Contexte:
Étant donné que j'utilise l'application RoadWave
# ===== ACTIONS STOCKÉES LOCALEMENT =====
Scénario: Like d'un contenu en mode offline
Étant donné que je n'ai aucune connexion Internet
Quand je like un contenu téléchargé
Alors l'action est enregistrée localement dans SQLite:
```sql
INSERT INTO pending_actions (type, content_id, created_at)
VALUES ('like', 'abc123', '2025-06-15 14:30:00');
```
Et l'UI affiche immédiatement le like (optimistic update)
Scénario: Unlike d'un contenu en mode offline
Étant donné que je n'ai aucune connexion Internet
Et que j'avais liké un contenu
Quand je retire mon like
Alors l'action est enregistrée localement:
```sql
INSERT INTO pending_actions (type, content_id, created_at)
VALUES ('unlike', 'abc123', '2025-06-15 14:35:00');
```
Et l'UI retire immédiatement le like
Scénario: Abonnement à un créateur en mode offline
Étant donné que je n'ai aucune connexion Internet
Quand je m'abonne à un créateur
Alors l'action est enregistrée localement:
```sql
INSERT INTO pending_actions (type, creator_id, created_at)
VALUES ('subscribe', 'creator456', '2025-06-15 14:40:00');
```
Et l'UI affiche immédiatement "Abonné "
Scénario: Désabonnement d'un créateur en mode offline
Étant donné que je n'ai aucune connexion Internet
Et que j'étais abonné à un créateur
Quand je me désabonne
Alors l'action est enregistrée localement:
```sql
INSERT INTO pending_actions (type, creator_id, created_at)
VALUES ('unsubscribe', 'creator456', '2025-06-15 14:45:00');
```
Et l'UI affiche "S'abonner"
Scénario: Signalement d'un contenu en mode offline
Étant donné que je n'ai aucune connexion Internet
Quand je signale un contenu pour "Contenu inapproprié"
Alors l'action est enregistrée localement:
```sql
INSERT INTO pending_actions (type, content_id, reason, created_at)
VALUES ('report', 'abc123', 'Contenu inapproprié', '2025-06-15 14:50:00');
```
Et je vois "Signalement enregistré. Sera envoyé à la reconnexion."
Scénario: Progression audio-guide en mode offline
Étant donné que je n'ai aucune connexion Internet
Et que j'écoute un audio-guide multi-séquences
Quand je termine la séquence 3/10
Alors la progression est enregistrée localement:
```sql
INSERT INTO pending_actions (type, guide_id, sequence_id, created_at)
VALUES ('guide_progress', 'guide789', 'seq003', '2025-06-15 15:00:00');
```
Et ma progression est sauvegardée
Scénario: Multiple actions offline stockées en queue
Étant donné que je n'ai aucune connexion Internet pendant 2 jours
Quand j'effectue plusieurs actions:
| action | cible |
| like | contenu A |
| like | contenu B |
| subscribe | créateur X |
| unlike | contenu C |
| report | contenu D |
Alors les 5 actions sont stockées dans pending_actions
Et elles seront synchronisées dans l'ordre à la reconnexion
# ===== SYNCHRONISATION AUTOMATIQUE =====
Scénario: Détection reconnexion Internet
Étant donné que j'étais en mode offline
Quand l'app détecte une reconnexion Internet
Alors le processus de synchronisation démarre automatiquement
Et je vois une notification "Synchronisation en cours..."
Scénario: Récupération queue locale pendant sync
Étant donné que la synchronisation démarre
Quand l'app récupère les actions en attente
Alors une requête SQL est exécutée:
```sql
SELECT * FROM pending_actions ORDER BY created_at ASC;
```
Et toutes les actions sont récupérées dans l'ordre chronologique
Scénario: Envoi batch API des actions
Étant donné que 15 actions sont en attente
Quand le batch est envoyé au backend
Alors une requête POST /sync/actions est faite:
```json
{
"actions": [
{"type": "like", "content_id": "abc123", "timestamp": "2025-06-15T14:30:00Z"},
{"type": "subscribe", "creator_id": "creator456", "timestamp": "2025-06-15T14:40:00Z"},
{"type": "unlike", "content_id": "def789", "timestamp": "2025-06-15T14:50:00Z"},
...
]
}
```
Et toutes les actions sont groupées en une seule requête
Scénario: Backend traite chaque action
Étant donné que le backend reçoit le batch d'actions
Quand il traite chaque action
Alors pour chaque action:
| étape | détail |
| Validation | Vérifier user_id, content_id valides |
| Vérification existence | Contenu/créateur existe toujours ? |
| Application action | INSERT/UPDATE/DELETE en base |
| Mise à jour compteurs | Likes, abonnés, etc. |
| Impact sur algorithme | Mise à jour jauges si nécessaire |
Scénario: Confirmation réception et suppression queue locale
Étant donné que le backend a traité toutes les actions avec succès
Quand la confirmation est reçue par l'app
Alors les actions sont supprimées de la queue locale:
```sql
DELETE FROM pending_actions WHERE id IN (1, 2, 3, ..., 15);
```
Et la table pending_actions est vidée
Scénario: Toast confirmation synchronisation
Étant donné que 15 actions ont été synchronisées
Quand la synchronisation se termine
Alors je vois un toast:
"""
Synchronisation réussie
3 likes, 1 abonnement et 1 signalement synchronisés.
"""
Scénario: Synchronisation silencieuse si peu d'actions
Étant donné que j'ai seulement 2 actions en attente
Quand la synchronisation se termine
Alors aucun toast n'est affiché (sync silencieuse)
Et l'expérience reste fluide
Mais je peux voir le détail dans l'historique des syncs
# ===== GESTION ERREURS SYNC =====
Scénario: Échec synchronisation - Retry automatique
Étant donné que la synchronisation échoue (erreur réseau)
Quand l'échec est détecté
Alors un retry automatique est programmé dans 30 secondes
Et les actions restent dans pending_actions
Scénario: 3 tentatives échouées - Notification utilisateur
Étant donné que 3 tentatives de synchronisation ont échoué
Quand la 3ème tentative échoue
Alors je reçois une notification:
"""
Impossible de synchroniser vos actions
15 actions en attente de synchronisation.
Vérifiez votre connexion et réessayez.
[Réessayer maintenant] [Plus tard]
```
Scénario: Actions conservées jusqu'à sync réussie
Étant donné que la synchronisation échoue plusieurs fois
Quand les tentatives continuent d'échouer
Alors les actions restent dans pending_actions
Et aucune action n'est perdue
Et elles seront envoyées dès que la connexion sera stable
Scénario: Rétention max 7 jours - Purge automatique
Étant donné qu'une action est en attente depuis 7 jours
Quand le système détecte cette ancienneté
Alors l'action est automatiquement supprimée de la queue
Et je vois "1 action trop ancienne supprimée (>7 jours)"
Et cela évite une queue infinie
Scénario: Justification rétention 7 jours
Étant donné qu'un utilisateur ne se connecte jamais pendant 2 semaines
Quand ses actions ont >7 jours
Alors elles sont purgées automatiquement
Car après 7 jours, l'action perd sa pertinence
Et évite une queue qui grandit indéfiniment
Scénario: Retry manuel après échec
Étant donné que la synchronisation a échoué
Quand je clique sur "Réessayer maintenant"
Alors une nouvelle tentative de synchronisation est lancée immédiatement
Et si elle réussit, les actions sont synchronisées
# ===== CONFLITS CONTENUS SUPPRIMÉS =====
Scénario: Backend retourne contenus supprimés
Étant donné que j'ai liké un contenu offline
Mais que le contenu a été supprimé entre temps
Quand le backend traite la synchronisation
Alors il retourne:
```json
{
"status": "partial_success",
"deleted_content_ids": [123, 456],
"failed_actions": [
{"type": "like", "content_id": "123", "reason": "content_deleted"}
]
}
```
Scénario: App supprime fichiers locaux contenus supprimés
Étant donné que le backend retourne deleted_content_ids: [123, 456]
Quand l'app traite la réponse
Alors elle supprime les fichiers locaux des contenus 123 et 456
Et libère l'espace disque
Et les actions associées sont retirées de la queue
Scénario: Contenu supprimé en cours d'écoute
Étant donné que j'écoute le contenu 123 en offline
Et que la sync détecte que le contenu a été supprimé
Quand la lecture actuelle se termine
Alors l'app attend 2 secondes
Et passe automatiquement au contenu suivant
Et le fichier du contenu 123 est supprimé en arrière-plan
Scénario: Toast notification contenu retiré
Étant donné que 2 contenus téléchargés ont été supprimés
Quand la synchronisation se termine
Alors je vois un toast:
"""
🗑 2 contenus téléchargés ont été retirés
Raison: Violation des règles de la plateforme
"""
Scénario: Contenu modéré après téléchargement
Étant donné que j'ai téléchargé un contenu qui est ensuite modéré
Quand la synchronisation détecte la modération
Alors le contenu est immédiatement supprimé du device
Et je ne peux plus l'écouter
Et cela garantit la conformité même offline
# ===== JUSTIFICATIONS =====
Scénario: Justification pas de conflit possible
Étant donné que les actions offline sont unilatérales (likes, abonnements)
Quand elles sont synchronisées
Alors il n'y a pas de conflit de version possible
Car l'utilisateur ajoute/retire simplement des préférences
Et pas de merge complexe nécessaire
Scénario: Justification UX fluide offline
Étant donné que toutes les actions fonctionnent offline
Quand l'utilisateur interagit sans connexion
Alors l'expérience est identique au mode online
Et l'utilisateur n'est pas bloqué
Et peut utiliser l'app normalement
Scénario: Justification batch = Économie requêtes
Étant donné que 15 actions sont en attente
Quand elles sont synchronisées en batch
Alors 1 seule requête HTTP est envoyée (vs 15 si individuelles)
Et cela économise la bande passante et la batterie
Et réduit la charge serveur
Scénario: Justification conformité modération offline
Étant donné qu'un contenu illégal est modéré pendant qu'un user est offline
Quand le user se reconnecte
Alors le contenu est immédiatement supprimé de son device
Et cela garantit que les contenus illégaux disparaissent même offline
# ===== STATISTIQUES ET MONITORING =====
Scénario: Historique synchronisations
Étant donné que j'accède à "Paramètres > Synchronisation"
Quand je consulte l'historique
Alors je vois:
| date | actions sync | statut |
| 15/06/2025 14:30:00 | 15 | Réussi |
| 14/06/2025 09:15:00 | 7 | Réussi |
| 13/06/2025 18:45:00 | 3 | Échec |
Scénario: Détail d'une synchronisation
Étant donné que je clique sur une ligne de l'historique
Quand le détail s'affiche
Alors je vois:
```
Synchronisation du 15/06/2025 14:30:00
Actions synchronisées:
3 likes
1 abonnement
1 signalement
10 progressions audio-guides
Durée: 1.2s
Statut: Réussi
```
Scénario: Compteur actions en attente visible
Étant donné que j'ai 12 actions en attente de synchronisation
Quand j'accède à l'onglet Profil
Alors je vois un badge "12" sur l'icône de synchronisation
Et je sais qu'il y a des actions en attente
Scénario: Synchronisation manuelle forcée
Étant donné que je veux forcer une synchronisation immédiate
Quand je vais dans "Paramètres > Synchronisation"
Et que je clique sur "Synchroniser maintenant"
Alors la synchronisation démarre immédiatement
Et toutes les actions en attente sont envoyées
Scénario: Statistiques utilisateur - Syncs effectuées
Étant donné que j'accède à mes statistiques
Quand je consulte la section Synchronisation
Alors je vois:
| métrique | valeur |
| Synchronisations depuis début | 87 |
| Actions synchronisées total | 1,234 |
| Taux de succès | 94% |
| Dernière sync | Il y a 2h|
Scénario: Statistiques admin - Volume synchronisations
Étant donné qu'un admin consulte les métriques de synchronisation
Quand il accède au dashboard
Alors il voit:
| métrique | valeur |
| Synchronisations/jour | 45,678 |
| Actions synchronisées/jour | 234,567 |
| Taux succès sync | 96.5% |
| Temps moyen traitement batch | 0.8s |
| Actions en attente (global) | 12,345 |
Scénario: Alerte admin si taux échec sync >10%
Étant donné que le taux d'échec sync dépasse 10%
Quand le système détecte cette anomalie
Alors une alerte est envoyée:
"""
Taux échec synchronisation anormal: 12.3%
Échecs aujourd'hui: 5,621 / 45,678 syncs
Causes principales:
- Timeout serveur: 3,245
- Erreur réseau client: 1,876
- Données invalides: 500
Action recommandée: Vérifier charge serveur + logs erreurs
"""
# ===== TESTS PERFORMANCE =====
Scénario: Synchronisation rapide <2s
Étant donné que j'ai 20 actions en attente
Quand la synchronisation démarre
Alors le traitement prend <2 secondes
Et je ne remarque aucun ralentissement de l'app
Scénario: Synchronisation de gros batch (100 actions)
Étant donné que je n'ai pas synchronisé pendant 1 semaine
Et que j'ai 100 actions en attente
Quand la synchronisation démarre
Alors le batch de 100 actions est traité en <5 secondes
Et toutes les actions sont synchronisées avec succès
Scénario: Gestion charge serveur - 10 000 syncs simultanées
Étant donné que 10 000 utilisateurs se reconnectent simultanément
Quand chacun envoie un batch de 20 actions
Alors le serveur traite 200 000 actions
Et grâce au traitement asynchrone (queue Redis), le temps de réponse reste <3s
Et aucun timeout n'est constaté
Scénario: Stockage SQLite optimisé
Étant donné que la table pending_actions stocke des centaines d'actions
Quand des requêtes sont exécutées
Alors la table est indexée sur created_at
Et les requêtes SELECT et DELETE sont instantanées (<10ms)
Et l'expérience utilisateur reste fluide
Scénario: Nettoyage automatique table pending_actions
Étant donné que la table pending_actions grossit avec le temps
Quand les actions sont synchronisées et supprimées
Alors la table est automatiquement optimisée (VACUUM sur SQLite)
Et l'espace disque est libéré
Et les performances restent optimales
# ===== EDGE CASES =====
Scénario: Action dupliquée - Idempotence
Étant donné que j'ai liké un contenu offline
Et que la sync échoue et retry
Quand le backend reçoit 2 fois le même like
Alors il applique l'idempotence (1 seul like enregistré)
Et le compteur de likes n'est pas faussé
Scénario: Séquence like/unlike offline
Étant donné que j'ai liké puis unliké un contenu offline
Quand les 2 actions sont synchronisées
Alors le backend applique les 2 actions dans l'ordre
Et le résultat final est "pas de like" (état correct)
Scénario: Abonnement puis désabonnement offline
Étant donné que je me suis abonné puis désabonné d'un créateur offline
Quand les 2 actions sont synchronisées
Alors le backend applique les 2 actions dans l'ordre
Et le résultat final est "pas abonné"
Et les jauges évoluent correctement (+5% puis -5% = 0% net)
Scénario: Créateur supprimé pendant offline
Étant donné que je me suis abonné à un créateur offline
Mais que le créateur a supprimé son compte entre temps
Quand la sync traite l'abonnement
Alors le backend retourne "creator_deleted"
Et l'action est ignorée silencieusement
Et aucune erreur n'est affichée à l'utilisateur

View File

@@ -0,0 +1,409 @@
# language: fr
Fonctionnalité: Téléchargement de contenus offline
En tant qu'utilisateur
Je veux télécharger des contenus pour les écouter sans connexion
Afin de profiter de RoadWave même dans les zones sans réseau
Contexte:
Étant donné que je suis connecté à l'application RoadWave
# ===== SÉLECTION ZONE GÉOGRAPHIQUE =====
Scénario: Option "Autour de moi" - Rayon 50 km
Étant donné que je suis à Paris (position GPS détectée)
Quand je sélectionne "Télécharger > Autour de moi"
Alors l'app recherche tous les contenus géolocalisés dans un rayon de 50 km
Et je vois une liste de contenus de Paris et banlieue proche
Et l'estimation affiche "~150 contenus disponibles"
Scénario: Option "Ma ville" - Limite administrative détectée
Étant donné que je suis à Lyon (position GPS détectée)
Quand je sélectionne "Télécharger > Ma ville"
Alors l'app détecte automatiquement "Lyon" comme ville
Et recherche tous les contenus géolocalisés "Lyon"
Et je vois uniquement les contenus de la ville de Lyon (pas banlieue)
Scénario: Option "Mon département" - Sélection dans liste
Étant donné que je veux télécharger des contenus pour un département
Quand je sélectionne "Télécharger > Mon département"
Alors je vois une liste de tous les départements français:
| département |
| 01 - Ain |
| 02 - Aisne |
| 75 - Paris |
| 69 - Rhône |
| ... |
Et je peux choisir un département
Scénario: Sélection département et téléchargement contenus
Étant donné que je sélectionne "75 - Paris" dans la liste des départements
Quand la sélection est confirmée
Alors l'app recherche tous les contenus géolocalisés "Paris"
Et je vois "~234 contenus disponibles pour Paris"
Scénario: Option "Ma région" - Sélection dans liste
Étant donné que je veux télécharger des contenus pour une région
Quand je sélectionne "Télécharger > Ma région"
Alors je vois une liste de toutes les régions françaises:
| région |
| Auvergne-Rhône-Alpes |
| Bretagne |
| Île-de-France |
| Nouvelle-Aquitaine |
| Occitanie |
| ... |
Et je peux choisir une région
Scénario: Sélection région et téléchargement contenus
Étant donné que je sélectionne "Bretagne" dans la liste des régions
Quand la sélection est confirmée
Alors l'app recherche tous les contenus géolocalisés des départements bretons:
| département |
| Côtes-d'Armor (22) |
| Finistère (29) |
| Ille-et-Vilaine (35) |
| Morbihan (56) |
Et je vois "~487 contenus disponibles pour Bretagne"
Scénario: Recherche manuelle ville
Étant donné que je veux télécharger des contenus pour une ville spécifique
Quand je tape "Marseille" dans la barre de recherche
Alors l'app propose des suggestions:
| suggestion |
| Marseille (13) |
| Marseille-en-Beauvaisis |
Et je peux sélectionner "Marseille (13)"
Scénario: Recherche manuelle avec autocomplétion
Étant donné que je tape "Ly" dans la barre de recherche
Quand l'autocomplétion s'active
Alors je vois des suggestions:
| suggestion |
| Lyon (69) |
| Lys-lez-Lannoy |
Et je peux affiner ma recherche
# ===== LIMITES TÉLÉCHARGEMENT =====
Scénario: Utilisateur gratuit - Limite 50 contenus max
Étant donné que je suis un utilisateur gratuit
Et que j'ai déjà téléchargé 45 contenus
Quand j'accède à la page Téléchargements
Alors je vois "45 / 50 contenus téléchargés"
Et je peux télécharger 5 contenus supplémentaires maximum
Scénario: Utilisateur gratuit - Tentative dépasser limite 50
Étant donné que je suis gratuit et j'ai déjà 50 contenus téléchargés
Quand j'essaie de télécharger un 51ème contenu
Alors le téléchargement est refusé
Et je vois le message:
"""
📥 Limite atteinte (50 contenus)
Vous avez atteint la limite de téléchargements gratuits.
Options:
Supprimez des contenus existants pour en télécharger de nouveaux
Passez Premium pour des téléchargements illimités
[Gérer mes téléchargements] [Découvrir Premium]
"""
Scénario: Utilisateur Premium - Téléchargements illimités
Étant donné que je suis un utilisateur Premium
Et que j'ai déjà téléchargé 245 contenus
Quand j'accède à la page Téléchargements
Alors je vois "245 contenus (3.2 GB)"
Et aucune limite n'est affichée
Et je peux télécharger autant de contenus que je veux
Scénario: Limite Premium = Espace disque disponible
Étant donné que je suis Premium
Et que mon device a 500 MB d'espace disque disponible
Quand j'essaie de télécharger 100 contenus (2 GB)
Alors le téléchargement échoue après ~50 contenus (500 MB)
Et je vois "Espace disque insuffisant. Libérez de l'espace pour continuer."
Scénario: Calcul temps écoute disponible gratuit
Étant donné que je suis gratuit avec 50 contenus téléchargés
Et que la durée moyenne d'un contenu est 5 minutes
Quand je calcule le temps d'écoute disponible
Alors 50 contenus × 5 min = 250 minutes = 4h10 d'écoute
Et cela suffit pour un trajet quotidien ou road trip court
Scénario: Calcul temps écoute disponible Premium illimité
Étant donné que je suis Premium avec 300 contenus téléchargés
Et que la durée moyenne est 5 minutes
Quand je calcule le temps d'écoute disponible
Alors 300 contenus × 5 min = 1500 minutes = 25h d'écoute
Et cela suffit pour un road trip de plusieurs jours
# ===== CONNEXION WIFI / MOBILE =====
Scénario: Téléchargement par défaut en WiFi uniquement
Étant donné que je suis connecté en WiFi
Quand je clique sur "Télécharger 20 contenus"
Alors le téléchargement démarre immédiatement
Et aucune popup de confirmation n'apparaît
Scénario: Tentative téléchargement en données mobiles - Popup confirmation
Étant donné que je suis connecté en 4G (pas de WiFi)
Quand je clique sur "Télécharger 20 contenus"
Alors une popup apparaît:
"""
📡 Vous n'êtes pas connecté en WiFi
Télécharger via données mobiles consommera environ 72 MB.
[Attendre WiFi] [Continuer quand même]
"""
Scénario: Calcul estimation consommation data mobile
Étant donné que je veux télécharger 20 contenus
Et que la durée moyenne est 5 minutes
Et que la qualité Standard est 48 kbps Opus
Quand l'estimation est calculée
Alors consommation = 20 contenus × 5 min × 48 kbps / 8 = 72 MB
Et ce montant est affiché dans la popup
Scénario: Confirmation téléchargement en données mobiles
Étant donné que je vois la popup de confirmation données mobiles
Quand je clique sur "Continuer quand même"
Alors le téléchargement démarre immédiatement via 4G
Et la consommation data est comptabilisée sur mon forfait mobile
Scénario: Refus téléchargement données mobiles - Attendre WiFi
Étant donné que je vois la popup de confirmation données mobiles
Quand je clique sur "Attendre WiFi"
Alors les téléchargements sont mis en file d'attente
Et ils démarreront automatiquement quand le WiFi sera détecté
Scénario: Détection automatique WiFi et reprise téléchargements
Étant donné que j'ai mis 20 contenus en file d'attente (attente WiFi)
Quand l'app détecte une connexion WiFi
Alors les téléchargements démarrent automatiquement
Et je reçois une notification "Téléchargements en cours via WiFi"
# ===== QUALITÉ AUDIO =====
Scénario: Qualité Standard (48 kbps) par défaut
Étant donné que je configure mes téléchargements
Quand j'accède aux paramètres de qualité
Alors la qualité "Standard (48 kbps - ~20 MB/h)" est sélectionnée par défaut
Et elle est disponible pour tous (gratuit + Premium)
Scénario: Qualité Basse (24 kbps) disponible pour tous
Étant donné que j'ai peu d'espace disque disponible
Quand je sélectionne qualité "Basse (24 kbps - ~10 MB/h)"
Alors mes prochains téléchargements seront en 24 kbps
Et l'espace utilisé sera divisé par 2 par rapport à Standard
Et cette option est disponible pour gratuit + Premium
Scénario: Qualité Haute (64 kbps) réservée Premium
Étant donné que je suis un utilisateur gratuit
Quand je consulte les options de qualité
Alors l'option "Haute (64 kbps - ~30 MB/h)" est grisée
Et je vois "👑 Premium uniquement"
Et je ne peux pas la sélectionner
Scénario: Utilisateur Premium peut choisir qualité Haute
Étant donné que je suis un utilisateur Premium
Quand je consulte les options de qualité
Alors l'option "Haute (64 kbps - ~30 MB/h)" est disponible
Et je peux la sélectionner pour mes téléchargements
Et la qualité audio sera excellente (meilleure restitution voix et ambiances)
Scénario: Comparaison taille fichiers selon qualité
Étant donné que je veux télécharger 50 contenus de 5 min chacun
Quand je compare les qualités
Alors les tailles totales sont:
| qualité | bitrate | taille totale |
| Basse | 24 kbps | ~250 MB |
| Standard | 48 kbps | ~500 MB |
| Haute | 64 kbps | ~650 MB |
Scénario: Justification Standard = Bon compromis
Étant donné que le contenu RoadWave est principalement de la voix
Quand la qualité Standard (48 kbps Opus) est utilisée
Alors la qualité est très correcte pour la voix
Et équivalente à la radio FM
Et le compromis qualité/taille est optimal
Scénario: Justification Haute réservée Premium = Incitation upgrade
Étant donné qu'un utilisateur gratuit veut la meilleure qualité
Quand il voit que Haute est réservée Premium
Alors cela l'incite à passer Premium pour 4.99/mois
Et c'est un avantage tangible supplémentaire de Premium
Scénario: Changement qualité après téléchargements existants
Étant donné que j'ai déjà téléchargé 30 contenus en qualité Standard
Quand je change la qualité vers Haute (si Premium)
Alors les 30 contenus existants restent en Standard
Et seuls les nouveaux téléchargements seront en Haute
Et je peux manuellement re-télécharger les 30 contenus pour les avoir en Haute
# ===== PROCESSUS DE TÉLÉCHARGEMENT =====
Scénario: Téléchargement individuel d'un contenu
Étant donné que je consulte la page d'un contenu
Quand je clique sur l'icône de téléchargement 📥
Alors le téléchargement démarre
Et une barre de progression apparaît
Et l'icône devient quand terminé
Scénario: Téléchargement batch de contenus sélectionnés
Étant donné que je consulte une liste de contenus pour "Paris"
Quand je sélectionne 15 contenus manuellement
Et que je clique sur "Télécharger la sélection"
Alors les 15 contenus sont téléchargés en parallèle (max 3 simultanés)
Et une notification affiche "15 contenus téléchargés"
Scénario: Téléchargement automatique recommandations zone
Étant donné que je sélectionne "Autour de moi" (Paris)
Quand je clique sur "Télécharger les 50 meilleurs contenus"
Alors l'algorithme sélectionne automatiquement les 50 contenus les mieux notés/récents
Et les télécharge tous
Et je n'ai pas besoin de choisir manuellement
Scénario: Barre de progression téléchargement global
Étant donné que je télécharge 20 contenus
Quand les téléchargements sont en cours
Alors je vois une barre de progression globale:
"""
📥 Téléchargement en cours...
7 / 20 contenus (35%)
~45 MB restants
Temps estimé: 2 min
"""
Scénario: Téléchargements en tâche de fond
Étant donné que je lance le téléchargement de 30 contenus
Quand je ferme l'app ou passe à une autre activité
Alors les téléchargements continuent en arrière-plan
Et je reçois une notification quand tous sont terminés
Scénario: Pause et reprise téléchargements
Étant donné que je télécharge 20 contenus
Quand je clique sur "Pause"
Alors les téléchargements en cours se terminent
Et les téléchargements en attente sont mis en pause
Et je peux cliquer sur "Reprendre" plus tard
Scénario: Annulation téléchargements
Étant donné que je télécharge 20 contenus
Quand je clique sur "Annuler"
Alors tous les téléchargements sont arrêtés
Et les fichiers partiels sont supprimés
Et l'espace disque est libéré
Scénario: Gestion erreurs téléchargement
Étant donné que je télécharge un contenu
Mais que la connexion Internet coupe au milieu
Quand la connexion revient
Alors le téléchargement reprend automatiquement où il s'était arrêté
Et aucune perte de progression n'a lieu
Scénario: Retry automatique après échec
Étant donné qu'un téléchargement échoue 3 fois consécutives
Quand l'échec est détecté
Alors le contenu est marqué "Échec"
Et je vois une notification "3 contenus n'ont pas pu être téléchargés"
Et je peux retry manuellement en cliquant sur "Réessayer"
# ===== GESTION CONTENUS TÉLÉCHARGÉS =====
Scénario: Liste contenus téléchargés
Étant donné que j'ai téléchargé 45 contenus
Quand j'accède à "Téléchargements"
Alors je vois la liste complète de mes 45 contenus
Et pour chaque contenu: titre, créateur, durée, taille, date téléchargement
Scénario: Tri contenus téléchargés
Étant donné que je consulte ma liste de téléchargements
Quand je clique sur "Trier par"
Alors je peux trier par:
| critère | ordre |
| Date téléchargement | Plus récent / Plus ancien|
| Titre | A-Z / Z-A |
| Créateur | A-Z / Z-A |
| Durée | Plus long / Plus court |
| Taille | Plus gros / Plus petit |
Scénario: Recherche dans contenus téléchargés
Étant donné que j'ai 200 contenus téléchargés
Quand je tape "Tesla" dans la barre de recherche
Alors seuls les contenus contenant "Tesla" s'affichent
Et je peux rapidement trouver un contenu spécifique
Scénario: Suppression individuelle contenu téléchargé
Étant donné que je veux supprimer un contenu téléchargé
Quand je swipe left (iOS) ou long press (Android) sur le contenu
Et que je clique sur "Supprimer"
Alors le fichier est supprimé du device
Et l'espace disque est libéré
Et le compteur est décrémenté (ex: 45/50 44/50)
Scénario: Suppression batch contenus téléchargés
Étant donné que je veux supprimer plusieurs contenus
Quand je sélectionne 10 contenus
Et que je clique sur "Supprimer la sélection"
Alors les 10 fichiers sont supprimés
Et ~100 MB d'espace disque sont libérés
Et une notification confirme "10 contenus supprimés"
Scénario: Suppression tous les contenus téléchargés
Étant donné que j'ai 45 contenus téléchargés
Quand je clique sur "Supprimer tout"
Et que je confirme l'action
Alors tous les 45 contenus sont supprimés
Et l'espace disque total est libéré (~450 MB)
Et le compteur repasse à 0/50
Scénario: Espace disque utilisé visible
Étant donné que j'ai téléchargé 45 contenus
Quand j'accède à la page Téléchargements
Alors je vois l'espace disque utilisé:
"""
📥 Téléchargements
45 / 50 contenus
Espace utilisé: 478 MB
"""
Scénario: Statistiques téléchargements
Étant donné que j'accède à mes statistiques
Quand je consulte la section Téléchargements
Alors je vois:
| métrique | valeur |
| Contenus actuellement téléchargés | 45 |
| Espace disque utilisé | 478 MB |
| Contenus téléchargés depuis début | 287 |
| Total data téléchargée | 3.2 GB |
| Téléchargements via WiFi | 92% |
| Téléchargements via mobile | 8% |
# ===== LECTURE OFFLINE =====
Scénario: Lecture contenu téléchargé sans connexion
Étant donné que je n'ai aucune connexion Internet (mode avion)
Et que j'ai des contenus téléchargés
Quand je lance un contenu téléchargé
Alors la lecture démarre normalement depuis le fichier local
Et aucune erreur de connexion n'apparaît
Scénario: Badge "Téléchargé" sur contenus offline
Étant donné que j'ai téléchargé certains contenus
Quand je consulte une liste de contenus
Alors les contenus téléchargés ont un badge "Offline"
Et je sais immédiatement lesquels sont disponibles sans connexion
Scénario: Filtre "Téléchargés uniquement"
Étant donné que je veux voir uniquement mes contenus offline
Quand j'active le filtre "Téléchargés uniquement"
Alors seuls les contenus téléchargés s'affichent
Et je peux facilement naviguer dans mon catalogue offline
Scénario: Playlist offline automatique
Étant donné que j'ai téléchargé 45 contenus
Quand j'accède à "Téléchargements"
Alors je peux lancer une playlist aléatoire de mes 45 contenus
Et profiter d'une écoute continue offline

View File

@@ -0,0 +1,335 @@
# language: fr
Fonctionnalité: Validité et renouvellement contenus offline
En tant qu'utilisateur
Je veux que mes contenus téléchargés restent valides un certain temps
Afin de garantir la légalité et la fraîcheur du contenu
Contexte:
Étant donné que je suis connecté à l'application RoadWave
Et que j'ai des contenus téléchargés
# ===== DURÉE DE VALIDITÉ =====
Scénario: Validité de 30 jours après téléchargement
Étant donné que je télécharge un contenu le 1er juin 2025
Quand le téléchargement est terminé
Alors le contenu est valide jusqu'au 1er juillet 2025 (30 jours)
Et la date d'expiration est stockée en local
Scénario: Affichage date expiration sur contenu téléchargé
Étant donné que j'ai téléchargé un contenu il y a 20 jours
Quand je consulte les détails du contenu
Alors je vois "Expire dans 10 jours"
Et je sais combien de temps il reste avant expiration
Scénario: Standard industrie aligné (Spotify, YouTube, Deezer)
Étant donné que Spotify, YouTube Music et Deezer utilisent 30 jours
Quand RoadWave fixe également 30 jours
Alors c'est le standard accepté par les utilisateurs
Et il n'y a pas de confusion avec les autres plateformes
Scénario: Justification 30 jours - Force reconnexion régulière
Étant donné qu'un utilisateur ne se connecte jamais
Quand ses contenus expirent après 30 jours
Alors il est obligé de se reconnecter pour les renouveler
Et le système peut vérifier:
| vérification |
| Abonnement Premium toujours actif|
| Contenus non modérés/supprimés |
| Métadonnées à jour |
Scénario: Justification 30 jours - Évite stockage obsolète
Étant donné qu'un contenu a été modéré après téléchargement
Quand le contenu expire après 30 jours maximum
Alors le contenu illégal est automatiquement supprimé
Et ne reste pas indéfiniment sur le device
# ===== RENOUVELLEMENT AUTOMATIQUE =====
Scénario: Détection WiFi et contenus >25 jours
Étant donné que j'ai des contenus téléchargés il y a 26 jours
Quand l'app détecte une connexion WiFi
Alors une requête GET /offline/contents/refresh est envoyée
Et le backend vérifie chaque contenu
Scénario: Vérification abonnement Premium toujours actif
Étant donné qu'un contenu téléchargé en Premium est à renouveler
Quand le backend vérifie le statut
Et que l'abonnement Premium est toujours actif
Alors la validité est renouvelée à 30 jours supplémentaires
Scénario: Abonnement Premium expiré - Contenu non renouvelé
Étant donné qu'un contenu Premium téléchargé est à renouveler
Quand le backend vérifie le statut
Et que l'abonnement Premium a expiré
Alors le contenu n'est pas renouvelé
Et il sera supprimé à l'expiration (J-0)
Et l'utilisateur voit "Contenu Premium expiré (abonnement inactif)"
Scénario: Vérification contenu pas modéré/supprimé
Étant donné qu'un contenu téléchargé est à renouveler
Quand le backend vérifie le statut
Et que le contenu a été modéré ou supprimé entre temps
Alors le contenu n'est pas renouvelé
Et sera supprimé immédiatement du device
Et l'utilisateur voit "1 contenu retiré (violation règles)"
Scénario: Mise à jour métadonnées lors du renouvellement
Étant donné qu'un contenu téléchargé est renouvelé
Quand le backend traite le renouvellement
Alors les métadonnées sont mises à jour:
| métadonnée | mise à jour si changée |
| Titre | |
| Nom créateur | |
| Description | |
| Tags | |
| Statut Premium | |
Et l'utilisateur voit les infos à jour
Scénario: Pas de re-téléchargement audio si fichier OK
Étant donné qu'un contenu est renouvelé
Quand le fichier audio local est intact
Alors seules les métadonnées sont mises à jour
Et le fichier audio n'est pas re-téléchargé
Et cela économise la bande passante
Scénario: Re-téléchargement audio si fichier corrompu
Étant donné qu'un contenu est renouvelé
Quand le fichier audio local est corrompu (checksum invalide)
Alors le fichier audio est re-téléchargé entièrement
Et le nouveau fichier remplace le corrompu
Scénario: Renouvellement silencieux si WiFi régulier
Étant donné que je me connecte en WiFi tous les jours
Quand mes contenus atteignent 25-30 jours
Alors ils sont automatiquement renouvelés en arrière-plan
Et je ne vois aucune notification (processus transparent)
Et mes contenus restent valides indéfiniment
Scénario: Renouvellement batch de plusieurs contenus
Étant donné que j'ai 30 contenus à renouveler
Quand le renouvellement automatique se déclenche
Alors une requête batch est envoyée:
```json
POST /offline/contents/refresh
{
"content_ids": ["abc123", "def456", "ghi789", ...]
}
```
Et le backend traite les 30 contenus en une seule requête
Et cela économise les requêtes HTTP
Scénario: Temps de traitement renouvellement
Étant donné que 30 contenus sont à renouveler
Quand la requête batch est traitée
Alors le backend répond en <2 secondes
Et les métadonnées sont mises à jour localement
Et l'utilisateur ne remarque aucun ralentissement
# ===== NOTIFICATIONS EXPIRATION =====
Scénario: Notification J-3 avant expiration
Étant donné que j'ai 15 contenus qui expirent dans 3 jours
Quand le système vérifie les expirations
Alors je reçois une notification:
"""
⚠️ 15 contenus expirent dans 3 jours
Connectez-vous en WiFi pour les renouveler automatiquement.
"""
Et je peux agir avant l'expiration
Scénario: Pas de notification si connexion WiFi régulière
Étant donné que je me connecte en WiFi tous les jours
Et que mes contenus sont automatiquement renouvelés
Quand le système vérifie les expirations
Alors aucune notification J-3 n'est envoyée
Car les contenus sont déjà renouvelés silencieusement
Scénario: Notification uniquement si contenus non renouvelés
Étant donné que j'ai 20 contenus dont 15 renouvelés et 5 non renouvelés
Quand le J-3 arrive pour les 5 non renouvelés
Alors je reçois "5 contenus expirent dans 3 jours"
Et seuls les contenus à risque sont mentionnés
Scénario: Action utilisateur après notification J-3
Étant donné que je reçois la notification J-3
Quand je clique sur la notification
Alors l'app s'ouvre sur la page Téléchargements
Et je vois les contenus qui vont expirer en rouge
Et je peux me connecter en WiFi pour les renouveler
Scénario: Suppression automatique J-0 (expiration)
Étant donné qu'un contenu n'a pas été renouvelé
Quand le jour d'expiration arrive (J-0)
Alors le fichier est automatiquement supprimé du device
Et l'espace disque est libéré
Et le compteur est décrémenté (ex: 45/50 → 44/50)
Scénario: Toast après suppression automatique J-0
Étant donné que 15 contenus viennent d'expirer
Quand l'utilisateur ouvre l'app
Alors il voit un toast:
"""
🗑️ 15 contenus expirés ont été supprimés
Reconnectez-vous en WiFi régulièrement pour éviter les expirations.
"""
Scénario: Liste contenus supprimés après expiration
Étant donné que 15 contenus ont expiré
Quand je consulte l'historique des suppressions
Alors je vois la liste des 15 contenus supprimés:
| titre | créateur | date expiration |
| Mon épisode préféré | JeanDupont | 15 juin 2025 |
| Road trip Bretagne | MarieLambert| 15 juin 2025 |
| ... | ... | ... |
Et je peux les re-télécharger si je veux
Scénario: Re-téléchargement après expiration
Étant donné qu'un contenu a expiré et été supprimé
Quand je retrouve ce contenu dans l'app
Alors le badge ✅ "Offline" n'est plus affiché
Et je peux le re-télécharger normalement
Et la validité repart à 30 jours
# ===== CAS PARTICULIERS =====
Scénario: Utilisateur ne se connecte jamais pendant 30 jours
Étant donné que je télécharge 50 contenus le 1er juin
Mais que je ne me connecte jamais en WiFi pendant 30 jours
Quand le 1er juillet arrive
Alors tous les 50 contenus expirent
Et sont automatiquement supprimés
Et je n'ai plus aucun contenu offline
Scénario: Utilisateur en zone blanche 30+ jours
Étant donné que je télécharge 50 contenus avant de partir en zone sans réseau
Et que je reste 45 jours sans connexion
Quand les contenus expirent après 30 jours
Alors ils sont supprimés même si je ne peux pas me connecter
Et je perds l'accès à mes contenus offline
Scénario: Recommandation téléchargement avant zone blanche longue
Étant donné que je prépare un road trip de 60 jours
Quand je consulte la FAQ
Alors je vois la recommandation:
"""
⚠️ Road trips >30 jours
Les contenus téléchargés expirent après 30 jours.
Pour les longs voyages sans connexion:
Téléchargez de nouveaux contenus tous les 25 jours si possible
Ou planifiez une reconnexion WiFi tous les 25 jours
"""
Scénario: Changement statut Premium en gratuit pendant validité
Étant donné que je suis Premium et j'ai téléchargé 200 contenus
Quand mon abonnement Premium expire
Et que je repasse en gratuit
Alors au prochain renouvellement, seulement 50 contenus sont conservés
Et les 150 autres sont supprimés (limite gratuit)
Et je vois "Limite gratuit (50 contenus) appliquée. 150 contenus supprimés."
Scénario: Sélection automatique 50 meilleurs contenus si passage gratuit
Étant donné que je repasse en gratuit avec 200 contenus téléchargés
Quand le système applique la limite de 50
Alors les 50 contenus les plus récemment écoutés sont conservés
Et les 150 autres sont supprimés
Et cela maximise les chances de garder les contenus que j'aime
Scénario: Contenus Premium exclusifs supprimés si abonnement expire
Étant donné que j'ai téléchargé 20 contenus Premium exclusifs
Quand mon abonnement Premium expire
Alors les 20 contenus Premium sont immédiatement supprimés
Car ils ne sont accessibles qu'aux abonnés Premium actifs
Et je vois "20 contenus Premium supprimés (abonnement expiré)"
# ===== STATISTIQUES ET MONITORING =====
Scénario: Affichage temps restant avant expiration
Étant donné que j'ai 45 contenus téléchargés
Quand je consulte la page Téléchargements
Alors je vois pour chaque contenu:
| contenu | temps restant |
| Mon épisode (récent)| Expire dans 28 jours |
| Road trip (ancien) | Expire dans 3 jours |
Et je sais lesquels sont prioritaires pour renouvellement
Scénario: Tri par date expiration
Étant donné que j'ai 45 contenus avec différentes dates d'expiration
Quand je trie par "Expiration"
Alors les contenus qui expirent le plus tôt apparaissent en premier
Et je peux voir rapidement lesquels nécessitent une reconnexion urgente
Scénario: Badge rouge si expiration <3 jours
Étant donné qu'un contenu expire dans 2 jours
Quand je consulte la liste des téléchargements
Alors le contenu a un badge rouge "⚠️ Expire bientôt"
Et il est visuellement mis en avant
Scénario: Statistiques utilisateur - Taux de renouvellement
Étant donné que j'accède à mes statistiques
Quand je consulte la section Téléchargements
Alors je vois:
| métrique | valeur |
| Contenus actuels | 45 |
| Contenus expirés depuis début | 87 |
| Contenus renouvelés (auto) | 234 |
| Taux renouvellement automatique | 73% |
Scénario: Statistiques admin - Taux expiration global
Étant donné qu'un admin consulte les métriques offline
Quand il accède au dashboard
Alors il voit:
| métrique | valeur |
| Contenus téléchargés actifs | 1,234,567 |
| Expirations ce mois | 45,678 |
| Taux expiration | 3.7% |
| Renouvellements automatiques/mois | 234,567 |
Scénario: Alerte admin si taux expiration >10%
Étant donné que le taux d'expiration mensuel dépasse 10%
Quand le système détecte cette anomalie
Alors une alerte est envoyée:
"""
Taux d'expiration anormal: 12.3%
Nombre expirations ce mois: 152,345
Causes possibles:
- Utilisateurs ne se connectent plus en WiFi
- Problème renouvellement automatique ?
- Churn utilisateurs augmenté ?
Action recommandée: Enquête technique + email rappel utilisateurs
"""
Scénario: Email rappel si pas de connexion WiFi depuis 20 jours
Étant donné que je n'ai pas connecté l'app en WiFi depuis 20 jours
Et que j'ai 45 contenus téléchargés
Quand le système détecte cette inactivité WiFi
Alors je reçois un email:
"""
📡 Connectez-vous en WiFi pour conserver vos téléchargements
Vous n'avez pas connecté RoadWave en WiFi depuis 20 jours.
Vos 45 contenus téléchargés expireront dans 10 jours si non renouvelés.
Connectez-vous en WiFi avant le 30 juin pour les renouveler automatiquement.
"""
Scénario: Performance renouvellement avec 10 000 utilisateurs simultanés
Étant donné que 10 000 utilisateurs se connectent en WiFi simultanément
Quand chacun demande le renouvellement de 50 contenus
Alors le serveur traite 500 000 vérifications
Et grâce au cache Redis et index PostgreSQL, le temps de réponse reste <3s
Et les serveurs gèrent la charge sans problème
Scénario: Logs audit renouvellements
Étant donné qu'un contenu est renouvelé
Quand l'opération se termine
Alors un log est enregistré:
| timestamp | user_id | content_id | action | résultat |
| 2025-06-15 14:30:00 | abc123 | xyz789 | renew | success (+30d) |
| 2025-06-15 14:30:01 | abc123 | def456 | renew | failed (deleted)|
Et ces logs aident à débugger les problèmes