docs(qa-261): ajoute documents conformité et scripts QA pour release Android
- Ajoute privacy-policy-v1.md et release-compliance-checklist.md - Ajoute documents QA gates #238-#243 - Ajoute scripts de validation repo-only et device runbooks - Prépare checklists exécutables avant upload Play fermé Ticket #261
This commit is contained in:
91
docs/legal/privacy-policy-v1.md
Normal file
91
docs/legal/privacy-policy-v1.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# GameTime Privacy Policy
|
||||||
|
|
||||||
|
Version: 1.0
|
||||||
|
Effective date: 2026-08-22
|
||||||
|
Status: repo reference draft for release preparation
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This policy covers the GameTime mobile app, including the Android phone app,
|
||||||
|
the optional Wear OS companion, account features, sharing, synchronization,
|
||||||
|
purchase entitlement checks, and optional Health Connect integration.
|
||||||
|
|
||||||
|
## Data We Handle
|
||||||
|
|
||||||
|
GameTime is designed as an offline-first workout tracker. Depending on the
|
||||||
|
features used, the app may handle:
|
||||||
|
|
||||||
|
- workout library content created by the user, including exercises, programs,
|
||||||
|
workout templates, timers, scores, repetitions, session history, and local
|
||||||
|
media selected for exercises
|
||||||
|
- account identifiers such as email address and authentication tokens when the
|
||||||
|
user creates an account or signs in
|
||||||
|
- shared workout resources and recipient email addresses when the sharing
|
||||||
|
feature is used
|
||||||
|
- purchase entitlement status needed to determine whether the account is on the
|
||||||
|
Free or Pro plan
|
||||||
|
- optional workout telemetry such as heart rate, distance, calories, and
|
||||||
|
exercise records when the user explicitly enables Health Connect integration
|
||||||
|
- optional live workout state and commands exchanged with the Wear OS companion
|
||||||
|
|
||||||
|
## Free and Pro Features
|
||||||
|
|
||||||
|
Sharing remains free. The Free plan limits the editable workout library, not
|
||||||
|
basic workout execution. Imported or shared resources count toward the
|
||||||
|
receiving account's quota when accepted. Pro provides unlimited library capacity
|
||||||
|
and synchronization.
|
||||||
|
|
||||||
|
The Wear OS companion and Health Connect integration are free features and are
|
||||||
|
not paywalled.
|
||||||
|
|
||||||
|
## Local Storage and Offline Use
|
||||||
|
|
||||||
|
Workout data is stored locally on the device first. The app is intended to keep
|
||||||
|
working without network access, including before any server synchronization has
|
||||||
|
been configured.
|
||||||
|
|
||||||
|
## Synchronization and Sharing
|
||||||
|
|
||||||
|
When synchronization is enabled, workout library and account data may be sent to
|
||||||
|
the GameTime server so the account can restore or synchronize data. When sharing
|
||||||
|
is used, the selected resources and recipient identifiers are sent to the server
|
||||||
|
so recipients can receive, accept, decline, or revoke shares.
|
||||||
|
|
||||||
|
## Health Connect
|
||||||
|
|
||||||
|
Health Connect access is optional. GameTime requests only the health permissions
|
||||||
|
needed for the enabled workout features. Health data is used to support workout
|
||||||
|
tracking and export flows shown in the app. The user can revoke Health Connect
|
||||||
|
permissions from Android settings.
|
||||||
|
|
||||||
|
## Wear OS Companion
|
||||||
|
|
||||||
|
The Wear OS companion exchanges live session state, commands, and available
|
||||||
|
metrics with the phone app. The companion is optional and depends on the Android
|
||||||
|
Wear Data Layer between paired devices.
|
||||||
|
|
||||||
|
## Purchases and Entitlements
|
||||||
|
|
||||||
|
Purchase and entitlement data is used to unlock Pro functionality such as
|
||||||
|
unlimited library capacity and synchronization. GameTime does not use purchase
|
||||||
|
state to restrict sharing, the Wear OS companion, Health Connect, or basic
|
||||||
|
workout execution.
|
||||||
|
|
||||||
|
## Data Retention and Deletion
|
||||||
|
|
||||||
|
Local workout data remains on the device until the user deletes it or removes
|
||||||
|
the app. Server-side account, synchronization, sharing, and entitlement data
|
||||||
|
requires an operational account management process before public release.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Release Android builds must use HTTPS for remote GameTime server traffic.
|
||||||
|
Cleartext HTTP is permitted only for local debug/profile development builds.
|
||||||
|
Authentication tokens are treated as sensitive credentials and should be stored
|
||||||
|
through the platform secure storage adapter.
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
Before public distribution, replace this section with the legal support contact
|
||||||
|
and the public URL that will be submitted to the Play Console.
|
||||||
|
|
||||||
629
docs/qa-functional-test-plan-238.md
Normal file
629
docs/qa-functional-test-plan-238.md
Normal file
@ -0,0 +1,629 @@
|
|||||||
|
# Ticket #238 — Cadrage QA runnable des features principales
|
||||||
|
|
||||||
|
## Objectif
|
||||||
|
|
||||||
|
Ce document sert de base opérationnelle au nouveau process TDD GameTime.
|
||||||
|
Il fixe :
|
||||||
|
|
||||||
|
- l'ordre recommandé de couverture des features majeures
|
||||||
|
- les suites attendues par niveau de test
|
||||||
|
- la stratégie d'implémentation runnable
|
||||||
|
- les commandes cibles à exécuter
|
||||||
|
- le backlog initial d'automatisation prioritaire
|
||||||
|
|
||||||
|
Le principe directeur est simple : verrouiller d'abord les parcours qui portent la valeur produit et les régressions les plus coûteuses, avant d'étendre la couverture device et infra.
|
||||||
|
|
||||||
|
## Preuves réelles ajoutées le 22 août 2026
|
||||||
|
|
||||||
|
Preuves exécutées sur `/tmp/gametime-src-1787384228` :
|
||||||
|
|
||||||
|
- gate `#239` verte
|
||||||
|
- gate `#240` verte
|
||||||
|
- smoke `#241` vert
|
||||||
|
- gate `#242` verte
|
||||||
|
- `dart test` serveur vert
|
||||||
|
|
||||||
|
Conséquence :
|
||||||
|
|
||||||
|
- le socle QA Flutter transverse est désormais prouvé exécutable
|
||||||
|
- le coeur offline Drift est prouvé exécutable
|
||||||
|
- la gate monétisation actuellement cadrée est prouvée exécutable
|
||||||
|
- la validation device reste distincte et passe par `#243`
|
||||||
|
|
||||||
|
## Constat repo au 21 août 2026
|
||||||
|
|
||||||
|
Le dépôt contient déjà une base exploitable :
|
||||||
|
|
||||||
|
- tests Flutter domaine/application/infrastructure dans `test/application`, `test/infrastructure`, `test/domain_import_boundaries_test.dart`
|
||||||
|
- nombreux tests widget écran par écran dans `test/presentation`
|
||||||
|
- premier harnais fonctionnel mémoire dans `test/support/functional_harness.dart`
|
||||||
|
- première suite fonctionnelle transverse dans `test/functional/functional_coverage_test.dart`
|
||||||
|
- suite montre dédiée dans `watch_app/test/presentation`
|
||||||
|
- suite serveur Dart dans `server/test`
|
||||||
|
- checklist d'intégration réelle infra dans `server/docs/integration-checklist.md`
|
||||||
|
|
||||||
|
Ce qui manque pour relancer le delivery vers la prod n'est pas une base de tests, mais une hiérarchie claire :
|
||||||
|
|
||||||
|
- quels parcours servent de gate de non-régression
|
||||||
|
- quels niveaux de tests portent chaque feature
|
||||||
|
- quelles suites doivent tourner en local, en CI rapide, en CI complète et en validation manuelle scriptée
|
||||||
|
|
||||||
|
## Convention d'exécution runnable
|
||||||
|
|
||||||
|
Dans l'environnement actuel, les commandes Flutter et Dart passent en forçant un `HOME` writable et en coupant l'analytics.
|
||||||
|
|
||||||
|
Convention à utiliser pour les runners locaux et CI :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export FLUTTER_SUPPRESS_ANALYTICS=true
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
```
|
||||||
|
|
||||||
|
Preuve minimale vérifiée dans ce ticket :
|
||||||
|
|
||||||
|
- `flutter test test/functional/functional_coverage_test.dart --plain-name 'builders create readable exercise, program and template scenarios'`
|
||||||
|
- `dart test test/health_test.dart` depuis `server/`
|
||||||
|
|
||||||
|
Ces deux commandes passent avec la convention ci-dessus.
|
||||||
|
|
||||||
|
## Ordre de couverture recommandé
|
||||||
|
|
||||||
|
### Lot 1 — Gate prod minimale téléphone offline-first
|
||||||
|
|
||||||
|
But : garantir que l'app principale remplit sa promesse cœur sans compte ni sync.
|
||||||
|
|
||||||
|
Features incluses :
|
||||||
|
|
||||||
|
- bibliothèque d'exercices
|
||||||
|
- composition de programmes
|
||||||
|
- composition de séances
|
||||||
|
- exécution d'une séance
|
||||||
|
- enregistrement d'historique
|
||||||
|
- reprise d'une séance en cours
|
||||||
|
- progression issue de l'historique
|
||||||
|
|
||||||
|
Pourquoi en premier :
|
||||||
|
|
||||||
|
- c'est le cœur de la valeur GameTime
|
||||||
|
- la plupart des invariants sont déjà testables en mémoire
|
||||||
|
- ce lot permet de relancer le développement produit sans attendre l'infra distante
|
||||||
|
|
||||||
|
### Lot 2 — Variantes métier à fort risque de régression
|
||||||
|
|
||||||
|
Features incluses :
|
||||||
|
|
||||||
|
- score manuel
|
||||||
|
- score chrono
|
||||||
|
- timers de série et de repos
|
||||||
|
- séquences d'étapes
|
||||||
|
- correction d'une série passée
|
||||||
|
- import/export local
|
||||||
|
|
||||||
|
Pourquoi ensuite :
|
||||||
|
|
||||||
|
- ces variantes cassent facilement les écrans et les use cases
|
||||||
|
- elles demandent des suites de comportement plus transverses que du simple widget isolé
|
||||||
|
|
||||||
|
### Lot 3 — Compte, sync et partage
|
||||||
|
|
||||||
|
Features incluses :
|
||||||
|
|
||||||
|
- profil connecté/déconnecté
|
||||||
|
- auth
|
||||||
|
- sync
|
||||||
|
- boîte de réception des partages
|
||||||
|
- partage de programme et de séance
|
||||||
|
- import de partage accepté
|
||||||
|
|
||||||
|
Pourquoi après le lot 1 :
|
||||||
|
|
||||||
|
- forte dépendance à l'API et à des fixtures serveur
|
||||||
|
- besoin de distinguer clairement tests clients mockés, tests serveur réels et smoke end-to-end
|
||||||
|
|
||||||
|
### Lot 4 — Intégrations gratuites device
|
||||||
|
|
||||||
|
Features incluses :
|
||||||
|
|
||||||
|
- Health Connect
|
||||||
|
- compagnon montre Android/Wear
|
||||||
|
- projection de séance vers la montre
|
||||||
|
- télémétrie live montre
|
||||||
|
|
||||||
|
Pourquoi en quatrième :
|
||||||
|
|
||||||
|
- important produit, mais plus coûteux à rendre deterministic
|
||||||
|
- nécessite émulateurs / devices / bridge natif
|
||||||
|
|
||||||
|
### Lot 5 — Validation déploiement et packaging
|
||||||
|
|
||||||
|
Features incluses :
|
||||||
|
|
||||||
|
- build Android
|
||||||
|
- build watch
|
||||||
|
- bootstrap serveur Docker/PostgreSQL
|
||||||
|
- smoke API réelle
|
||||||
|
|
||||||
|
Pourquoi en dernier :
|
||||||
|
|
||||||
|
- ce lot doit s'appuyer sur des fondations fonctionnelles déjà stables
|
||||||
|
|
||||||
|
## Matrice feature -> suites attendues
|
||||||
|
|
||||||
|
### 1. Exercices
|
||||||
|
|
||||||
|
Parcours nominaux :
|
||||||
|
|
||||||
|
- créer un exercice simple
|
||||||
|
- créer un exercice avec reps, temps et score
|
||||||
|
- ajouter tags et médias
|
||||||
|
- définir une icône média
|
||||||
|
- configurer des étapes
|
||||||
|
- modifier puis supprimer un exercice
|
||||||
|
|
||||||
|
Cas limites :
|
||||||
|
|
||||||
|
- aucune mesure active
|
||||||
|
- neuvième étape refusée
|
||||||
|
- sixième image refusée
|
||||||
|
- étape invalide
|
||||||
|
- exercice seedé modifié
|
||||||
|
|
||||||
|
Suites attendues :
|
||||||
|
|
||||||
|
- unitaires : validations métier et normalisation
|
||||||
|
- intégration : persistance Drift des exercices, tags, médias, étapes
|
||||||
|
- widget : formulaire réel et liste filtrable
|
||||||
|
- end-to-end/manuel scripté : ajout complet avec média réel sur device
|
||||||
|
|
||||||
|
Base existante :
|
||||||
|
|
||||||
|
- `test/presentation/exercise_library_screen_test.dart`
|
||||||
|
- `test/infrastructure/drift_repositories_test.dart`
|
||||||
|
|
||||||
|
### 2. Programmes
|
||||||
|
|
||||||
|
Parcours nominaux :
|
||||||
|
|
||||||
|
- créer un programme depuis des exercices existants
|
||||||
|
- configurer séries, cibles, repos
|
||||||
|
- dupliquer
|
||||||
|
- filtrer
|
||||||
|
- partager
|
||||||
|
|
||||||
|
Cas limites :
|
||||||
|
|
||||||
|
- programme sans exercice
|
||||||
|
- exercice snapshot incomplet
|
||||||
|
- partage sans compte
|
||||||
|
|
||||||
|
Suites attendues :
|
||||||
|
|
||||||
|
- unitaires : construction snapshot et validations de configuration
|
||||||
|
- intégration : lecture/écriture repository
|
||||||
|
- widget : formulaire, liste, duplication, partage
|
||||||
|
- end-to-end/manuel scripté : création puis partage depuis un compte réel
|
||||||
|
|
||||||
|
Base existante :
|
||||||
|
|
||||||
|
- `test/presentation/program_screen_test.dart`
|
||||||
|
|
||||||
|
### 3. Séances / templates
|
||||||
|
|
||||||
|
Parcours nominaux :
|
||||||
|
|
||||||
|
- créer une séance avec un ou plusieurs programmes
|
||||||
|
- configurer overrides
|
||||||
|
- dupliquer
|
||||||
|
- lancer depuis la liste
|
||||||
|
|
||||||
|
Cas limites :
|
||||||
|
|
||||||
|
- séance sans programme
|
||||||
|
- aucune exécution possible
|
||||||
|
- legacy invalide non bloquante
|
||||||
|
|
||||||
|
Suites attendues :
|
||||||
|
|
||||||
|
- unitaires : résolution des snapshots et overrides
|
||||||
|
- intégration : persistance template + programme snapshot
|
||||||
|
- widget : création/édition/lancement
|
||||||
|
- end-to-end/manuel scripté : création complète puis lancement
|
||||||
|
|
||||||
|
Base existante :
|
||||||
|
|
||||||
|
- `test/presentation/workout_template_screen_test.dart`
|
||||||
|
- `test/functional/functional_coverage_test.dart`
|
||||||
|
|
||||||
|
### 4. Exécution de séance
|
||||||
|
|
||||||
|
Parcours nominaux :
|
||||||
|
|
||||||
|
- démarrer depuis une séance
|
||||||
|
- exécuter score manuel
|
||||||
|
- exécuter chrono score
|
||||||
|
- gérer repos
|
||||||
|
- pause/reprise
|
||||||
|
- terminer une série
|
||||||
|
- quitter et reprendre
|
||||||
|
- compléter la séance
|
||||||
|
- enregistrer l'historique
|
||||||
|
- relancer depuis l'historique
|
||||||
|
|
||||||
|
Cas limites :
|
||||||
|
|
||||||
|
- séance invalide
|
||||||
|
- repos resynchronisé
|
||||||
|
- chrono jamais démarré
|
||||||
|
- dernière série sans repos
|
||||||
|
- série passée corrigée
|
||||||
|
- skip de série
|
||||||
|
- skip de séquence
|
||||||
|
|
||||||
|
Suites attendues :
|
||||||
|
|
||||||
|
- unitaires : transitions d'état de session, repos, chrono, score, steps
|
||||||
|
- intégration : persistance session active -> historique
|
||||||
|
- widget : écran d'exécution, plan, édition de série passée, reprise
|
||||||
|
- end-to-end/manuel scripté : parcours complet réel sur téléphone
|
||||||
|
|
||||||
|
Base existante :
|
||||||
|
|
||||||
|
- `test/application/use_cases_test.dart`
|
||||||
|
- `test/application/session_notification_use_cases_test.dart`
|
||||||
|
- `test/presentation/workout_execution_screen_test.dart`
|
||||||
|
- `test/functional/functional_coverage_test.dart`
|
||||||
|
|
||||||
|
### 5. Historique et progression
|
||||||
|
|
||||||
|
Parcours nominaux :
|
||||||
|
|
||||||
|
- consulter les séances passées
|
||||||
|
- ouvrir le détail
|
||||||
|
- supprimer
|
||||||
|
- relancer
|
||||||
|
- visualiser la progression globale
|
||||||
|
- visualiser la progression par exercice
|
||||||
|
|
||||||
|
Cas limites :
|
||||||
|
|
||||||
|
- historique vide
|
||||||
|
- historique legacy invalide
|
||||||
|
- score chrono affiché comme temps
|
||||||
|
- ouverture de détail depuis point de graphe
|
||||||
|
|
||||||
|
Suites attendues :
|
||||||
|
|
||||||
|
- unitaires : agrégations progression et mapping métriques
|
||||||
|
- intégration : repository historique
|
||||||
|
- widget : écrans Historique et Progression
|
||||||
|
- end-to-end/manuel scripté : séance jouée puis visible dans progression
|
||||||
|
|
||||||
|
Base existante :
|
||||||
|
|
||||||
|
- `test/presentation/history_screen_test.dart`
|
||||||
|
- `test/presentation/progression_screen_test.dart`
|
||||||
|
|
||||||
|
### 6. Compte, auth, sync et partage
|
||||||
|
|
||||||
|
Parcours nominaux :
|
||||||
|
|
||||||
|
- créer un compte
|
||||||
|
- se connecter
|
||||||
|
- se déconnecter
|
||||||
|
- synchroniser
|
||||||
|
- partager un programme
|
||||||
|
- partager une séance
|
||||||
|
- recevoir un partage
|
||||||
|
- accepter et importer
|
||||||
|
- décliner
|
||||||
|
|
||||||
|
Cas limites :
|
||||||
|
|
||||||
|
- erreur login inline
|
||||||
|
- erreur serveur dédiée
|
||||||
|
- token invalide
|
||||||
|
- conflit LWW sync
|
||||||
|
- partage déjà répondu
|
||||||
|
- email inconnu
|
||||||
|
- quota receveur plein
|
||||||
|
|
||||||
|
Suites attendues :
|
||||||
|
|
||||||
|
- unitaires : use cases auth/sync/share, règles quota/import
|
||||||
|
- intégration : client HTTP, API serveur, repositories serveur
|
||||||
|
- widget : Profil, Inbox, formulaires de partage
|
||||||
|
- end-to-end/manuel scripté : 2 comptes réels, partage puis sync
|
||||||
|
|
||||||
|
Base existante :
|
||||||
|
|
||||||
|
- client Flutter : `test/presentation/profile_screen_test.dart`, `test/presentation/share_inbox_screen_test.dart`, `test/infrastructure/remote/*.dart`
|
||||||
|
- serveur Dart : `server/test/auth_*`, `server/test/sync_*`, `server/test/share_*`
|
||||||
|
|
||||||
|
Note monétisation :
|
||||||
|
|
||||||
|
- le partage reste gratuit
|
||||||
|
- le quota free limite la bibliothèque éditable, pas l'exécution
|
||||||
|
- les objets importés/partagés comptent côté receveur à l'acceptation
|
||||||
|
- le backlog QA devra explicitement ajouter les cas quota multi-comptes et restauration
|
||||||
|
|
||||||
|
### 7. Import / export local
|
||||||
|
|
||||||
|
Parcours nominaux :
|
||||||
|
|
||||||
|
- exporter ses données
|
||||||
|
- importer en fusion
|
||||||
|
- importer en remplacement total
|
||||||
|
|
||||||
|
Cas limites :
|
||||||
|
|
||||||
|
- fichier invalide
|
||||||
|
- annulation silencieuse
|
||||||
|
- séance active qui bloque l'import
|
||||||
|
- double confirmation destructive
|
||||||
|
|
||||||
|
Suites attendues :
|
||||||
|
|
||||||
|
- unitaires : parsing et règles de fusion/remplacement
|
||||||
|
- intégration : repositories et frontières d'import
|
||||||
|
- widget : flux import/export depuis Profil
|
||||||
|
- end-to-end/manuel scripté : vrai fichier sur device
|
||||||
|
|
||||||
|
Base existante :
|
||||||
|
|
||||||
|
- `test/presentation/profile_screen_test.dart`
|
||||||
|
- `test/domain_import_boundaries_test.dart`
|
||||||
|
|
||||||
|
### 8. Health Connect
|
||||||
|
|
||||||
|
Parcours nominaux :
|
||||||
|
|
||||||
|
- afficher l'état d'intégration
|
||||||
|
- demander les permissions
|
||||||
|
- rafraîchir le statut
|
||||||
|
|
||||||
|
Cas limites :
|
||||||
|
|
||||||
|
- permissions partielles
|
||||||
|
- refus explicite
|
||||||
|
- fallback vers réglages
|
||||||
|
- accès bloqué sans action
|
||||||
|
- échec d'appel natif
|
||||||
|
|
||||||
|
Suites attendues :
|
||||||
|
|
||||||
|
- unitaires : mapping des statuts natifs
|
||||||
|
- intégration : gateway Health Connect mockée
|
||||||
|
- widget : écran Paramètres / Intégrations
|
||||||
|
- manuel scripté : device Android compatible Health Connect
|
||||||
|
|
||||||
|
Base existante :
|
||||||
|
|
||||||
|
- `test/application/health_connect_use_cases_test.dart`
|
||||||
|
- `test/presentation/settings_screen_test.dart`
|
||||||
|
|
||||||
|
### 9. Watch companion
|
||||||
|
|
||||||
|
Parcours nominaux :
|
||||||
|
|
||||||
|
- projeter une séance active vers la montre
|
||||||
|
- piloter score / timer / pause depuis la montre
|
||||||
|
- remonter la fréquence cardiaque et la télémétrie
|
||||||
|
- gérer reconnexion et fraîcheur de projection
|
||||||
|
|
||||||
|
Cas limites :
|
||||||
|
|
||||||
|
- téléphone absent
|
||||||
|
- projection stale
|
||||||
|
- actions bloquées en reconnexion
|
||||||
|
- timer visible en pause
|
||||||
|
- TTL dépassé
|
||||||
|
|
||||||
|
Suites attendues :
|
||||||
|
|
||||||
|
- unitaires : contrat de projection, commandes, policy de retry
|
||||||
|
- intégration : bridge natif téléphone <-> montre
|
||||||
|
- widget : UI montre
|
||||||
|
- manuel scripté : téléphone Android + émulateur/device Wear
|
||||||
|
|
||||||
|
Base existante :
|
||||||
|
|
||||||
|
- `test/application/watch_companion_projection_test.dart`
|
||||||
|
- `test/application/watch_companion_command_handler_test.dart`
|
||||||
|
- `test/infrastructure/watch_bridge/wear_data_layer_adapter_test.dart`
|
||||||
|
- `watch_app/test/presentation/watch_session_screen_test.dart`
|
||||||
|
- `watch_app/android/app/src/test/kotlin/com/gametime/watch/bridge/WatchExerciseMetricsRetryPolicyTest.kt`
|
||||||
|
|
||||||
|
## Stratégie runnable par niveau de suite
|
||||||
|
|
||||||
|
### 1. Suites rapides obligatoires sur chaque lot
|
||||||
|
|
||||||
|
Objectif : feedback en quelques minutes, sans device réel.
|
||||||
|
|
||||||
|
Contenu :
|
||||||
|
|
||||||
|
- unitaires domaine/application
|
||||||
|
- intégration repository mémoire ou Drift locale
|
||||||
|
- widget ciblés
|
||||||
|
- fonctionnels mémoire via `FunctionalTestHarness`
|
||||||
|
|
||||||
|
Règle :
|
||||||
|
|
||||||
|
- toute nouvelle feature/correction doit d'abord produire ou enrichir une suite de ce niveau
|
||||||
|
|
||||||
|
### 2. Suites de référence transverses
|
||||||
|
|
||||||
|
Objectif : prouver que les briques s'assemblent sur des parcours principaux.
|
||||||
|
|
||||||
|
Contenu :
|
||||||
|
|
||||||
|
- un petit nombre de scénarios fonctionnels end-to-end en mémoire côté Flutter
|
||||||
|
- un petit nombre de scénarios API serveur de bout en bout en local
|
||||||
|
|
||||||
|
Règle :
|
||||||
|
|
||||||
|
- garder ces scénarios courts, lisibles et déterministes
|
||||||
|
- ne pas y mettre toutes les permutations écran par écran
|
||||||
|
|
||||||
|
### 3. Suites device / infra scriptées
|
||||||
|
|
||||||
|
Objectif : couvrir les frontières impossibles à prouver en sandbox mémoire.
|
||||||
|
|
||||||
|
Contenu :
|
||||||
|
|
||||||
|
- import/export réel
|
||||||
|
- Health Connect réel
|
||||||
|
- compagnon montre réel
|
||||||
|
- Docker/PostgreSQL/smoke API réel
|
||||||
|
|
||||||
|
Règle :
|
||||||
|
|
||||||
|
- documenter chaque parcours sous forme de script de validation réexécutable
|
||||||
|
- promouvoir en automatisation seulement après stabilisation du protocole et des fixtures
|
||||||
|
|
||||||
|
## Commandes cibles
|
||||||
|
|
||||||
|
### Flutter app
|
||||||
|
|
||||||
|
Installer les dépendances :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export FLUTTER_SUPPRESS_ANALYTICS=true
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter pub get
|
||||||
|
```
|
||||||
|
|
||||||
|
Smoke domaine/widget/functional :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test test/functional/functional_coverage_test.dart
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test test/presentation/workout_execution_screen_test.dart
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test test/presentation/profile_screen_test.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
### Watch app
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd watch_app
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export FLUTTER_SUPPRESS_ANALYTICS=true
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
../.ideai/flutter-sdk-1785572580/bin/flutter pub get
|
||||||
|
../.ideai/flutter-sdk-1785572580/bin/flutter test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Serveur
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd server
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
/home/anthony/Documents/Projects/GameTime/.ideai/flutter-sdk-1785572580/bin/dart pub get
|
||||||
|
/home/anthony/Documents/Projects/GameTime/.ideai/flutter-sdk-1785572580/bin/dart test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Intégration PostgreSQL réelle
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd server
|
||||||
|
TEST_DATABASE_URL=postgres://gametime:gametime@localhost:5432/gametime \
|
||||||
|
/home/anthony/Documents/Projects/GameTime/.ideai/flutter-sdk-1785572580/bin/dart test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build / smoke Android manuel scripté
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export FLUTTER_SUPPRESS_ANALYTICS=true
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter build apk --debug
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backlog initial d'automatisation
|
||||||
|
|
||||||
|
### Priorité P0 — à garder verte en permanence
|
||||||
|
|
||||||
|
- stabiliser `test/functional/functional_coverage_test.dart` comme gate Flutter transverse
|
||||||
|
- y conserver au moins 4 scénarios de référence :
|
||||||
|
- création exercice/programme/séance via formulaires réels
|
||||||
|
- exécution complète avec score manuel + chrono + repos + historique + replay
|
||||||
|
- reprise de séance sauvegardée
|
||||||
|
- séquences d'étapes avec skip et correction de résultat
|
||||||
|
- définir une commande CI rapide `flutter test test/functional/functional_coverage_test.dart`
|
||||||
|
- définir une commande CI serveur `dart test` dans `server/`
|
||||||
|
|
||||||
|
### Priorité P1 — verrouiller le cœur prod offline
|
||||||
|
|
||||||
|
- compléter une suite intégration Drift dédiée au cycle exercice -> programme -> template -> session -> historique
|
||||||
|
- ajouter une suite application dédiée aux invariants de progression à partir d'historiques réels
|
||||||
|
- ajouter une suite widget de navigation nominale accueil -> séance -> historique -> progression
|
||||||
|
- isoler un groupe "smoke critical screens" pour `home`, `exercise_library`, `program`, `workout_template`, `workout_execution`, `history`, `progression`
|
||||||
|
|
||||||
|
### Priorité P2 — verrouiller les frontières produit payantes et multi-comptes
|
||||||
|
|
||||||
|
- ajouter tests use case et serveur pour quota free/pro
|
||||||
|
- couvrir import de partage quand quota receveur est plein
|
||||||
|
- couvrir multi-comptes, restauration et sync Pro
|
||||||
|
- couvrir offline puis resync après reconnexion
|
||||||
|
|
||||||
|
### Priorité P3 — transformer les checklists device en scripts réexécutables
|
||||||
|
|
||||||
|
- écrire un script manuel standardisé Health Connect
|
||||||
|
- écrire un script manuel standardisé watch companion
|
||||||
|
- écrire un script manuel standardisé partage entre deux comptes réels
|
||||||
|
- écrire un script manuel standardisé import/export fichier réel
|
||||||
|
|
||||||
|
## Première découpe TDD recommandée pour relancer le delivery
|
||||||
|
|
||||||
|
### Sprint QA-A — gate rapide commune
|
||||||
|
|
||||||
|
- figer la convention d'environnement de test
|
||||||
|
- garder vert :
|
||||||
|
- `test/functional/functional_coverage_test.dart`
|
||||||
|
- `server/test`
|
||||||
|
- `watch_app/test`
|
||||||
|
|
||||||
|
### Sprint QA-B — cœur offline téléphone
|
||||||
|
|
||||||
|
- enrichir le functional harness pour couvrir navigation nominale complète
|
||||||
|
- compléter les invariants manquants exercice -> programme -> template -> exécution -> historique -> progression
|
||||||
|
|
||||||
|
### Sprint QA-C — compte/sync/partage
|
||||||
|
|
||||||
|
- préparer fixtures API et scénarios 2 comptes
|
||||||
|
- séparer clairement :
|
||||||
|
- tests client mockés
|
||||||
|
- tests serveur réels
|
||||||
|
- smoke manuels API + client
|
||||||
|
|
||||||
|
### Sprint QA-D — device integrations
|
||||||
|
|
||||||
|
- formaliser scripts de validation montre et Health Connect
|
||||||
|
- décider ensuite ce qui mérite une automatisation instrumentée
|
||||||
|
|
||||||
|
## Critères de sortie pour qu'une feature soit "finie"
|
||||||
|
|
||||||
|
Une feature n'est pas considérée terminée tant que :
|
||||||
|
|
||||||
|
- le plan fonctionnel du lot existe
|
||||||
|
- les tests unitaires / intégration / widget prévus pour le lot existent
|
||||||
|
- les commandes de suites rapides ont réellement tourné
|
||||||
|
- les éventuels scripts manuels device/infra ont réellement été exécutés si la feature touche ces frontières
|
||||||
|
- les régressions critiques correspondantes sont absorbées dans les suites P0/P1
|
||||||
|
|
||||||
|
## Recommandation immédiate
|
||||||
|
|
||||||
|
Pour redémarrer vers la prod sans disperser l'équipe :
|
||||||
|
|
||||||
|
1. utiliser `test/functional/functional_coverage_test.dart` comme colonne vertébrale Flutter
|
||||||
|
2. considérer `server/test` comme gate du scope compte/sync/partage
|
||||||
|
3. ne pas lancer de nouvelle feature transverse sans ajouter son scénario dans le harnais fonctionnel ou dans une suite serveur équivalente
|
||||||
|
4. traiter Health Connect et watch companion comme checklists scriptées tant que le setup device n'est pas stabilisé en CI
|
||||||
63
docs/qa-gate-239-functional-flutter.md
Normal file
63
docs/qa-gate-239-functional-flutter.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# QA Gate #239 — Suite fonctionnelle Flutter transverse
|
||||||
|
|
||||||
|
## But
|
||||||
|
|
||||||
|
Cette gate sert de socle rapide de non-régression Flutter pour la reprise TDD.
|
||||||
|
Elle couvre le parcours transverse minimal suivant :
|
||||||
|
|
||||||
|
- création via formulaires réels
|
||||||
|
- exécution complète d'une séance
|
||||||
|
- reprise de séance
|
||||||
|
- séquences, skip et correction
|
||||||
|
|
||||||
|
## Fichier source
|
||||||
|
|
||||||
|
- `test/functional/functional_coverage_test.dart`
|
||||||
|
|
||||||
|
## Pré-requis
|
||||||
|
|
||||||
|
Utiliser un environnement writable pour Flutter :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export FLUTTER_SUPPRESS_ANALYTICS=true
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commande gate complète
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test test/functional/functional_coverage_test.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commandes ciblées utiles
|
||||||
|
|
||||||
|
Scénario de référence transverse :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test test/functional/functional_coverage_test.dart --plain-name "complete execution covers manual score, stopwatch, rests, skips, history and replay"
|
||||||
|
```
|
||||||
|
|
||||||
|
Scénario reprise :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test test/functional/functional_coverage_test.dart --plain-name "saved exit sessions resume from the execution UI without showing completion"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verdict attendu
|
||||||
|
|
||||||
|
- vert si la base Flutter transverse est prête pour une boucle TDD rapide
|
||||||
|
- rouge si un parcours nominal majeur est cassé
|
||||||
|
|
||||||
|
## Preuve réelle du 22 août 2026
|
||||||
|
|
||||||
|
Exécution rapportée verte sur `/tmp/gametime-src-1787384228`.
|
||||||
|
|
||||||
|
Cette gate devient la référence rapide de non-régression Flutter transverse.
|
||||||
|
|
||||||
|
## Usage dans la boucle TDD
|
||||||
|
|
||||||
|
- avant implémentation d'une feature transverse touchant exécution/navigation
|
||||||
|
- après chaque lot modifiant les formulaires, l'exécution, l'historique ou la reprise
|
||||||
|
- comme gate rapide avant d'élargir vers les suites widget plus détaillées
|
||||||
57
docs/qa-gate-240-drift-core-offline.md
Normal file
57
docs/qa-gate-240-drift-core-offline.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# QA Gate #240 — Suite coeur offline Drift
|
||||||
|
|
||||||
|
## But
|
||||||
|
|
||||||
|
Cette gate sécurise le coeur offline local avant reprise intensive du développement.
|
||||||
|
Le point d'entrée recommandé est le parcours intégré :
|
||||||
|
|
||||||
|
- exercice
|
||||||
|
- programme
|
||||||
|
- séance-template
|
||||||
|
- session active
|
||||||
|
- clôture en historique
|
||||||
|
- progression minimale
|
||||||
|
|
||||||
|
## Fichier source
|
||||||
|
|
||||||
|
- `test/infrastructure/drift_repositories_test.dart`
|
||||||
|
|
||||||
|
## Pré-requis
|
||||||
|
|
||||||
|
Utiliser le runner Flutter/Dart avec un environnement writable :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export FLUTTER_SUPPRESS_ANALYTICS=true
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commande gate complète
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test test/infrastructure/drift_repositories_test.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Point d'entrée coeur offline recommandé
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test test/infrastructure/drift_repositories_test.dart --plain-name "QA core offline journey persists exercise to progression through local repositories"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verdict attendu
|
||||||
|
|
||||||
|
- vert si la chaîne locale principale reste cohérente de la création jusqu'à la progression
|
||||||
|
- rouge si le domaine local ou la persistance Drift régressent sur le flux principal
|
||||||
|
|
||||||
|
## Preuve réelle du 22 août 2026
|
||||||
|
|
||||||
|
Exécution rapportée verte sur `/tmp/gametime-src-1787384228`.
|
||||||
|
|
||||||
|
Cette gate devient la référence coeur offline avant toute validation device ou release.
|
||||||
|
|
||||||
|
## Usage dans la boucle TDD
|
||||||
|
|
||||||
|
- à lancer avant et après chaque lot touchant les use cases offline
|
||||||
|
- à utiliser comme première preuve exécutable avant les suites écran par écran
|
||||||
|
- à compléter ensuite par les tests fonctionnels Flutter et, plus tard, les validations device
|
||||||
73
docs/qa-gate-241-critical-screens-smoke.md
Normal file
73
docs/qa-gate-241-critical-screens-smoke.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# QA Gate #241 — Smoke écrans critiques Flutter
|
||||||
|
|
||||||
|
## But
|
||||||
|
|
||||||
|
Cette gate sert de détection rapide des régressions visibles majeures pendant la boucle TDD Flutter.
|
||||||
|
|
||||||
|
Écrans couverts :
|
||||||
|
|
||||||
|
- `home`
|
||||||
|
- `exercise library`
|
||||||
|
- `program`
|
||||||
|
- `workout template`
|
||||||
|
- `workout execution`
|
||||||
|
- `history`
|
||||||
|
- `progression`
|
||||||
|
- `profile`
|
||||||
|
|
||||||
|
## Fichiers sources
|
||||||
|
|
||||||
|
- `test/presentation/home_screen_test.dart`
|
||||||
|
- `test/presentation/exercise_library_screen_test.dart`
|
||||||
|
- `test/presentation/program_screen_test.dart`
|
||||||
|
- `test/presentation/workout_template_screen_test.dart`
|
||||||
|
- `test/presentation/workout_execution_screen_test.dart`
|
||||||
|
- `test/presentation/history_screen_test.dart`
|
||||||
|
- `test/presentation/progression_screen_test.dart`
|
||||||
|
- `test/presentation/profile_screen_test.dart`
|
||||||
|
|
||||||
|
## Pré-requis
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export FLUTTER_SUPPRESS_ANALYTICS=true
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Point d'entrée recommandé
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tool/qa_gate_241_critical_screens_smoke.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commande directe équivalente
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test \
|
||||||
|
test/presentation/home_screen_test.dart \
|
||||||
|
test/presentation/exercise_library_screen_test.dart \
|
||||||
|
test/presentation/program_screen_test.dart \
|
||||||
|
test/presentation/workout_template_screen_test.dart \
|
||||||
|
test/presentation/workout_execution_screen_test.dart \
|
||||||
|
test/presentation/history_screen_test.dart \
|
||||||
|
test/presentation/progression_screen_test.dart \
|
||||||
|
test/presentation/profile_screen_test.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verdict attendu
|
||||||
|
|
||||||
|
- vert si les écrans critiques restent fonctionnels sur les parcours nominaux majeurs
|
||||||
|
- rouge si une régression UI majeure casse la boucle TDD Flutter
|
||||||
|
|
||||||
|
## Preuve réelle du 22 août 2026
|
||||||
|
|
||||||
|
Exécution rapportée verte sur `/tmp/gametime-src-1787384228`.
|
||||||
|
|
||||||
|
Le script `./tool/qa_gate_241_critical_screens_smoke.sh` devient l'entrée de référence pour ce smoke.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
- avant merge d'un lot Flutter transverse
|
||||||
|
- après toute modification navigation/formulaires/exécution/historique/profil
|
||||||
|
- en complément de la gate `#239`
|
||||||
80
docs/qa-gate-242-monetization-free-pro.md
Normal file
80
docs/qa-gate-242-monetization-free-pro.md
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# QA Gate #242 — Monétisation Free/Pro et partage/quota
|
||||||
|
|
||||||
|
## But
|
||||||
|
|
||||||
|
Matérialiser une première gate runnable autour de ce qui est déjà testable aujourd'hui, tout en isolant les blockers réels pour les règles Free/Pro non encore implémentées.
|
||||||
|
|
||||||
|
## Ce qui est runnable maintenant
|
||||||
|
|
||||||
|
Couverture partielle déjà testable :
|
||||||
|
|
||||||
|
- profil et synchronisation côté Flutter
|
||||||
|
- partage / inbox / acceptation locale
|
||||||
|
- Health Connect gratuit
|
||||||
|
- companion montre gratuit
|
||||||
|
|
||||||
|
Fichiers déjà exploitables :
|
||||||
|
|
||||||
|
- `test/presentation/profile_screen_test.dart`
|
||||||
|
- `test/presentation/share_inbox_screen_test.dart`
|
||||||
|
- `test/presentation/settings_screen_test.dart`
|
||||||
|
- `test/application/health_connect_use_cases_test.dart`
|
||||||
|
- `test/application/watch_companion_projection_test.dart`
|
||||||
|
|
||||||
|
## Point d'entrée recommandé
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tool/qa_gate_242_monetization_partial.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pré-requis
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export FLUTTER_SUPPRESS_ANALYTICS=true
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commande directe équivalente
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./.ideai/flutter-sdk-1785572580/bin/flutter test \
|
||||||
|
test/presentation/profile_screen_test.dart \
|
||||||
|
test/presentation/share_inbox_screen_test.dart \
|
||||||
|
test/presentation/settings_screen_test.dart \
|
||||||
|
test/application/health_connect_use_cases_test.dart \
|
||||||
|
test/application/watch_companion_projection_test.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Blockers réels
|
||||||
|
|
||||||
|
Les contrats suivants ne sont pas encore testables proprement contre du code produit, car la surface métier n'existe pas encore clairement dans le repo :
|
||||||
|
|
||||||
|
- quota `Free/Pro`
|
||||||
|
- refus création/édition quand quota plein
|
||||||
|
- import de partage chez receveur plein
|
||||||
|
- restauration d'achat
|
||||||
|
- statut `Pro`
|
||||||
|
- sync `Pro`
|
||||||
|
- multi-comptes monétisation
|
||||||
|
|
||||||
|
## Recommandation de suite
|
||||||
|
|
||||||
|
Avant d'écrire une vraie suite verte sur ces règles, il faut introduire un contrat métier testable, par exemple :
|
||||||
|
|
||||||
|
- une policy `LibraryEntitlementPolicy`
|
||||||
|
- un use case `QuotaGuard`
|
||||||
|
- un état de compte distinguant `Free` et `Pro`
|
||||||
|
- une règle explicite d'acceptation de partage sous quota
|
||||||
|
|
||||||
|
## Verdict attendu
|
||||||
|
|
||||||
|
- vert aujourd'hui sur la gate partielle gratuite / partage
|
||||||
|
- rouge ou non applicable sur Free/Pro tant que la couche métier quota/billing n'existe pas
|
||||||
|
|
||||||
|
## Preuve réelle du 22 août 2026
|
||||||
|
|
||||||
|
Exécution rapportée verte sur `/tmp/gametime-src-1787384228`.
|
||||||
|
|
||||||
|
Cette gate valide la surface monétisation actuellement testable en local, sans fermer la QA release Android Play Store.
|
||||||
105
docs/qa-gate-243-device-runbooks.md
Normal file
105
docs/qa-gate-243-device-runbooks.md
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# QA Gate #243 — Runbooks manuels device
|
||||||
|
|
||||||
|
## But
|
||||||
|
|
||||||
|
Standardiser les validations device non encore raisonnablement automatisables, avec des scripts réexécutables de collecte d'artefacts et un déroulé manuel stable.
|
||||||
|
|
||||||
|
Périmètre couvert :
|
||||||
|
|
||||||
|
- Health Connect téléphone Android
|
||||||
|
- watch companion téléphone + Wear
|
||||||
|
- import/export réel sur téléphone
|
||||||
|
|
||||||
|
## Références officielles
|
||||||
|
|
||||||
|
### Health Connect
|
||||||
|
|
||||||
|
Préparer la collecte :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tool/qa_device_health_connect.sh start
|
||||||
|
```
|
||||||
|
|
||||||
|
Finaliser la collecte :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tool/qa_device_health_connect.sh stop <artifact_dir>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Watch companion
|
||||||
|
|
||||||
|
Préparer la collecte :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
WATCH_SERIAL=<watch-adb-serial> ./tool/qa_device_watch_companion.sh start
|
||||||
|
```
|
||||||
|
|
||||||
|
Finaliser la collecte :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
WATCH_SERIAL=<watch-adb-serial> ./tool/qa_device_watch_companion.sh stop <artifact_dir>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Import / export réel
|
||||||
|
|
||||||
|
Préparer la collecte :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tool/qa_device_import_export_real.sh start
|
||||||
|
```
|
||||||
|
|
||||||
|
Finaliser la collecte :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tool/qa_device_import_export_real.sh stop <artifact_dir>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pré-requis communs
|
||||||
|
|
||||||
|
- `adb` disponible dans le `PATH`
|
||||||
|
- appareil téléphone connecté et autorisé
|
||||||
|
- pour la montre : `WATCH_SERIAL` renseigné et montre visible via `adb devices -l`
|
||||||
|
- build GameTime fraîche installée sur le ou les appareils sous test
|
||||||
|
|
||||||
|
## Artefacts attendus
|
||||||
|
|
||||||
|
Chaque script crée un dossier sous :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
.ideai/artifacts/qa-device/
|
||||||
|
```
|
||||||
|
|
||||||
|
Le dossier produit doit contenir au minimum :
|
||||||
|
|
||||||
|
- `adb-devices.txt`
|
||||||
|
- fingerprint build device
|
||||||
|
- `logcat.txt` téléphone et/ou montre
|
||||||
|
- `steps.md` avec le scénario manuel joué
|
||||||
|
- `package-dumpsys-before.txt` et `package-dumpsys-after.txt` quand applicable
|
||||||
|
|
||||||
|
## Verdict attendu par runbook
|
||||||
|
|
||||||
|
### Health Connect
|
||||||
|
|
||||||
|
- ouverture propre du flux permission ou fallback réglages
|
||||||
|
- retour propre dans GameTime
|
||||||
|
- état UI cohérent avant/après
|
||||||
|
- export fin de séance vérifiable si exercé
|
||||||
|
|
||||||
|
### Watch companion
|
||||||
|
|
||||||
|
- projection de séance visible sur montre
|
||||||
|
- actions montre répercutées sur téléphone
|
||||||
|
- métriques montre lisibles, dont les pas si disponibles
|
||||||
|
- clôture de séance cohérente côté téléphone et montre
|
||||||
|
|
||||||
|
### Import / export réel
|
||||||
|
|
||||||
|
- export de fichier réussi
|
||||||
|
- réimport `merge` cohérent
|
||||||
|
- réimport `replaceAll` cohérent sur dataset jetable
|
||||||
|
- refus attendu si une séance active bloque l'import
|
||||||
|
|
||||||
|
## Limite actuelle au 22 août 2026
|
||||||
|
|
||||||
|
Ces runbooks rendent `#243` matérialisable et rejouable, mais la clôture QA device reste dépendante de la disponibilité réelle d'un appareil `adb`.
|
||||||
73
docs/release-compliance-checklist.md
Normal file
73
docs/release-compliance-checklist.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# GameTime Release and Compliance Checklist
|
||||||
|
|
||||||
|
This checklist tracks the repo-owned release/compliance work that can be closed
|
||||||
|
without Play Console access or physical devices.
|
||||||
|
|
||||||
|
## Privacy Policy
|
||||||
|
|
||||||
|
- Canonical repo draft: `docs/legal/privacy-policy-v1.md`
|
||||||
|
- Version: `1.0`
|
||||||
|
- Effective date: `2026-08-22`
|
||||||
|
- Before Play submission, publish the exact approved policy at a stable HTTPS
|
||||||
|
URL and enter that URL in Play Console.
|
||||||
|
- Keep future policy changes versioned in `docs/legal/`.
|
||||||
|
|
||||||
|
## Product Entitlements
|
||||||
|
|
||||||
|
The release surface must preserve these product invariants:
|
||||||
|
|
||||||
|
- sharing is free
|
||||||
|
- Free limits the editable workout library, not basic workout execution
|
||||||
|
- imported/shared resources count against the receiver quota on acceptance
|
||||||
|
- Pro means unlimited library plus sync
|
||||||
|
- Wear OS companion is free
|
||||||
|
- Health Connect is free
|
||||||
|
|
||||||
|
## Android Network Policy
|
||||||
|
|
||||||
|
Phone app release builds:
|
||||||
|
|
||||||
|
- keep `android.permission.INTERNET` in `android/app/src/main/AndroidManifest.xml`
|
||||||
|
- do not enable `android:usesCleartextTraffic` in the main manifest
|
||||||
|
- use HTTPS for `GAMETIME_API_BASE_URL` in release builds
|
||||||
|
|
||||||
|
Phone app debug/profile builds:
|
||||||
|
|
||||||
|
- may keep cleartext enabled through the debug/profile manifest overlays
|
||||||
|
- may use LAN HTTP URLs for local API development
|
||||||
|
|
||||||
|
Wear OS companion:
|
||||||
|
|
||||||
|
- keep release cleartext disabled
|
||||||
|
- keep companion functionality free and independent from Pro entitlement
|
||||||
|
|
||||||
|
## Repo-Only Validation
|
||||||
|
|
||||||
|
Run these checks before handing off to Play/device validation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rg -n 'usesCleartextTraffic="true"' android/app/src/main watch_app/android/app/src/main
|
||||||
|
rg -n 'usesCleartextTraffic="true"' android/app/src/debug android/app/src/profile
|
||||||
|
rg -n 'android.permission.INTERNET' android/app/src/main/AndroidManifest.xml
|
||||||
|
rg -n 'Health Connect|Wear OS|sharing is free|Pro means unlimited' docs/legal docs
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected result:
|
||||||
|
|
||||||
|
- no `usesCleartextTraffic="true"` in release/main manifests
|
||||||
|
- debug/profile overlays explicitly allow local cleartext
|
||||||
|
- phone release manifest still declares `INTERNET`
|
||||||
|
- privacy and release docs preserve the Free/Pro invariants
|
||||||
|
|
||||||
|
## External Blockers
|
||||||
|
|
||||||
|
These items cannot be closed from the repository alone:
|
||||||
|
|
||||||
|
- Play Console app content forms
|
||||||
|
- public privacy-policy hosting URL
|
||||||
|
- production support/contact address approval
|
||||||
|
- Play Health Connect declaration/review, if required by the final release track
|
||||||
|
- validation on a real Android phone
|
||||||
|
- validation on a real Wear OS device
|
||||||
|
- production HTTPS endpoint and certificate verification
|
||||||
|
|
||||||
138
tool/qa_device_health_connect.sh
Executable file
138
tool/qa_device_health_connect.sh
Executable file
@ -0,0 +1,138 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PROJECT_ROOT="/home/anthony/Documents/Projects/GameTime"
|
||||||
|
ARTIFACT_BASE="${ARTIFACT_BASE:-$PROJECT_ROOT/.ideai/artifacts/qa-device}"
|
||||||
|
PHONE_SERIAL="${PHONE_SERIAL:-}"
|
||||||
|
PACKAGE_NAME="${PACKAGE_NAME:-com.idea.gametime}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage:
|
||||||
|
./tool/qa_device_health_connect.sh start
|
||||||
|
./tool/qa_device_health_connect.sh stop <artifact_dir>
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
PHONE_SERIAL Optional adb serial for the phone under test
|
||||||
|
ARTIFACT_BASE Optional artifact root
|
||||||
|
PACKAGE_NAME Optional Android package name (default: com.idea.gametime)
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
adb_cmd() {
|
||||||
|
if [[ -n "$PHONE_SERIAL" ]]; then
|
||||||
|
adb -s "$PHONE_SERIAL" "$@"
|
||||||
|
else
|
||||||
|
adb "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
require_adb() {
|
||||||
|
command -v adb >/dev/null 2>&1 || {
|
||||||
|
echo "adb not found in PATH." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
adb start-server >/dev/null
|
||||||
|
adb_cmd get-state >/dev/null 2>&1 || {
|
||||||
|
echo "No adb device available. Connect the phone or set PHONE_SERIAL." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp() {
|
||||||
|
date -u +"%Y%m%dT%H%M%SZ"
|
||||||
|
}
|
||||||
|
|
||||||
|
start_capture() {
|
||||||
|
require_adb
|
||||||
|
local dir="$ARTIFACT_BASE/health-connect-$(timestamp)"
|
||||||
|
mkdir -p "$dir"
|
||||||
|
|
||||||
|
adb devices -l >"$dir/adb-devices.txt"
|
||||||
|
adb_cmd shell getprop ro.build.fingerprint >"$dir/phone-build-fingerprint.txt"
|
||||||
|
adb_cmd shell dumpsys package "$PACKAGE_NAME" >"$dir/package-dumpsys-before.txt" || true
|
||||||
|
adb_cmd logcat -c
|
||||||
|
adb_cmd logcat -v threadtime >"$dir/logcat.txt" 2>&1 &
|
||||||
|
local pid=$!
|
||||||
|
echo "$pid" >"$dir/logcat.pid"
|
||||||
|
|
||||||
|
cat >"$dir/steps.md" <<EOF
|
||||||
|
# Health Connect manual QA
|
||||||
|
|
||||||
|
Date: $(date -u +"%Y-%m-%d %H:%M:%SZ")
|
||||||
|
Package: $PACKAGE_NAME
|
||||||
|
|
||||||
|
## Preconditions
|
||||||
|
- Fresh GameTime phone build installed on the connected Android device.
|
||||||
|
- Health Connect available on device.
|
||||||
|
- Device unlocked.
|
||||||
|
|
||||||
|
## Manual flow
|
||||||
|
1. Open GameTime.
|
||||||
|
2. Go to Paramètres > Intégrations > Health Connect.
|
||||||
|
3. Validate the visible initial status.
|
||||||
|
4. Tap "Autoriser l'accès" or "Gérer les autorisations".
|
||||||
|
5. Validate the expected path:
|
||||||
|
- permission sheet opens, or
|
||||||
|
- settings fallback opens cleanly.
|
||||||
|
6. Grant or deny permissions according to the scenario under test.
|
||||||
|
7. Return to GameTime and validate the refreshed status.
|
||||||
|
8. Start and finish a workout if export-after-workout must be checked.
|
||||||
|
9. Confirm the final Health Connect export outcome shown by the app.
|
||||||
|
|
||||||
|
## Evidence to collect
|
||||||
|
- Screenshot(s) of the visible status before and after permission handling.
|
||||||
|
- Screenshot(s) of Health Connect permission/settings UI if opened.
|
||||||
|
- Notes on whether the path used the permission contract or settings fallback.
|
||||||
|
- Result of export-after-workout if exercised.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "$dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_capture() {
|
||||||
|
local dir="${1:-}"
|
||||||
|
[[ -n "$dir" ]] || {
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
require_adb
|
||||||
|
[[ -d "$dir" ]] || {
|
||||||
|
echo "Artifact directory not found: $dir" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -f "$dir/logcat.pid" ]]; then
|
||||||
|
kill "$(cat "$dir/logcat.pid")" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
adb_cmd shell dumpsys package "$PACKAGE_NAME" >"$dir/package-dumpsys-after.txt" || true
|
||||||
|
adb_cmd shell settings list secure >"$dir/settings-secure.txt" || true
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
Health Connect manual QA artifacts finalized in:
|
||||||
|
$dir
|
||||||
|
|
||||||
|
Archive expected:
|
||||||
|
- adb-devices.txt
|
||||||
|
- phone-build-fingerprint.txt
|
||||||
|
- package-dumpsys-before.txt
|
||||||
|
- package-dumpsys-after.txt
|
||||||
|
- logcat.txt
|
||||||
|
- steps.md
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
start)
|
||||||
|
start_capture
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
shift
|
||||||
|
stop_capture "${1:-}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
129
tool/qa_device_import_export_real.sh
Executable file
129
tool/qa_device_import_export_real.sh
Executable file
@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PROJECT_ROOT="/home/anthony/Documents/Projects/GameTime"
|
||||||
|
ARTIFACT_BASE="${ARTIFACT_BASE:-$PROJECT_ROOT/.ideai/artifacts/qa-device}"
|
||||||
|
PHONE_SERIAL="${PHONE_SERIAL:-}"
|
||||||
|
PACKAGE_NAME="${PACKAGE_NAME:-com.idea.gametime}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage:
|
||||||
|
./tool/qa_device_import_export_real.sh start
|
||||||
|
./tool/qa_device_import_export_real.sh stop <artifact_dir>
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
PHONE_SERIAL Optional adb serial for the phone under test
|
||||||
|
ARTIFACT_BASE Optional artifact root
|
||||||
|
PACKAGE_NAME Optional Android package name (default: com.idea.gametime)
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
adb_cmd() {
|
||||||
|
if [[ -n "$PHONE_SERIAL" ]]; then
|
||||||
|
adb -s "$PHONE_SERIAL" "$@"
|
||||||
|
else
|
||||||
|
adb "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
require_adb() {
|
||||||
|
command -v adb >/dev/null 2>&1 || {
|
||||||
|
echo "adb not found in PATH." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
adb start-server >/dev/null
|
||||||
|
adb_cmd get-state >/dev/null 2>&1 || {
|
||||||
|
echo "No adb device available. Connect the phone or set PHONE_SERIAL." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp() {
|
||||||
|
date -u +"%Y%m%dT%H%M%SZ"
|
||||||
|
}
|
||||||
|
|
||||||
|
start_capture() {
|
||||||
|
require_adb
|
||||||
|
local dir="$ARTIFACT_BASE/import-export-real-$(timestamp)"
|
||||||
|
mkdir -p "$dir"
|
||||||
|
|
||||||
|
adb devices -l >"$dir/adb-devices.txt"
|
||||||
|
adb_cmd shell getprop ro.build.fingerprint >"$dir/phone-build-fingerprint.txt"
|
||||||
|
adb_cmd shell dumpsys package "$PACKAGE_NAME" >"$dir/package-dumpsys-before.txt" || true
|
||||||
|
adb_cmd logcat -c
|
||||||
|
adb_cmd logcat -v threadtime >"$dir/logcat.txt" 2>&1 &
|
||||||
|
echo "$!" >"$dir/logcat.pid"
|
||||||
|
|
||||||
|
cat >"$dir/steps.md" <<EOF
|
||||||
|
# Import / export real-device QA
|
||||||
|
|
||||||
|
Date: $(date -u +"%Y-%m-%d %H:%M:%SZ")
|
||||||
|
Package: $PACKAGE_NAME
|
||||||
|
|
||||||
|
## Preconditions
|
||||||
|
- Fresh GameTime phone build installed on the connected Android device.
|
||||||
|
- At least one exercise, one program and one workout template available locally.
|
||||||
|
- File picker available on device.
|
||||||
|
|
||||||
|
## Manual flow
|
||||||
|
1. Open GameTime.
|
||||||
|
2. Go to the profile/settings surface exposing import/export.
|
||||||
|
3. Export local data and confirm a file is produced.
|
||||||
|
4. Record the exported filename and storage location.
|
||||||
|
5. Re-import the same file in merge mode and validate the expected result.
|
||||||
|
6. Re-import in replace-all mode only on a disposable dataset.
|
||||||
|
7. If relevant, try importing while an active workout exists and validate the expected refusal.
|
||||||
|
|
||||||
|
## Evidence to collect
|
||||||
|
- Screenshot(s) before export and after export confirmation.
|
||||||
|
- Exported filename and location.
|
||||||
|
- Screenshot(s) after merge import and replace-all import.
|
||||||
|
- Notes on any refusal caused by active workout protection.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "$dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_capture() {
|
||||||
|
local dir="${1:-}"
|
||||||
|
[[ -n "$dir" ]] || {
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
require_adb
|
||||||
|
[[ -d "$dir" ]] || {
|
||||||
|
echo "Artifact directory not found: $dir" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ -f "$dir/logcat.pid" ]] && kill "$(cat "$dir/logcat.pid")" >/dev/null 2>&1 || true
|
||||||
|
adb_cmd shell dumpsys package "$PACKAGE_NAME" >"$dir/package-dumpsys-after.txt" || true
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
Import/export manual QA artifacts finalized in:
|
||||||
|
$dir
|
||||||
|
|
||||||
|
Archive expected:
|
||||||
|
- adb-devices.txt
|
||||||
|
- phone-build-fingerprint.txt
|
||||||
|
- package-dumpsys-before.txt
|
||||||
|
- package-dumpsys-after.txt
|
||||||
|
- logcat.txt
|
||||||
|
- steps.md
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
start)
|
||||||
|
start_capture
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
shift
|
||||||
|
stop_capture "${1:-}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
154
tool/qa_device_watch_companion.sh
Executable file
154
tool/qa_device_watch_companion.sh
Executable file
@ -0,0 +1,154 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PROJECT_ROOT="/home/anthony/Documents/Projects/GameTime"
|
||||||
|
ARTIFACT_BASE="${ARTIFACT_BASE:-$PROJECT_ROOT/.ideai/artifacts/qa-device}"
|
||||||
|
PHONE_SERIAL="${PHONE_SERIAL:-}"
|
||||||
|
WATCH_SERIAL="${WATCH_SERIAL:-}"
|
||||||
|
PACKAGE_NAME="${PACKAGE_NAME:-com.idea.gametime}"
|
||||||
|
WATCH_PACKAGE_NAME="${WATCH_PACKAGE_NAME:-com.idea.gametime}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage:
|
||||||
|
./tool/qa_device_watch_companion.sh start
|
||||||
|
./tool/qa_device_watch_companion.sh stop <artifact_dir>
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
PHONE_SERIAL Optional adb serial for the phone under test
|
||||||
|
WATCH_SERIAL Optional adb serial for the Wear device under test
|
||||||
|
ARTIFACT_BASE Optional artifact root
|
||||||
|
PACKAGE_NAME Optional phone package name
|
||||||
|
WATCH_PACKAGE_NAME Optional watch package name
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
adb_phone() {
|
||||||
|
if [[ -n "$PHONE_SERIAL" ]]; then
|
||||||
|
adb -s "$PHONE_SERIAL" "$@"
|
||||||
|
else
|
||||||
|
adb "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
adb_watch() {
|
||||||
|
[[ -n "$WATCH_SERIAL" ]] || {
|
||||||
|
echo "WATCH_SERIAL is required for watch companion QA." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
adb -s "$WATCH_SERIAL" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
require_adb() {
|
||||||
|
command -v adb >/dev/null 2>&1 || {
|
||||||
|
echo "adb not found in PATH." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
adb start-server >/dev/null
|
||||||
|
adb_phone get-state >/dev/null 2>&1 || {
|
||||||
|
echo "No phone adb device available." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
adb_watch get-state >/dev/null 2>&1 || {
|
||||||
|
echo "No watch adb device available." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp() {
|
||||||
|
date -u +"%Y%m%dT%H%M%SZ"
|
||||||
|
}
|
||||||
|
|
||||||
|
start_capture() {
|
||||||
|
require_adb
|
||||||
|
local dir="$ARTIFACT_BASE/watch-companion-$(timestamp)"
|
||||||
|
mkdir -p "$dir"
|
||||||
|
|
||||||
|
adb devices -l >"$dir/adb-devices.txt"
|
||||||
|
adb_phone shell getprop ro.build.fingerprint >"$dir/phone-build-fingerprint.txt"
|
||||||
|
adb_watch shell getprop ro.build.fingerprint >"$dir/watch-build-fingerprint.txt"
|
||||||
|
adb_phone shell dumpsys package "$PACKAGE_NAME" >"$dir/phone-package-dumpsys-before.txt" || true
|
||||||
|
adb_watch shell dumpsys package "$WATCH_PACKAGE_NAME" >"$dir/watch-package-dumpsys-before.txt" || true
|
||||||
|
adb_phone logcat -c
|
||||||
|
adb_watch logcat -c
|
||||||
|
adb_phone logcat -v threadtime >"$dir/phone-logcat.txt" 2>&1 &
|
||||||
|
echo "$!" >"$dir/phone-logcat.pid"
|
||||||
|
adb_watch logcat -v threadtime >"$dir/watch-logcat.txt" 2>&1 &
|
||||||
|
echo "$!" >"$dir/watch-logcat.pid"
|
||||||
|
|
||||||
|
cat >"$dir/steps.md" <<EOF
|
||||||
|
# Watch companion manual QA
|
||||||
|
|
||||||
|
Date: $(date -u +"%Y-%m-%d %H:%M:%SZ")
|
||||||
|
Phone package: $PACKAGE_NAME
|
||||||
|
Watch package: $WATCH_PACKAGE_NAME
|
||||||
|
|
||||||
|
## Preconditions
|
||||||
|
- Phone and watch connected through adb.
|
||||||
|
- Same GameTime app version installed on both.
|
||||||
|
- Watch paired to the phone and reachable.
|
||||||
|
|
||||||
|
## Manual flow
|
||||||
|
1. Launch GameTime on the phone.
|
||||||
|
2. Start a workout from the phone.
|
||||||
|
3. Validate that the active session is projected to the watch.
|
||||||
|
4. Validate visible metrics on watch, including steps if available.
|
||||||
|
5. Trigger at least one action from the watch that must affect the phone session.
|
||||||
|
6. Validate phone UI updates correctly after the watch action.
|
||||||
|
7. Finish the workout and validate the watch teardown / final state.
|
||||||
|
|
||||||
|
## Evidence to collect
|
||||||
|
- Screenshot(s) on phone and watch while a session is active.
|
||||||
|
- Notes on connection status and any visible lag.
|
||||||
|
- Notes on step visibility if data is present.
|
||||||
|
- Final verdict on session projection and round-trip actions.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "$dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_capture() {
|
||||||
|
local dir="${1:-}"
|
||||||
|
[[ -n "$dir" ]] || {
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
require_adb
|
||||||
|
[[ -d "$dir" ]] || {
|
||||||
|
echo "Artifact directory not found: $dir" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ -f "$dir/phone-logcat.pid" ]] && kill "$(cat "$dir/phone-logcat.pid")" >/dev/null 2>&1 || true
|
||||||
|
[[ -f "$dir/watch-logcat.pid" ]] && kill "$(cat "$dir/watch-logcat.pid")" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
adb_phone shell dumpsys package "$PACKAGE_NAME" >"$dir/phone-package-dumpsys-after.txt" || true
|
||||||
|
adb_watch shell dumpsys package "$WATCH_PACKAGE_NAME" >"$dir/watch-package-dumpsys-after.txt" || true
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
Watch companion manual QA artifacts finalized in:
|
||||||
|
$dir
|
||||||
|
|
||||||
|
Archive expected:
|
||||||
|
- adb-devices.txt
|
||||||
|
- phone-build-fingerprint.txt
|
||||||
|
- watch-build-fingerprint.txt
|
||||||
|
- phone-logcat.txt
|
||||||
|
- watch-logcat.txt
|
||||||
|
- steps.md
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
start)
|
||||||
|
start_capture
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
shift
|
||||||
|
stop_capture "${1:-}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
17
tool/qa_gate_241_critical_screens_smoke.sh
Executable file
17
tool/qa_gate_241_critical_screens_smoke.sh
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export FLUTTER_SUPPRESS_ANALYTICS=true
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
|
||||||
|
exec ./.ideai/flutter-sdk-1785572580/bin/flutter test \
|
||||||
|
test/presentation/home_screen_test.dart \
|
||||||
|
test/presentation/exercise_library_screen_test.dart \
|
||||||
|
test/presentation/program_screen_test.dart \
|
||||||
|
test/presentation/workout_template_screen_test.dart \
|
||||||
|
test/presentation/workout_execution_screen_test.dart \
|
||||||
|
test/presentation/history_screen_test.dart \
|
||||||
|
test/presentation/progression_screen_test.dart \
|
||||||
|
test/presentation/profile_screen_test.dart
|
||||||
14
tool/qa_gate_242_monetization_partial.sh
Executable file
14
tool/qa_gate_242_monetization_partial.sh
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export HOME=/tmp
|
||||||
|
export XDG_CONFIG_HOME=/tmp
|
||||||
|
export FLUTTER_SUPPRESS_ANALYTICS=true
|
||||||
|
export DART_SUPPRESS_ANALYTICS=true
|
||||||
|
|
||||||
|
exec ./.ideai/flutter-sdk-1785572580/bin/flutter test \
|
||||||
|
test/presentation/profile_screen_test.dart \
|
||||||
|
test/presentation/share_inbox_screen_test.dart \
|
||||||
|
test/presentation/settings_screen_test.dart \
|
||||||
|
test/application/health_connect_use_cases_test.dart \
|
||||||
|
test/application/watch_companion_projection_test.dart
|
||||||
Reference in New Issue
Block a user