Tests des clés et véhicules¶
Les garages rattachés aux bâtiments ajoutent les matrices personal/group et la relocation
transactionnelle de recovery décrites dans Tests immobilier et bâtiments.
Automatisation¶
Depuis le conteneur API :
pytest tests/test_vehicles.py tests/test_inventories.py tests/test_groups.py tests/test_bank.py
ruff check app tests
alembic upgrade head
Les tests véhicules contrôlent la paire véhicule/clé, le format de plaque, l’idempotence, le verrou, l’autorisation moteur, les protections génériques, le transfert de génération et l’atomicité du paiement serrurier.
Régression des doubles de clés¶
test_locksmith_duplicate_payment_and_insufficient_balance_are_atomic conserve les deux objets
créés par le serrurier, puis vérifie successivement le verrouillage sans UUID (U/possession
générale), chacune des deux instances exactes, l'autorisation moteur et les options du serrurier.
test_duplicate_keys_remain_independent_when_transferred transfère les doubles un par un : le
détenteur de la clé déplacée peut l'utiliser, l'ancien détenteur conserve ses droits tant qu'une
autre clé reste dans son inventaire, puis les perd lorsque les deux ont quitté celui-ci. Le nouveau
détenteur possédant alors deux clés doit continuer à verrouiller et démarrer sans exception de
cardinalité.
Valider également :
npm --prefix fivem ci
npm --prefix fivem test
node --test fivem/tests/nui-transparency.test.mjs
node --check admin/public/app.js
node --check fivem/resources/[local]/medusa-admin/server.js
node --check fivem/resources/[local]/medusa-admin/web/app.js
node --check fivem/resources/[local]/medusa-vehicles/server.js
node --check fivem/resources/[local]/medusa-vehicles/web/app.js
node .agents/scripts/refresh-context.mjs --check
node .agents/scripts/validate-domain-context.mjs
git diff --check
La garde statique Lua doit aussi retourner zéro occurrence :
rg -n "\b(Number|String|Boolean)\(" fivem/resources -g "*.lua"
Recette à deux clients obligatoire¶
Le build et les tests statiques ne prouvent pas le comportement en jeu. Utiliser deux personnages et au moins un véhicule vanilla puis un custom.
- Founder ouvre F10, enregistre un véhicule vide et immobile à moins de 10 m.
- Vérifier la plaque
DDLLLDDD, le verrouillage immédiat, le moteur coupé et la clé principale à 0 kg. - Reconfigurer la touche de verrouillage dans les options, puis tester
Uà bord, à pied, à 15 m et au-delà. Répéter juste après enregistrement puis après une sortie/re-entrée de zone pour couvrir une réplication tardive du state bag. Couper temporairement la réponse serveur en environnement de test et vérifier l'erreur visible après trois secondes, puis le bon fonctionnement à l'essai suivant. À pied, le geste de télécommande doit suivre chaque succès serveur ; à bord, trop loin, sans réponse ou sur refus, aucun geste ne doit être joué. - Utiliser la clé en cliquant dessus sans fermer l’inventaire, puis depuis un slot rapide. Vérifier
le geste
anim@mp_player_intmenu@key_fob@/fob_click, 1 signal au verrouillage, 2 au déverrouillage et aucun toast de succès. Pendant que l'inventaire reste focalisé, vérifier queUest ignoré mais que le clic sur la clé part bien ; fermer ensuite l'inventaire et vérifierU. - Avec le second client sans clé, tester entrée et démarrage refusés. À bord d’une voiture fermée, vérifier la sortie bloquée ; sur moto, quad et bateau, vérifier la descente autorisée.
- Monter conducteur avec la clé et attendre sans toucher aux commandes : le moteur reste éteint.
Appuyer sur l'action Accélérer (
Zsur l'AZERTY courant) : le moteur démarre sans être recoupé à l'image suivante. L'arrêter avecG, puis le redémarrer avecG. Remapper successivement Accélérer dans GTA et « Démarrer ou arrêter le moteur » dans FiveM : les deux nouvelles touches doivent fonctionner sans lettre codée en dur. Sur un profil ayant déjà chargé l'ancien défautM, affecter explicitement l'action moteur àGdans les options FiveM et vérifier que cette préférence personnelle est conservée après reconnexion. Moteur allumé, l'arrêter avecG, puis presser ou spammer Accélérer immédiatement et à 59,9 s : le moteur reste coupé, aucune notification n'apparaît et aucun événement moteur ne part. Pendant ce délai,Gdoit redémarrer immédiatement. Refaire l'arrêt, attendre 60 s, relâcher puis presser Accélérer : le démarrage est de nouveau demandé. Répéter en descendant, en changeant de siège ou de véhicule : le délai local doit être nettoyé. Un second conducteur avec une clé doit pouvoir démarrer sans hériter du délai ; un restart de la ressource ne doit laisser aucun état résiduel. Régler temporairementengineAccelerationRestartDelayMsà0, puis à une valeur négative : dans les deux cas Accélérer redevient immédiatement disponible après l'arrêt, sans erreur Lua. Donner/déposer/stocker ensuite la clé pendant que le moteur tourne : il reste allumé etGpeut l'arrêter, mais Accélérer etGrefusent le redémarrage sans clé. Simuler personnage absent, refus API et réponse perdue : une erreur privée ou un timeout apparaît sous trois secondes, puis le prochain essai fonctionne sans reconnecter. - Tester don, drop et stockage : seul le détenteur réel peut agir. Révoquer ensuite depuis F10/web et vérifier la disparition de l’objet.
- Transférer personnage vers groupe puis groupe vers personnage. Vérifier génération, nouvelle clé et permissions groupe séparées.
- Placer un serrurier sur un trottoir plat puis sur une pente et vérifier que ses pieds touchent le
sol sans flottement ni enfoncement. Le déplacer, changer son modèle, sortir/revenir dans la zone
puis redémarrer la ressource : une seule instance actualisée doit rester. Avec un modèle invalide
en environnement de test, vérifier la ligne
[medusa-vehicles]en F8 et l'absence de faux Ped. Tester ensuite prix 0/250/1000, solde insuffisant, inventaire plein, double simultané et reprogrammation. Après un premier double, conserver les deux clés dans l'inventaire et rejouerU, le clic sur chacune,G, Accélérer, F5 et l'ouverture du serrurier. Déposer ensuite un seul double : l'autre doit continuer à fonctionner immédiatement. Reprendre la clé, transférer chaque double séparément et vérifier que seul l'inventaire qui contient physiquement au moins une clé est autorisé. F8 et les logs API ne doivent contenir niMultipleResultsFoundni réponse 500. Avec zéro compte personnel, vérifier l'option explicite, le conseil bancaire et les boutons grisés ; avec un ou plusieurs comptes personnels actifs, vérifierNUMÉRO — $SOLDE. Les comptes joints, de groupe, fermés ou en attente ne doivent pas apparaître. Avant la première ouverture, puis après cinq cycles ouverture/fermeture, vérifier à 1280×720, 1920×1080 et en ultralarge que l’état fermé ne laisse aucun fond noir ou voile et ne capture ni clic ni clavier. Ouverte, seule la console du serrurier doit peindre une surface sombre : aucun rectangle noir ne doit entourer le panneau, jusque dans les coins de l'écran. - Attendre plus de 20 secondes, modifier dégâts/ouvrants, reconnecter puis redémarrer la ressource : plaque/verrou/état convergent et une seule entité existe.
- Détruire le véhicule : le dossier devient indisponible et reste restaurable. Tester
/delvsur un temporaire puis sur un enregistré. - Répéter sur auto/utilitaire/camion, moto, quad, bateau, avion et hélicoptère ; vérifier le refus train/spécial/modèle cassé.
Pannes et sécurité¶
- Couper l’API : les nouvelles actions échouent fermées, avec erreur privée, sans couper un moteur déjà actif.
- Falsifier network ID, plaque, vehicle ID, item UUID, owner et bucket : aucune mutation ne doit se produire.
- Presser
Usimultanément sur les deux clients puis spammer : une seule transition par mutex/cooldown. - Désactiver
VEHICLES_ENABLEDavec des dossiers présents : aucune nouvelle action runtime, aucune perte de données. - Inspecter les audits de register, plaque, transfert, restore, despawn, delete, clés et serruriers ; les locks ordinaires ne doivent pas polluer le journal.
Conserver captures, timestamps, plaques, modèles et extraits de logs comme preuve. Ne déclarer les critères E2E validés qu’après cette recette réelle.
Administration spatiale F10¶
- Créer un véhicule personnel puis un véhicule de groupe. Actualiser F10 et vérifier les libellés
PROPRIÉTAIRE : Prénom NometGROUPE : Nom, sans UUID. Tester aussi un nom long. - Avec le véhicule actif dans la même instance, cliquer sur GPS, puis SE TP à pied et dans un véhicule. Vérifier le marqueur, le décalage sûr, les collisions et les audits.
- Rejouer GPS/TP sur un véhicule remisé, indisponible, sans entité runtime, dans un autre bucket et
avec un UUID forgé. Rejouer sans
ADMIN_ALLOW_VIEW_VEHICLES, puis sansADMIN_ALLOW_TPC. - Ouvrir RESTAURER, annuler, choisir DERNIER EMPLACEMENT, puis DEVANT MOI. Vérifier une seule entité, la position persistée, les portes verrouillées et le moteur coupé.
- Rejouer avec un occupant, une position invalide et deux restaurations simultanées : toutes doivent échouer sans déplacer un joueur ni créer de doublon.
- Vérifier les huit actions et la ligne propriétaire en 1280×720, 1920×1080 et 2560×1080, à la souris puis au clavier. Aucun bouton ne doit être coupé et le focus doit rester visible.
Attendu : VEH-API-005, VEH-LIFE-005, VEH-UI-005 et VEH-ADM-005 à 007 sont satisfaits ;
les coordonnées sont dérivées côté serveur et aucun libellé ne promet un garage.
Administration web des propriétaires¶
- Ouvrir la page Véhicules avec un véhicule personnel et un véhicule de groupe ; vérifier les noms RP/groupes et l'absence d'UUID visible, puis filtrer par prénom, nom et groupe.
- Ouvrir Transférer, rechercher avec 0, 1 puis 2 caractères, changer le type en cours de recherche et sélectionner séparément le propriétaire et le destinataire de la clé.
- Transférer vers un personnage, puis vers un groupe avec un autre personnage destinataire ; vérifier le propriétaire, la révocation des anciennes clés et la nouvelle clé principale.
- Rejouer la recherche sans
ADMIN_ALLOW_EDIT_VEHICLE, avec des UUID falsifiés ou supprimés, et vérifier que le dossier et les clés restent inchangés. - Tester à 1280×720, 1920×1080, 2560×1080 et sur une largeur mobile : scroll, Échap, Annuler, clavier, focus, nom long et absence de débordement.
Attendu : VEH-API-006, VEH-WEB-001 et VEH-WEB-002 sont satisfaits ; vingt suggestions au
maximum sont retournées, les réponses obsolètes ne remplacent pas la recherche courante et aucun
UUID n'est demandé ou affiché.
Recette plaques et garages¶
Automatisé : exécuter pytest tests/test_vehicle_garages.py tests/test_vehicles.py
tests/test_permissions.py tests/test_system.py. Vérifier génération signée, 100 plaques ambiantes
uniques, validation manuelle, rangement idempotent, réservation/finalisation, conservation du
carburant, mauvais garage et sorties toutes occupées. alembic heads doit retourner uniquement
0032_vehicle_garages.
Recette FiveM obligatoire avec deux clients :
- démarrer puis redémarrer deux fois
medusa-vehicleset vérifier dans F8/CitizenFX l'absence deError parsing script,Failed to load script, export manquant et erreur NUI ; - visiter les neuf sites et vérifier cercle bleu de 2 mètres sans borne, blip, catégorie et sorties sans collision ; renommer puis désactiver/réactiver un garage et vérifier qu'un seul blip à jour subsiste ;
- ranger avec
Eun véhicule contenant conducteur, passager joueur et PNJ ; tous sortent et une seule entité disparaît après sauvegarde ; - sortir simultanément le même véhicule ; une seule réservation et une seule entité existent ;
- occuper toutes les sorties ; aucun spawn ni débit ne se produit ;
- vérifier dégâts, roues, carburant, plaque, verrouillage et moteur coupé après sortie ;
- redémarrer la ressource puis FXServer avec états active/garaged/impounded ; seuls les active réapparaissent une fois ;
- tester F10 et web avec fondateur puis permissions unitaires refusées ;
- dans F10, utiliser SE TP sur un garage actif puis inactif, à pied et dans un véhicule ;
vérifier le refus sans
ADMIN_ALLOW_VIEW_GARAGES, sansADMIN_ALLOW_TPC, avec UUID forgé ou autre bucket, puis contrôler l'audit unique après succès ; - créer 100 véhicules ambiants et contrôler format/style, absence de collision et
resmon; - enregistrer un véhicule proche et vérifier l'absence de
No such export describeTarget; dans une recette contrôlée, arrêtermedusa-vehicleset vérifier une erreur F10 propre sansFailed to fetchnon géré ; - créer puis déplacer un serrurier avec deux modèles valides et vérifier son apparition sans reconnexion sur les deux clients ;
- rejouer U, clé inventaire, G/Z, délai moteur 60 s, serrurier, GPS/TP et restauration.
- ouvrir Administration > Garages, déplacer un rond puis ajouter et déplacer une sortie ;
annuler une fois avec Retour/Échap puis confirmer avec
E, et vérifier sur les deux clients que seule la cible a changé et que son UUID est resté identique ; - réserver une sortie, rejouer une ancienne révision et tenter de supprimer la dernière sortie active d'un garage actif : les trois actions sont refusées sans état partiel ;
- tester enregistrement, transfert et réinitialisation de clés avec joueurs connectés, personnage
hors ligne, homonyme et groupe : les connectés portent
Prénom Nom (ID serveur), aucun UUID n'est visible et une valeur falsifiée est refusée côté serveur ; - provoquer plaque invalide/dupliquée, permission refusée, erreur garage et indisponibilité API : une bannière française typée apparaît dans F10, tout en conservant les traces F8/F9 ;
- vérifier qu'aucune carte véhicule ne contient SCANNER et que l'unique action supérieure Identifier le véhicule proche distingue dossier enregistré, plaque ambiante et absence de cible.
Résultat attendu : aucune donnée technique dans la NUI, aucun fond noir, aucune double transition, et des erreurs françaises explicites. La validation des coordonnées en jeu ne peut pas être remplacée par les tests statiques locaux.
Recette MED-20260827-001¶
Révision corrective des libellés et du backdrop¶
- Sans aucune affectation, ouvrir F10 puis le web : chaque carte ORIGINAL doit afficher
REPLI AUTOMATIQUEet0 affectation(s) explicite(s). Confirmer avec un véhicule sans règle qu'il résout toujours ORIGINAL. - Affecter SPORT à un véhicule personnage puis à un véhicule groupe. Vérifier modèle, plaque,
PROPRIÉTAIRE : Prénom NomouGROUPE : Nomdans F10 et le web. Rechercher successivement par modèle, plaque et nom ; rechercher un fragment de l'UUID ne doit rien retourner. - Ouvrir la confirmation ORIGINAL : elle reprend le libellé métier, mais la requête conserve
scope, cible interne et révision. Une fixture orpheline contrôlée affiche
VÉHICULE INDISPONIBLE, jamais sa clé technique. - Avant la connexion au serveur, puis après cinq cycles serrurier, garage, Alt et F5, contrôler 1280×720, 1920×1080 et ultrawide. Les quatre coins et le centre hors panneau doivent montrer le monde, et Échap/fermeture/stop de ressource doivent rendre focus et curseur au jeu.
- Exécuter
node --test tests/nui-transparency.test.mjsdepuisfivem/. Le test doit refuser une fixture aveccolor-scheme:darkou une racine opaque, accepter le loading screen et passer sur toutes lesui_pagecourantes.
Révision corrective F5, sièges et Alt¶
Cette recette runtime est obligatoire pour fermer REV-F5-001 à REV-TARGET-002 ; les tests de
contrat Node ne remplacent pas les natives FiveM.
- Dans un véhicule compatible, ouvrir F5 puis déplacer rapidement la souris sur les deux axes et
utiliser la molette. La vue, la caméra cinématique et la station radio ne doivent jamais changer.
Sans fermer F5, vérifier direction, accélération, freinage, frein à main et sortie au clavier puis
à la manette. Fermer successivement par F5, Échap, bouton, sortie, mort, despawn, autre NUI et
restart de
medusa-vehicles; caméra, radio, curseur et commandes doivent être immédiatement rendus, sans double fermeture. Cela couvreREV-F5-001etREV-F5-002. - Avec deux clients, sélectionner successivement chaque place libre d'une 2 portes, 4 portes puis
d'une grande cabine. Attendre dix secondes sur chaque siège avec le conducteur libre : le joueur
doit rester exactement sur l'index choisi. Faire occuper la place au dernier moment, lancer deux
demandes concurrentes, sortir, mourir, despawner puis redémarrer la ressource pendant la
transition. Aucun occupant ne doit être éjecté, aucun échec ne doit déplacer au conducteur et la
tentative suivante doit fonctionner. Cela couvre
REV-SEAT-001etREV-SEAT-002. - À pied, maintenir Alt gauche près d'un véhicule puis déplacer le curseur : caméra et roue native
doivent rester fixes. Cliquer à gauche le véhicule sous le pointeur à moins de 3 m ; le panneau
extérieur doit s'ouvrir. Répéter avec plusieurs véhicules proches, un obstacle, hors portée,
relâchement Alt, Échap, clic droit, mort et disparition de la cible. Redémarrer ensuite
medusa-interactionssans redémarrermedusa-vehicleset recommencer : le fournisseur doit se réinscrire. Une inscription volontairement refusée doit produire un message visible, pas seulement une ligne F8. Cela couvreREV-TARGET-001etREV-TARGET-002. - Remapper F5 et l'interaction ciblée dans les options FiveM, puis rejouer les trois parcours. Les actions U, G, TAB, E garages et E serrurier doivent rester inchangées.
Révision Alt extérieur définitive et lisibilité handling¶
Les contrôles Node/Playwright valident le contrat et la présentation, mais le contour et les natives de focus doivent encore être constatés dans FiveM avant de fermer les critères runtime.
- Ouvrir F10 puis Medusa Admin web aux largeurs 360, 768, 1280 et 1920 px. Vérifier les titres Profils disponibles, Profils appliqués et Base ORIGINAL des véhicules. Une affectation SPORT doit porter PROFIL APPLIQUÉ. Chaque source montre modèle, famille, provenance et état français sans chemin ni empreinte dans le résumé.
- Ouvrir Détails techniques au clavier puis à la souris. Vérifier que nom de handling,
ressource, chemin, empreinte complète, date, révision et diagnostic sont lisibles, sélectionnables
et copiables. Rechercher successivement
GTA / FiveM,Détectée en jeu, un chemin, une empreinte et un diagnostic ; chaque recherche doit retrouver la même carte. Une source absente, invalide ou ambiguë doit rester signalée sans ouvrir le détail. - Dans FiveM, à pied et à moins de 3 m, maintenir Alt puis viser avec le curseur un véhicule
enregistré vide, le même véhicule occupé, puis un véhicule PNJ. Le contour turquoise doit suivre
exactement le véhicule visé à 16:9 et en ultrawide. Répéter immédiatement après son streaming ou
un redémarrage de
medusa-vehicles: une réplication tardive peut retarder brièvement le contour, jamais le désactiver durablement. - Cliquer une fois puis double-cliquer rapidement : un seul panneau extérieur doit s'ouvrir pour
le même véhicule. Le panneau garde son focus après relâchement Alt ; Échap ou sa fermeture le
rend ensuite au jeu. Rejouer après redémarrage de
medusa-interactionssans redémarrermedusa-vehicles. - Tester successivement hors véhicule, hors portée, cible disparue entre contour et clic, flag
VEHICLE_CONTROL_MENUS_ENABLED=false, train et véhicule spécial. Aucun panneau ne doit s'ouvrir. Après un clic refusé, un message français avec un codeALT-…doit apparaître à l'écran. Simuler enfin une panne du callback CEF : elle doit produire le même type de retour visible. - Avec le debug actif, observer F8 pendant tous les parcours : seules les transitions mode, raycast, candidat, sélection et focus sont journalisées. Une visée immobile ne doit jamais produire une ligne par frame.
Les tests automatisés associés sont interactions-target-ui.test.mjs, les contrats cible de
vehicle-regression.test.mjs et admin/tests/vehicles.spec.js. La preuve finale de
REV-TARGET-003 à REV-TARGET-005 exige néanmoins une capture ou un log de cette recette FiveM.
Références Cfx du fournisseur Alt¶
Le test target-provider-callbacks.test.mjs reproduit la forme reçue à la frontière Cfx : une
table portant __cfx_functionReference et un appel métatable. Il vérifie les fonctions locales,
les doubles Cfx, le refus des tables ordinaires/callbacks absents, les exceptions protégées,
l'appel unique de resolve et action, puis unregister/réinscription sans doublon. Il interdit
aussi le retour de type(options.resolve) ~= 'function' et de la condition stricte historique sur
provider.action. Cela couvre la preuve locale T-TARGET-CFXREF-001.
La preuve runtime T-TARGET-PROVIDER-BOOT-001 reste obligatoire :
- Activer temporairement le debug de
medusa-interactions, démarrer les ressources et vérifier dans F8resource_loaded | version=1.7.4, puistarget_provider_registered | id=medusa-vehicles. - Maintenir Alt près d'un véhicule enregistré :
target_modedoit annoncerproviders=1, le raycast terminer avectype=2, le contour turquoise apparaître et un clic ouvrir exactement un panneau. - Répéter sur un véhicule PNJ, avec les mêmes résultats et sans
inscription refusée. - Redémarrer uniquement
medusa-interactions, attendre la réinscription automatique et rejouer les deux parcours. Le registre doit toujours annoncer un seul fournisseur et une seule action par clic, sans focus, curseur ou contour résiduel après fermeture. - Remettre le debug à sa valeur d'exploitation après avoir conservé le log ou la capture de preuve.
Automatisation obligatoire¶
Set-Location api
.\.venv\Scripts\python.exe -m pytest tests/test_vehicle_handling.py tests/test_vehicle_compartments.py tests/test_vehicles.py tests/test_vehicle_garages.py tests/test_inventories.py tests/test_inventory_drops.py tests/test_inventory_storages.py tests/test_permissions.py tests/test_system.py -q -p no:cacheprovider
Set-Location ..\fivem
npm test
Set-Location ..\admin
npm run test:e2e
Set-Location ..
node .agents/scripts/refresh-context.mjs --check
node .agents/scripts/validate-domain-context.mjs
git diff --check
Sur une stack PostgreSQL de test, ajouter obligatoirement :
docker compose exec api alembic upgrade head
docker compose exec api alembic check
docker compose exec api ruff check app tests
docker compose exec api pytest
Matrice des 77 critères¶
| Critères | Preuve automatisée minimale | Preuve runtime obligatoire |
|---|---|---|
AC-001–AC-005 |
extracteur/fixtures, priorité, profils, versions, preview | comparaison vanilla/realistic/custom avant-après, annulation/restart |
AC-006–AC-013 |
transferts, capacités, sessions, PNJ, conversion et rollback | TAB extérieur/intérieur à deux clients sur classes représentatives |
AC-014–AC-024 |
contrats Alt/F5, actions, rate limits, réservations/replay | raycast, ouvrants, chaque siège, moteur G/F5/Accélérer et concurrence |
AC-025–AC-033 |
ORIGINAL sans dérive, sources, empreintes, diagnostics/export | application successive puis ORIGINAL sur terre/mer/air |
AC-034–AC-052 |
lifecycle, suppression, explosion, notifications, warning clé | garage/fourrière/despawn/explosion réelle et sessions partagées |
AC-053–AC-062 |
permissions, bornes, absence handling NUI, Playwright responsive | rôles unitaires, AZERTY remappé, souris et manette |
AC-063–AC-077 |
migration paresseuse, flags x8, idempotence, redaction | restart, pannes API/DB/Redis, 48 joueurs/100 véhicules et p95 |
Chaque AC reçoit dans le plan une preuve nommée, une capture/log/hash runtime ou reste non coché. Les tests statiques de contrats ne prouvent ni les natives FiveM, ni la latence, ni un essai à deux clients.
Parcours runtime à deux clients¶
- Sauvegarder PostgreSQL, appliquer 0033 et confirmer le head/readiness.
- Tester sans affectation un vanilla, un
realistic-handling, chacun des six customs et un modèle nouvellement ajouté ; comparer les valeurs avant/après puis revenir à ORIGINAL. - Affecter successivement catégorie, modèle et UUID ; changer plaque/propriétaire, ranger, sortir, restaurer et redémarrer. La priorité et l'UUID doivent rester identiques.
- Ouvrir coffre par TAB à pied, boîte à gants par TAB sur les deux sièges avant et vérifier le fallback personnel aux sièges arrière. Tester verrou, 2/5 km/h, 4/4,25 m et hayon arraché. Refaire avant/après rangement-sortie de garage, après restauration et après chaque ordre de restart Inventaire/Véhicules. Avec les flags actifs mais les capacités retirées en recette, plusieurs appuis rapprochés doivent produire une seule réparation bornée, un message visible et jamais l'ouverture silencieuse du personnel sur la cible réelle.
- Mettre du contenu dans un PNJ, enregistrer l'entité puis répéter avec une capacité trop petite ; le premier contenu migre, le second reste intégralement temporaire.
- À deux clients, muter le même slot et viser le même siège. Un seul gagnant est accepté, sans duplication, éjection ni réservation orpheline.
- Tester Alt+clic et F5 sur 2 portes, 4 portes, moto, bateau, hélicoptère, avion et grande cabine ; vérifier portes/vitres/capot/coffre/feux, dégâts et permissions par siège.
- Arrêter le moteur par G puis F5, essayer Accélérer avant/après 60 s et redémarrer immédiatement par G/F5. Changer de siège pendant chaque état.
- Provoquer panne, feu, moteur à
-4000, streaming, despawn et enfin explosion confirmée. Seule l'explosion commitée purge exactement une fois. - Tester les huit combinaisons de flags, puis interrompre API, DB et Redis séparément. Aucun faux succès, replay destructif ou surface fantôme ne doit apparaître.
- Mesurer avec 48 joueurs/100 véhicules : API p95 sous 500 ms, pages de 50, aucun scan/raycast/API par frame et aucun état résiduel après fermeture/stop.
Recette MED-20260830-002 — retrait du régulateur et placement du compteur¶
Vérifications automatisées¶
Depuis api/ :
..\.venv\Scripts\python.exe -m pytest tests/test_speedometer_placement_migration.py tests/test_vehicle_preferences.py tests/test_vehicles.py tests/test_system.py tests/test_vehicle_handling.py tests/test_vehicle_compartments.py tests/test_vehicle_garages.py tests/test_inventories.py tests/test_inventory_drops.py tests/test_inventory_storages.py tests/test_permissions.py -q -p no:cacheprovider
..\.venv\Scripts\python.exe -m alembic heads
..\.venv\Scripts\python.exe -m alembic upgrade 0035_speedometer_cruise_v2:0036_speedometer_placement --sql
Depuis fivem/ :
npm test
node --test tests/vehicle-speedometer.test.mjs tests/vehicle-regression.test.mjs tests/nui-transparency.test.mjs
La suite vérifie notamment contrat v3, valeurs finies, pas de 5, UUID/idempotence/révision, 48 comptes en smoke SQLite, les 16 combinaisons de flags API, la syntaxe Lua, l'absence totale du runtime/mapping/callback/flag de régulateur, le masque d'entrées du placement et le garde-fou global de transparence. Elle impose aussi l'identité byte-à-byte des trois YTD, des trois Lua et de la licence, les hashes des six exports F5, les trois thèmes stricts, le renderer natif sans MPH ni runtime/commande/KVP/son amont et l'absence de SVG de substitution. Le SQL hors ligne et le smoke SQLite ne prouvent ni l'upgrade PostgreSQL réel ni son p95 de 500 ms.
Recette FiveM obligatoire¶
- Sur une copie PostgreSQL au head 0035 contenant
small,normaletlarge, appliquer 0036 et vérifier 80/100/120,(0.5,0.8), head unique, contraintes, ownership, timestamps et secondupgrade headsans mutation. - Avec deux comptes et deux personnages d'un même compte, appliquer CLASSIC, D6 STREET et D7 RACING à 60/100/140 %, plusieurs positions et les modes Automatique/Jour/Nuit. Reconnecter, changer de personnage et redémarrer API/HUD/véhicules : les cinq dimensions restent account-wide et l'autre compte est isolé.
- Ouvrir le placement à 0, 1 et 1,1 km/h, conducteur/passager, mort, pause et entité absente. Seul le conducteur à 1 km/h ou moins obtient l'éditeur ; chaque refus explique la cause sans focus.
- Tester drag, molette, slider, boutons ±5 %, flèches 0,25 %,
Maj1 %,Ctrlanti-snap, Recentrer et reset complet confirmé/non confirmé. Refaire à la manette avec stick, croix, épaules, modificateur et appliquer/annuler, puis débrancher/rebrancher la manette. - Pour chaque thème à 60/100/140 %, placer aux quatre bords en 1280×720, 1920×1080, 16:10, 21:9 et 32:9 avec safe zone minimale/maximale. Changer résolution à chaud : le rendu se borne sans PATCH, puis retrouve la position désirée au retour.
- Annuler/fermer puis invalider par accélération, siège, sortie, mort, pause, flag off et restart HUD/véhicules. Aucun PATCH ne part, l'aperçu masqué disparaît et aucun focus/contrôle ne reste bloqué. Provoquer 400/409/503/timeout/réseau et réponses réordonnées : le brouillon et la cause restent récupérables, sans faux succès.
- Vérifier que
K, Page précédente et Page suivante n'ont plus de mapping ni d'effet. Parcourir les quatre combinaisons compteur/F5 et tester séparément U, G, délai Accélérer 60 s, Alt+clic, TAB/coffre/boîte à gants, ouvrants, vitres, sièges, handling, garages et serrurier.
Mesure de performance¶
Sur le serveur de recette, simuler 48 sessions GET/PATCH sur PostgreSQL et conserver p50/p95,
erreurs, doublons et conflits ; attendu p95 <500 ms hors panne et une seule ligne/requête. Mesurer
medusa-vehicles pendant 60 s éditeur fermé : delta moyen ≤0,10 ms. Pendant un drag à 30/60/144 FPS,
vérifier zéro API/événement réseau/log par mouvement, maximum 20 snapshots/s et aucune croissance de
file ou mémoire.
Régression avec énergie¶
La matrice U/G, clés, serrurier, Alt, TAB, sièges, handling, garages et speedmeters doit être rejouée avec les seuils énergie. Voir Tests du système énergie.
Course des compartiments MED-20260904-001¶
Exécuter node --test tests/vehicle-compartment-runtime.test.mjs tests/vehicle-regression.test.mjs.
En jeu, ouvrir puis fermer vingt fois rapidement un coffre, puis une boîte à gants. Fermer pendant le
tick de surveillance, puis enchaîner immédiatement coffre A vers boîte à gants ou coffre B. Le
nouveau contexte doit rester ouvert et F8 ne doit jamais contenir activeCompartment nil. Terminer
par un cycle normal et provoquer successivement distance, vitesse, verrouillage et départ d’un siège
avant : chaque sécurité doit encore fermer uniquement le compartiment courant, sans spam.