test: pin the surviving marked-t keys and document the known test limits (#437) #473

Open
maximus wants to merge 3 commits from issue-437-test-pins into issue-393-category-hierarchy
Owner

Resolves #437
Generated autonomously by /autopilot run of 2026-10-18

Résumé

Maillon 6 sur 8 de la pile planned-2026-10-16-lot-v018, basé sur issue-393-category-hierarchy (PR #472). Restes non bloquants des revues de la pile #433 à #436 : relecture des cinq commits de suivi appliqués sans relecture, épingles manquantes, limites documentées. Aucun changement de comportement : des tests, des commentaires et de la documentation (un commentaire de db.ts compris), aucune entrée de CHANGELOG, aucune clé i18n.

Partie 1 — Relecture des cinq commits de suivi

Chaque diff lu contre son message et contre les revues 23505 (#433), 23495 (#434), 23499 (#435), 23511 (#436) et les suivis 23535, 23550. Les mutations du relecteur, rejouées ici sur la suite complète (R1 à R13, tableau plus bas), sont toutes rouges.

74fae14 — fix(db): follow-ups of the review of PR #433 : relu, rien à signaler. Le diff règle S1, S2, S3, S4 et S5 de la revue 23505 comme le dit son message : close() d'un handle de getDb() passe par une section connection close et vérifie sa génération ; closeUnlocked vide l'état et incrémente la génération avant close(), et un échec part au Journal par logWarn(withoutFolders(…)) sans rejeter ; l'alerte de blocage parle de cause possible ; le contrôle de génération du handle de transaction est commenté comme une défense inatteignable. Vérifié en plus : les deux appelants de closeDb() (switchProfile et deleteProfile de ProfileContext) enchaînent connectToProfile, qui ouvre maintenant le profil suivant même si l'ancien pool refuse de se fermer ; logWarn ne peut pas lever (sessionStorage sous try) ; le test « behind the queue » place bien la vérification entre deux opérations (sa réaction then est enregistrée après celle de la file).

a1c31a1 — test(harness): follow-ups of the review of PR #434 : relu, rien à signaler. Le test « a route change during the 150 ms wait… » épingle les dépendances du suiveur (M1 de la revue 23495, rejouée en R5 : rouge) ; le test de longueur du tableau de dépendances épingle la branche de depsChanged (M8, rejouée en R6 : rouge). La phrase « NOT SIMULATED » est exacte : le dispatch est créé une fois (writer, ??=) avec le reducer du premier rendu. « Un reducer défini au niveau du module, seul cas utilisé » reste vrai sur la base : les reducers des hooks passés au harnais (useOnboardingChecklist, useCategories, useAdjustments, useBudget) sont tous au niveau du module.

ac3a981 — test(i18n): follow-ups of the review of PR #435 : relu, rien à signaler. renderCategoryLabel.test.ts passe markedT et asserte la forme marquée ; la garde reconnaît t = (, t = vi.fn( et t: vi.fn(, ancrés sur une frontière de mot (t === ( et const at = ( restent propres), et exige un appel i18nMock( hors commentaires. Les faux positifs possibles (un // dans une chaîne coupe la ligne ; const t = (await …) serait refusé) rougissent la garde, ils ne la font jamais passer à tort.

86eff9b — fix(profiles): follow-ups of the review of PR #436 : code conforme à son message ; trois défauts de documentation, corrigés ici sans toucher au code. R10 à R12 rouges (R12, l'ancienne règle « un blanc termine les dossiers », fait rougir 18 tests).

  1. Le commentaire de withoutFolders disait « a closing parenthesis », alors que le code ne s'arrête qu'à une parenthèse fermante non suivie d'un séparateur (comme le disent le message du commit et l'ADR). Corrigé, avec un renvoi à l'ADR 0021.
  2. L'ADR 0021 § 7 écrivait qu'un chemin relatif sans début reconnu « n'a que ses séparateurs remplacés par - ». Faux pour un morceau qui porte deux séparateurs ou plus, réduit à son dernier segment (sonde : dossier/sous/x.db donne x.db) ; seuls les mots d'un dossier qui contient un blanc restent (dossier/sous dossier/x.db donne dossier-sous dossier-x.db). Phrase précisée.
  3. Une conséquence des arrêts n'était écrite nulle part : un nom de dossier qui contient l'un des arrêts coupe le chemin là, et ce nom, ou son début, reste dans la ligne (sondes : C:\Users\Jean (Work) Smith\AppData\x.db donne Jean (Work) x.db ; C:\Users\jean\My;Docs\x.db donne My;Docs-x.db ; une apostrophe inverse dans le nom fait de même). Écrite comme seconde limite dans l'ADR 0021 § 7. Pas de correctif de code : séparer (see /x/y.db) and… de Jean (Work) Smith\ serait une autre heuristique, et l'issue exclut tout changement de comportement. À Max de dire s'il veut une issue de suivi.

L'arrêt \r n'avait pas de test propre (déjà admis par 23535) : épinglé en partie 2.

c17bf5d — fix(balance): translate the best-effort badge of the price fetch button : relu, rien à signaler. Le badge passe par t("balance.priceFetching.bestEffortBadge") (« non garanti », décision de Max du 2026-10-16), clé présente dans les deux langues, entrée Corrigé / Fixed dans les deux CHANGELOG (publiée dans la v0.17.2). R13 (littéral remis) : rouge.

Partie 2 — Épingles

Clés lues sur la base 8a9d990 (#369 et #429 ont touché TransactionTable.tsx) ; chemins corrigés par le plan, pas transactions.table.*.

Clé Test Assertion
arrêt \r src/services/db.test.ts ["\r"] ajouté à l'it.each « withoutFolders ends the folders at %j »
transactions.transferIcon.ariaLabel TransactionTable.render.test.tsx aria-label="t(transactions.transferIcon.ariaLabel)", une seule fois, sur la ligne liée à un transfert (le helper markup prend linkedTransfersByTxId)
transactions.notes.placeholder TransactionTable.render.test.tsx title="t(transactions.notes.placeholder)" sur le bouton de notes de chaque ligne (toujours rendu, choix du plan)
même clé, second appel TransactionTable.wiring.test.ts un clic sur un bouton de notes, trouvé dans l'arbre rendu, ouvre une seule textarea, dont le placeholder vaut t(transactions.notes.placeholder)
license.keyPlaceholder LicenseKeyForm.render.test.tsx placeholder="t(license.keyPlaceholder)"
license.activate LicenseKeyForm.render.test.tsx <button type="submit" …>t(license.activate)</button>
balance.priceFetching.consent.accept PriceFetchControl.test.tsx fenêtre de consentement fermée par défaut, ouverte par l'emplacement 0 préréglé (showConsentModal) ; >t(balance.priceFetching.consent.accept)<, plus le titre, le texte et « Refuser » de la même fenêtre
dashboard.kpiSectionTitle DashboardPage.render.test.tsx >t(dashboard.kpiSectionTitle)<

PriceFetchControl se prête au préréglage : aucune clé déclarée non épinglable.

Partie 3 — Limites documentées

  • Commentaire sur la dépendance à l'ordre des hooks (tout hook ajouté avant décale les emplacements sans rien dire ; renvoi au helper slot de fakeReact, src/test/hookHarness.ts) à chaque préréglage : markup() de PriceFetchConsentToggle.test.tsx, mountWith de useOnboardingChecklist.wiring.test.ts (qui couvre aussi ses deux écritures directes de harness.slots[0]), le nouveau markup() de PriceFetchControl.test.tsx, et le premier préréglage de SystemsSettingsPage.test.tsx (ajouté par #372 dans cette pile).
  • docs/architecture.md, fin de la section Tests : « Limites connues (#437) ». Les emplacements préréglés sont écrits en entier (nulle part avant) ; withoutFolders et la mesure du rattrapage renvoient à l'ADR 0021 (§ 7, et le point « Le délai de démarrage couvre le rattrapage du profil actif »), qui les portaient déjà : 306 ms, SSD NVMe et risque d'un disque lent ou d'un antivirus ne sont pas recopiés. Ajouté seulement ce que l'ADR ne dit pas : le test #[ignore] ne tourne pas en CI et n'asserte rien.
  • ADR 0021 § 7 : les deux limites de withoutFolders (défauts 2 et 3 de la partie 1).

Fichiers

Fichier Changement
src/services/db.test.ts arrêt \r
src/services/db.ts commentaire de withoutFolders seulement
src/components/transactions/TransactionTable.render.test.tsx 2 tests, paramètre linkedTransfersByTxId du helper
src/components/transactions/TransactionTable.wiring.test.ts 1 test (ligne de notes), en-tête
src/components/settings/LicenseKeyForm.render.test.tsx 1 test ; en-tête « t echoes its key » corrigé
src/components/balance/PriceFetchControl.test.tsx harnais (vi.mock("react")), helper markup, 1 test ; en-tête périmé corrigé
src/pages/DashboardPage.render.test.tsx 1 test
src/components/settings/PriceFetchConsentToggle.test.tsx commentaire
src/hooks/useOnboardingChecklist.wiring.test.ts commentaire
src/pages/settings/SystemsSettingsPage.test.tsx commentaire
docs/architecture.md « Limites connues (#437) »
docs/adr/0021-migrations-profils-secondaires.md § 7 : deux limites

Décisions

13 décisions : 7 HIGH, 6 MEDIUM, 0 LOW (détail dans le journal de décisions du run).

  • [MEDIUM] Le mock de react par le harnais va dans PriceFetchControl.test.tsx, le fichier que nomme l'issue, et le rendu existant passe par le même helper markup() (harness.render), comme PriceFetchConsentToggle.test.tsx : sous un mock de fichier, un rendu JSX par react-dom/server appellerait les hooks du harnais sans remise à zéro du curseur. Écartés : un fichier de test à part ; garder le rendu JSX avec un simple harness.clear().
  • [MEDIUM] Les quatre textes de la fenêtre de consentement sont épinglés, pas seulement « Accepter » : aucun test ne rendait la fenêtre, donc les quatre étaient libres ; trois assertions de plus, chaque mutation rouge (M6b à M6d).
  • [MEDIUM] Clé des notes : le plan épingle le title du bouton ; le second appel (placeholder de la textarea) l'est aussi, dans TransactionTable.wiring.test.ts (créé par #369 après le plan), par un clic dans l'arbre rendu, sans emplacement préréglé. La revue 23499 ne dit pas lequel des deux appels elle avait muté.
  • [MEDIUM] Commentaire d'ordre des hooks aussi dans SystemsSettingsPage.test.tsx (même décalage silencieux) ; OnboardingStepCard.test.tsx ne fait que lire l'emplacement 0 et dit déjà « its first hook » : cité dans architecture.md, pas commenté.
  • [MEDIUM] architecture.md : section ajoutée en fin de « Tests », renvois à l'ADR 0021 plutôt que recopie.
  • [MEDIUM] 86eff9b : défauts de documentation corrigés, la seconde limite écrite, aucun changement du code ni test qui fige la fuite.
  • [HIGH] Préflight passé (#369, #419, #421 fermées, tag v0.17.2) ; chemins des clés lus sur la base ; verdicts de la partie 1 ; en-têtes périmés de LicenseKeyForm.render.test.tsx et (auto-revue) de PriceFetchControl.test.tsx corrigés ; pas de CHANGELOG ; niveau normal ; formulation de la seconde limite généralisée à tout arrêt dans un nom de dossier (sonde My;Docs).

Preuves

Passe de mutations par script à table, une mutation à la fois, suite complète (152 fichiers) à chaque fois, restauration par git checkout -- et arbre vérifié propre après chacune ; jouée après le commit des tests.

Épingles de cette PR (rouges attendues : le test du composant)

# Fichier Mutation Tests rouges rc
M1 src/services/db.ts \r retiré de PATH_STOP 1 (db.test.ts) 1
M2 TransactionTable.tsx aria-label de l'icône de transfert sans t 1 (TransactionTable.render.test.tsx) 1
M3 TransactionTable.tsx title du bouton de notes sans t 2 (render et wiring) 1
M3b TransactionTable.tsx placeholder de la textarea de notes sans t 1 (TransactionTable.wiring.test.ts) 1
M4 LicenseKeyForm.tsx placeholder du champ sans t 1 (LicenseKeyForm.render.test.tsx) 1
M5 LicenseKeyForm.tsx texte du bouton d'envoi sans t 1 (LicenseKeyForm.render.test.tsx) 1
M6 PriceFetchControl.tsx consent.accept sans t 1 (PriceFetchControl.test.tsx) 1
M6b PriceFetchControl.tsx consent.title sans t 1 1
M6c PriceFetchControl.tsx consent.body sans t 1 1
M6d PriceFetchControl.tsx consent.decline sans t 1 1
M7 DashboardPage.tsx dashboard.kpiSectionTitle sans t 1 (DashboardPage.render.test.tsx) 1
M8 PriceFetchControl.tsx un useState ajouté avant showConsentModal (décalage des emplacements) 1 (le test de la fenêtre : le décalage est bruyant ici) 1

Mutations rejouées des cinq commits relus

# Commit Mutation Tests rouges rc
R1 74fae14 close() d'un handle de getDb() sans contrôle de génération 1 1
R2 74fae14 closeUnlocked relance l'échec du close() 2 1
R3 74fae14 lockHolder jamais remis à null 1 1
R4 74fae14 échec du close() écrit sans withoutFolders 1 1
R5 a1c31a1 pathname dans les dépendances du suiveur (M1 de 23495) 1 1
R6 a1c31a1 branche de longueur de depsChanged retirée (M8 de 23495) 1 1
R7 ac3a981 garde réduite à la règle t: ( 1 1
R8 ac3a981 le nom i18nMock suffit (commentaires compris) 1 1
R9 ac3a981 renderCategoryLabel sans t 6 1
R10 86eff9b une ) n'arrête jamais un chemin 1 1
R11 86eff9b pas d'arrêt au chemin suivant 2 1
R12 86eff9b un blanc termine les dossiers (comportement de fbecfff) 18 1
R13 c17bf5d badge remis au littéral best-effort 1 1

Comptes

  • vitest : 152 fichiers, 2465 tests verts (+7 tests, aucun fichier ajouté) ; npm run build vert (tsc + vite).
  • Sonde : rc=1 (src/zz_tmp_probe.test.ts, un expect rouge, supprimée).
  • Rust : non touché, pas de cargo test.

Vérifications manuelles dues (prochaine release)

Aucune : la PR ne change ni comportement ni texte visible.

Pour le relecteur

  • Trois commits : les épingles (test:), les commentaires et la documentation (docs:), puis une correction d'auto-revue (docs:, en-tête de PriceFetchControl.test.tsx qui disait encore tout rendu React contourné).
  • license.activate est aussi appelée par le bouton « Activer » de la section Machines (LicenseCard.tsx) : déjà épinglée sous forme marquée (sonde : t retiré là, 2 tests rouges dans LicenseCard.render.test.tsx).
  • PriceFetchControl.test.tsx est maintenant entièrement sous le harnais (mock de react au niveau du fichier) ; les describes qui ne rendent rien n'en sont pas affectés, et le test de rendu existant garde ses six assertions telles quelles.
  • La liste « Utilisateurs » du harnais dans architecture.md était déjà incomplète avant cette PR (TransactionTable.wiring, AdjustmentForm.wiring, LinkTransfersModal.wiring, HierarchyCheckModal.wiring, useAdjustments, useCategories, ChangelogContent, SystemsSettingsPage, ProfileFormModal.delete n'y figurent pas) ; non mise à jour ici, hors périmètre ; PriceFetchControl.test.tsx s'y ajoute.
  • Seconde limite de withoutFolders (défaut 3 de la partie 1) : documentée, pas corrigée ; une issue de suivi est à décider.

🤖 Generated with Claude Code

Resolves #437 Generated autonomously by /autopilot run of 2026-10-18 ## Résumé Maillon 6 sur 8 de la pile `planned-2026-10-16-lot-v018`, basé sur `issue-393-category-hierarchy` (PR #472). Restes non bloquants des revues de la pile #433 à #436 : relecture des cinq commits de suivi appliqués sans relecture, épingles manquantes, limites documentées. **Aucun changement de comportement** : des tests, des commentaires et de la documentation (un commentaire de `db.ts` compris), aucune entrée de CHANGELOG, aucune clé i18n. ## Partie 1 — Relecture des cinq commits de suivi Chaque diff lu contre son message et contre les revues 23505 (#433), 23495 (#434), 23499 (#435), 23511 (#436) et les suivis 23535, 23550. Les mutations du relecteur, rejouées ici sur la suite complète (R1 à R13, tableau plus bas), sont toutes rouges. **`74fae14` — `fix(db): follow-ups of the review of PR #433` : relu, rien à signaler.** Le diff règle S1, S2, S3, S4 et S5 de la revue 23505 comme le dit son message : `close()` d'un handle de `getDb()` passe par une section `connection close` et vérifie sa génération ; `closeUnlocked` vide l'état et incrémente la génération avant `close()`, et un échec part au Journal par `logWarn(withoutFolders(…))` sans rejeter ; l'alerte de blocage parle de cause possible ; le contrôle de génération du handle de transaction est commenté comme une défense inatteignable. Vérifié en plus : les deux appelants de `closeDb()` (`switchProfile` et `deleteProfile` de `ProfileContext`) enchaînent `connectToProfile`, qui ouvre maintenant le profil suivant même si l'ancien pool refuse de se fermer ; `logWarn` ne peut pas lever (`sessionStorage` sous `try`) ; le test « behind the queue » place bien la vérification entre deux opérations (sa réaction `then` est enregistrée après celle de la file). **`a1c31a1` — `test(harness): follow-ups of the review of PR #434` : relu, rien à signaler.** Le test « a route change during the 150 ms wait… » épingle les dépendances du suiveur (M1 de la revue 23495, rejouée en R5 : rouge) ; le test de longueur du tableau de dépendances épingle la branche de `depsChanged` (M8, rejouée en R6 : rouge). La phrase « NOT SIMULATED » est exacte : le `dispatch` est créé une fois (`writer`, `??=`) avec le reducer du premier rendu. « Un reducer défini au niveau du module, seul cas utilisé » reste vrai sur la base : les reducers des hooks passés au harnais (`useOnboardingChecklist`, `useCategories`, `useAdjustments`, `useBudget`) sont tous au niveau du module. **`ac3a981` — `test(i18n): follow-ups of the review of PR #435` : relu, rien à signaler.** `renderCategoryLabel.test.ts` passe `markedT` et asserte la forme marquée ; la garde reconnaît `t = (`, `t = vi.fn(` et `t: vi.fn(`, ancrés sur une frontière de mot (`t === (` et `const at = (` restent propres), et exige un appel `i18nMock(` hors commentaires. Les faux positifs possibles (un `//` dans une chaîne coupe la ligne ; `const t = (await …)` serait refusé) rougissent la garde, ils ne la font jamais passer à tort. **`86eff9b` — `fix(profiles): follow-ups of the review of PR #436` : code conforme à son message ; trois défauts de documentation, corrigés ici sans toucher au code.** R10 à R12 rouges (R12, l'ancienne règle « un blanc termine les dossiers », fait rougir 18 tests). 1. Le commentaire de `withoutFolders` disait « a closing parenthesis », alors que le code ne s'arrête qu'à une parenthèse fermante non suivie d'un séparateur (comme le disent le message du commit et l'ADR). Corrigé, avec un renvoi à l'ADR 0021. 2. L'ADR 0021 § 7 écrivait qu'un chemin relatif sans début reconnu « n'a que ses séparateurs remplacés par `-` ». Faux pour un morceau qui porte deux séparateurs ou plus, réduit à son dernier segment (sonde : `dossier/sous/x.db` donne `x.db`) ; seuls les mots d'un dossier qui contient un blanc restent (`dossier/sous dossier/x.db` donne `dossier-sous dossier-x.db`). Phrase précisée. 3. Une conséquence des arrêts n'était écrite nulle part : un nom de dossier qui contient l'un des arrêts coupe le chemin là, et ce nom, ou son début, reste dans la ligne (sondes : `C:\Users\Jean (Work) Smith\AppData\x.db` donne `Jean (Work) x.db` ; `C:\Users\jean\My;Docs\x.db` donne `My;Docs-x.db` ; une apostrophe inverse dans le nom fait de même). Écrite comme seconde limite dans l'ADR 0021 § 7. Pas de correctif de code : séparer `(see /x/y.db) and…` de `Jean (Work) Smith\` serait une autre heuristique, et l'issue exclut tout changement de comportement. **À Max de dire s'il veut une issue de suivi.** L'arrêt `\r` n'avait pas de test propre (déjà admis par 23535) : épinglé en partie 2. **`c17bf5d` — `fix(balance): translate the best-effort badge of the price fetch button` : relu, rien à signaler.** Le badge passe par `t("balance.priceFetching.bestEffortBadge")` (« non garanti », décision de Max du 2026-10-16), clé présente dans les deux langues, entrée Corrigé / Fixed dans les deux CHANGELOG (publiée dans la v0.17.2). R13 (littéral remis) : rouge. ## Partie 2 — Épingles Clés lues sur la base `8a9d990` (#369 et #429 ont touché `TransactionTable.tsx`) ; chemins corrigés par le plan, pas `transactions.table.*`. | Clé | Test | Assertion | |---|---|---| | arrêt `\r` | `src/services/db.test.ts` | `["\r"]` ajouté à l'`it.each` « withoutFolders ends the folders at %j » | | `transactions.transferIcon.ariaLabel` | `TransactionTable.render.test.tsx` | `aria-label="t(transactions.transferIcon.ariaLabel)"`, une seule fois, sur la ligne liée à un transfert (le helper `markup` prend `linkedTransfersByTxId`) | | `transactions.notes.placeholder` | `TransactionTable.render.test.tsx` | `title="t(transactions.notes.placeholder)"` sur le bouton de notes de chaque ligne (toujours rendu, choix du plan) | | même clé, second appel | `TransactionTable.wiring.test.ts` | un clic sur un bouton de notes, trouvé dans l'arbre rendu, ouvre une seule `textarea`, dont le `placeholder` vaut `t(transactions.notes.placeholder)` | | `license.keyPlaceholder` | `LicenseKeyForm.render.test.tsx` | `placeholder="t(license.keyPlaceholder)"` | | `license.activate` | `LicenseKeyForm.render.test.tsx` | `<button type="submit" …>t(license.activate)</button>` | | `balance.priceFetching.consent.accept` | `PriceFetchControl.test.tsx` | fenêtre de consentement fermée par défaut, ouverte par l'emplacement 0 préréglé (`showConsentModal`) ; `>t(balance.priceFetching.consent.accept)<`, plus le titre, le texte et « Refuser » de la même fenêtre | | `dashboard.kpiSectionTitle` | `DashboardPage.render.test.tsx` | `>t(dashboard.kpiSectionTitle)<` | `PriceFetchControl` se prête au préréglage : aucune clé déclarée non épinglable. ## Partie 3 — Limites documentées - Commentaire sur la dépendance à l'ordre des hooks (tout hook ajouté avant décale les emplacements sans rien dire ; renvoi au helper `slot` de `fakeReact`, `src/test/hookHarness.ts`) à chaque préréglage : `markup()` de `PriceFetchConsentToggle.test.tsx`, `mountWith` de `useOnboardingChecklist.wiring.test.ts` (qui couvre aussi ses deux écritures directes de `harness.slots[0]`), le nouveau `markup()` de `PriceFetchControl.test.tsx`, et le premier préréglage de `SystemsSettingsPage.test.tsx` (ajouté par #372 dans cette pile). - `docs/architecture.md`, fin de la section Tests : « Limites connues (#437) ». Les emplacements préréglés sont écrits en entier (nulle part avant) ; `withoutFolders` et la mesure du rattrapage renvoient à l'ADR 0021 (§ 7, et le point « Le délai de démarrage couvre le rattrapage du profil actif »), qui les portaient déjà : 306 ms, SSD NVMe et risque d'un disque lent ou d'un antivirus ne sont pas recopiés. Ajouté seulement ce que l'ADR ne dit pas : le test `#[ignore]` ne tourne pas en CI et n'asserte rien. - ADR 0021 § 7 : les deux limites de `withoutFolders` (défauts 2 et 3 de la partie 1). ## Fichiers | Fichier | Changement | |---|---| | `src/services/db.test.ts` | arrêt `\r` | | `src/services/db.ts` | commentaire de `withoutFolders` seulement | | `src/components/transactions/TransactionTable.render.test.tsx` | 2 tests, paramètre `linkedTransfersByTxId` du helper | | `src/components/transactions/TransactionTable.wiring.test.ts` | 1 test (ligne de notes), en-tête | | `src/components/settings/LicenseKeyForm.render.test.tsx` | 1 test ; en-tête « `t` echoes its key » corrigé | | `src/components/balance/PriceFetchControl.test.tsx` | harnais (`vi.mock("react")`), helper `markup`, 1 test ; en-tête périmé corrigé | | `src/pages/DashboardPage.render.test.tsx` | 1 test | | `src/components/settings/PriceFetchConsentToggle.test.tsx` | commentaire | | `src/hooks/useOnboardingChecklist.wiring.test.ts` | commentaire | | `src/pages/settings/SystemsSettingsPage.test.tsx` | commentaire | | `docs/architecture.md` | « Limites connues (#437) » | | `docs/adr/0021-migrations-profils-secondaires.md` | § 7 : deux limites | ## Décisions 13 décisions : 7 HIGH, 6 MEDIUM, 0 LOW (détail dans le journal de décisions du run). - [MEDIUM] Le mock de `react` par le harnais va dans `PriceFetchControl.test.tsx`, le fichier que nomme l'issue, et le rendu existant passe par le même helper `markup()` (`harness.render`), comme `PriceFetchConsentToggle.test.tsx` : sous un mock de fichier, un rendu JSX par react-dom/server appellerait les hooks du harnais sans remise à zéro du curseur. Écartés : un fichier de test à part ; garder le rendu JSX avec un simple `harness.clear()`. - [MEDIUM] Les quatre textes de la fenêtre de consentement sont épinglés, pas seulement « Accepter » : aucun test ne rendait la fenêtre, donc les quatre étaient libres ; trois assertions de plus, chaque mutation rouge (M6b à M6d). - [MEDIUM] Clé des notes : le plan épingle le `title` du bouton ; le second appel (`placeholder` de la `textarea`) l'est aussi, dans `TransactionTable.wiring.test.ts` (créé par #369 après le plan), par un clic dans l'arbre rendu, sans emplacement préréglé. La revue 23499 ne dit pas lequel des deux appels elle avait muté. - [MEDIUM] Commentaire d'ordre des hooks aussi dans `SystemsSettingsPage.test.tsx` (même décalage silencieux) ; `OnboardingStepCard.test.tsx` ne fait que lire l'emplacement 0 et dit déjà « its first hook » : cité dans `architecture.md`, pas commenté. - [MEDIUM] `architecture.md` : section ajoutée en fin de « Tests », renvois à l'ADR 0021 plutôt que recopie. - [MEDIUM] `86eff9b` : défauts de documentation corrigés, la seconde limite écrite, aucun changement du code ni test qui fige la fuite. - [HIGH] Préflight passé (#369, #419, #421 fermées, tag `v0.17.2`) ; chemins des clés lus sur la base ; verdicts de la partie 1 ; en-têtes périmés de `LicenseKeyForm.render.test.tsx` et (auto-revue) de `PriceFetchControl.test.tsx` corrigés ; pas de CHANGELOG ; niveau normal ; formulation de la seconde limite généralisée à tout arrêt dans un nom de dossier (sonde `My;Docs`). ## Preuves Passe de mutations par script à table, une mutation à la fois, **suite complète** (152 fichiers) à chaque fois, restauration par `git checkout --` et arbre vérifié propre après chacune ; jouée après le commit des tests. **Épingles de cette PR** (rouges attendues : le test du composant) | # | Fichier | Mutation | Tests rouges | rc | |---|---|---|---|---| | M1 | `src/services/db.ts` | `\r` retiré de `PATH_STOP` | 1 (`db.test.ts`) | 1 | | M2 | `TransactionTable.tsx` | `aria-label` de l'icône de transfert sans `t` | 1 (`TransactionTable.render.test.tsx`) | 1 | | M3 | `TransactionTable.tsx` | `title` du bouton de notes sans `t` | 2 (render et wiring) | 1 | | M3b | `TransactionTable.tsx` | `placeholder` de la `textarea` de notes sans `t` | 1 (`TransactionTable.wiring.test.ts`) | 1 | | M4 | `LicenseKeyForm.tsx` | `placeholder` du champ sans `t` | 1 (`LicenseKeyForm.render.test.tsx`) | 1 | | M5 | `LicenseKeyForm.tsx` | texte du bouton d'envoi sans `t` | 1 (`LicenseKeyForm.render.test.tsx`) | 1 | | M6 | `PriceFetchControl.tsx` | `consent.accept` sans `t` | 1 (`PriceFetchControl.test.tsx`) | 1 | | M6b | `PriceFetchControl.tsx` | `consent.title` sans `t` | 1 | 1 | | M6c | `PriceFetchControl.tsx` | `consent.body` sans `t` | 1 | 1 | | M6d | `PriceFetchControl.tsx` | `consent.decline` sans `t` | 1 | 1 | | M7 | `DashboardPage.tsx` | `dashboard.kpiSectionTitle` sans `t` | 1 (`DashboardPage.render.test.tsx`) | 1 | | M8 | `PriceFetchControl.tsx` | un `useState` ajouté avant `showConsentModal` (décalage des emplacements) | 1 (le test de la fenêtre : le décalage est bruyant ici) | 1 | **Mutations rejouées des cinq commits relus** | # | Commit | Mutation | Tests rouges | rc | |---|---|---|---|---| | R1 | `74fae14` | `close()` d'un handle de `getDb()` sans contrôle de génération | 1 | 1 | | R2 | `74fae14` | `closeUnlocked` relance l'échec du `close()` | 2 | 1 | | R3 | `74fae14` | `lockHolder` jamais remis à `null` | 1 | 1 | | R4 | `74fae14` | échec du `close()` écrit sans `withoutFolders` | 1 | 1 | | R5 | `a1c31a1` | `pathname` dans les dépendances du suiveur (M1 de 23495) | 1 | 1 | | R6 | `a1c31a1` | branche de longueur de `depsChanged` retirée (M8 de 23495) | 1 | 1 | | R7 | `ac3a981` | garde réduite à la règle `t: (` | 1 | 1 | | R8 | `ac3a981` | le nom `i18nMock` suffit (commentaires compris) | 1 | 1 | | R9 | `ac3a981` | `renderCategoryLabel` sans `t` | 6 | 1 | | R10 | `86eff9b` | une `)` n'arrête jamais un chemin | 1 | 1 | | R11 | `86eff9b` | pas d'arrêt au chemin suivant | 2 | 1 | | R12 | `86eff9b` | un blanc termine les dossiers (comportement de `fbecfff`) | 18 | 1 | | R13 | `c17bf5d` | badge remis au littéral `best-effort` | 1 | 1 | ## Comptes - vitest : **152 fichiers, 2465 tests verts** (+7 tests, aucun fichier ajouté) ; `npm run build` vert (`tsc` + vite). - Sonde : rc=1 (`src/zz_tmp_probe.test.ts`, un `expect` rouge, supprimée). - Rust : non touché, pas de `cargo test`. ## Vérifications manuelles dues (prochaine release) Aucune : la PR ne change ni comportement ni texte visible. ## Pour le relecteur - Trois commits : les épingles (`test:`), les commentaires et la documentation (`docs:`), puis une correction d'auto-revue (`docs:`, en-tête de `PriceFetchControl.test.tsx` qui disait encore tout rendu React contourné). - `license.activate` est aussi appelée par le bouton « Activer » de la section Machines (`LicenseCard.tsx`) : déjà épinglée sous forme marquée (sonde : `t` retiré là, 2 tests rouges dans `LicenseCard.render.test.tsx`). - `PriceFetchControl.test.tsx` est maintenant entièrement sous le harnais (mock de `react` au niveau du fichier) ; les describes qui ne rendent rien n'en sont pas affectés, et le test de rendu existant garde ses six assertions telles quelles. - La liste « Utilisateurs » du harnais dans `architecture.md` était déjà incomplète avant cette PR (`TransactionTable.wiring`, `AdjustmentForm.wiring`, `LinkTransfersModal.wiring`, `HierarchyCheckModal.wiring`, `useAdjustments`, `useCategories`, `ChangelogContent`, `SystemsSettingsPage`, `ProfileFormModal.delete` n'y figurent pas) ; non mise à jour ici, hors périmètre ; `PriceFetchControl.test.tsx` s'y ajoute. - Seconde limite de `withoutFolders` (défaut 3 de la partie 1) : documentée, pas corrigée ; une issue de suivi est à décider. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
maximus added 2 commits 2026-10-19 00:02:09 +00:00
- db.test.ts: `\r` joins the path stops of withoutFolders (removing it from
  PATH_STOP now fails).
- The six keys whose "t removed" mutation survived the review of PR #435
  (comment 23499) are asserted in their marked form:
  transactions.transferIcon.ariaLabel (a row linked to a transfer) and
  transactions.notes.placeholder (title of every row's notes button) in
  TransactionTable.render.test.tsx; license.keyPlaceholder and
  license.activate in LicenseKeyForm.render.test.tsx;
  dashboard.kpiSectionTitle in DashboardPage.render.test.tsx;
  balance.priceFetching.consent.accept in PriceFetchControl.test.tsx, the
  consent dialog opened by presetting the control's first harness slot
  (the dialog's title, body and decline texts are pinned with it).
- TransactionTable.wiring.test.ts opens a row's notes through its button
  and pins the textarea placeholder, the second call of the notes key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs: name the slot-order dependency and the known test limits (#437)
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 2m7s
ae54406354
- Where a test presets a harness slot by position (PriceFetchConsentToggle,
  useOnboardingChecklist's mountWith, SystemsSettingsPage), a comment names
  the dependency on the component's hook order: any hook added before shifts
  the slots without a word (the `slot` helper of fakeReact).
- docs/architecture.md, Tests: "Limites connues" lists the slot presets, and
  links to ADR 0021 for withoutFolders and for the catch-up measurement
  instead of repeating them.
- ADR 0021 section 7: the relative-path limit is stated precisely (a run with
  two separators or more is still cut to its last segment; only the words of
  a folder holding a blank stay), and a second limit is written: a folder
  name holding one of the stops (a backtick, `;`, `|`, a closing parenthesis
  not followed by a separator...) ends the path there, and that name, or its
  start, stays in the line.
- db.ts: the comment of withoutFolders says "a closing parenthesis not
  followed by a separator", as the code does, and points to ADR 0021.

No behaviour change.

Resolves #437

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maximus added the
autopilot:pending-human
label 2026-10-19 00:02:25 +00:00
maximus added 1 commit 2026-10-19 00:04:57 +00:00
docs: fix the stale header of PriceFetchControl.test.tsx (#437)
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 2m2s
dad81fa53f
Self-review of PR #473: the header still said every React rendering of the
file was bypassed, while its "displayed texts" tests render the control with
its hooks from the shared harness. architecture.md: the slot presets are
commented in each test file (the two direct writes of the onboarding wiring
test are covered by the comment of mountWith).

Resolves #437

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Owner

Niveau : normal
Verdict : APPROVE

Auto-revue de l'auteur (worker /autopilot), pas une revue indépendante. Checklist de /pr-review appliquée au diff complet de la PR contre sa base issue-393-category-hierarchy, à la profondeur du niveau normal.

Résumé. Tests, commentaires et documentation seulement : l'arrêt \r et les six clés survivantes de la revue 23499 sont épinglés sous forme marquée (plus le second appel de la clé des notes et les trois autres textes de la fenêtre de consentement), la dépendance à l'ordre des hooks est commentée à chaque préréglage d'emplacement, et les limites connues sont écrites sans recopier l'ADR 0021. Les cinq commits de suivi sont relus : rien à signaler sur quatre ; sur 86eff9b, trois défauts de documentation corrigés ici, sans toucher au code.

Niveau (Step 0bis, REVIEW.md de main)

Fichier par fichier : les douze fichiers sont normaux. Aucune ligne du tableau Haut n'est remplie : les tests sous src/** n'ajoutent aucun appel réseau et ne retirent ni ne contournent aucun consentement (PriceFetchControl.tsx et PriceFetchConsentToggle.tsx ne sont touchés que par leurs tests, qui ouvrent la fenêtre dans un rendu de test) ; src/services/db.ts (commentaire seul), docs/architecture.md et docs/adr/** restent au moins normaux ; aucun fichier ajouté, renommé ou supprimé.

Ce qui a été exécuté

  • Sonde : un expect rouge fait sortir vitest en rc=1 ; fichier supprimé.
  • npm run build vert ; npm test : 152 fichiers, 2465 tests verts, sur la tête dad81fa.
  • 12 mutations des épingles (M1 à M8), suite complète à chaque fois : toutes rouges, chacune dans le test du composant visé (tableau dans le corps).
  • 13 mutations rejouées des cinq commits relus (R1 à R13) : toutes rouges.
  • Sonde hors tableau : t retiré du bouton « Activer » des Machines (LicenseCard.tsx, autre appel de license.activate) : 2 rouges dans LicenseCard.render.test.tsx, cet appel était déjà épinglé.
  • Arbre propre après chaque mutation ; aucun fichier zz_tmp_* laissé.

Checklist

  • Sécurité : aucun secret, aucun jeton, aucune clé de licence ; seuls des noms fictifs (Jean Dupont, marie claire, Jean (Work) Smith) ; aucun .env.
  • Correction : chaque test fait ce que son nom dit ; PriceFetchControl.test.tsx passe entier sous le harnais, et le test de rendu existant garde ses six assertions.
  • Tests : aucun .only ni .skip ; aucune régression (suite verte).
  • Qualité : commits conventionnels (test:, docs:) ; aucune chaîne visible ; mot-clé de fermeture en première ligne du corps et dans le dernier commit, nulle part ailleurs ; la timeline de l'issue porte un seul pull_ref en closes, celui de cette PR.
  • Données : aucune migration.
  • Zones de REVIEW.md : « i18n et documentation » (rien de visible, donc pas de CHANGELOG ; architecture.md et l'ADR 0021 à jour). « Vie privée » : la règle « un message du Journal nomme un fichier, jamais son dossier » a une exception préexistante, que la PR documente sans changer le code (suggestion 1).

Constat corrigé

  1. src/components/balance/PriceFetchControl.test.tsx:1-6 : l'en-tête disait encore que tout rendu React du fichier était contourné, alors que ses tests « displayed texts » rendent le contrôle, hooks fournis par le harnais. Corrigé dans dad81fa, avec une précision de formulation dans docs/architecture.md (préréglages « commentés dans son fichier »).

Corrigé aussi dans le corps de la PR avant ce verdict : la ligne M5 disait que LicenseCard.render.test.tsx laissait passer l'oubli par une assertion en sous-chaîne ; ses assertions license.activate visent le bouton « Activer » des Machines, déjà épinglé.

Suggestions (non bloquantes)

  1. Seconde limite de withoutFolders (défaut 3 de la partie 1, maintenant dans l'ADR 0021 § 7) : un nom de dossier qui contient l'un des arrêts laisse ce nom, ou son début, dans la ligne du Journal (Jean (Work) x.db). Cas rare, et le côté Rust remplace déjà le dossier des profils par <profile folder> ; le correctif changerait le comportement, ce que l'issue exclut. À Max de décider d'une issue de suivi.
  2. La liste « Utilisateurs » du harnais dans docs/architecture.md était déjà incomplète avant cette PR (neuf fichiers de test plus récents n'y figurent pas, PriceFetchControl.test.tsx s'y ajoute) : à rafraîchir avec un autre suivi de documentation.
Niveau : normal Verdict : APPROVE **Auto-revue de l'auteur (worker /autopilot), pas une revue indépendante.** Checklist de `/pr-review` appliquée au diff complet de la PR contre sa base `issue-393-category-hierarchy`, à la profondeur du niveau normal. **Résumé.** Tests, commentaires et documentation seulement : l'arrêt `\r` et les six clés survivantes de la revue 23499 sont épinglés sous forme marquée (plus le second appel de la clé des notes et les trois autres textes de la fenêtre de consentement), la dépendance à l'ordre des hooks est commentée à chaque préréglage d'emplacement, et les limites connues sont écrites sans recopier l'ADR 0021. Les cinq commits de suivi sont relus : rien à signaler sur quatre ; sur `86eff9b`, trois défauts de documentation corrigés ici, sans toucher au code. ### Niveau (Step 0bis, `REVIEW.md` de `main`) Fichier par fichier : les douze fichiers sont normaux. Aucune ligne du tableau Haut n'est remplie : les tests sous `src/**` n'ajoutent aucun appel réseau et ne retirent ni ne contournent aucun consentement (`PriceFetchControl.tsx` et `PriceFetchConsentToggle.tsx` ne sont touchés que par leurs tests, qui ouvrent la fenêtre dans un rendu de test) ; `src/services/db.ts` (commentaire seul), `docs/architecture.md` et `docs/adr/**` restent au moins normaux ; aucun fichier ajouté, renommé ou supprimé. ### Ce qui a été exécuté - Sonde : un `expect` rouge fait sortir vitest en rc=1 ; fichier supprimé. - `npm run build` vert ; `npm test` : 152 fichiers, 2465 tests verts, sur la tête `dad81fa`. - 12 mutations des épingles (M1 à M8), suite complète à chaque fois : toutes rouges, chacune dans le test du composant visé (tableau dans le corps). - 13 mutations rejouées des cinq commits relus (R1 à R13) : toutes rouges. - Sonde hors tableau : `t` retiré du bouton « Activer » des Machines (`LicenseCard.tsx`, autre appel de `license.activate`) : 2 rouges dans `LicenseCard.render.test.tsx`, cet appel était déjà épinglé. - Arbre propre après chaque mutation ; aucun fichier `zz_tmp_*` laissé. ### Checklist - Sécurité : aucun secret, aucun jeton, aucune clé de licence ; seuls des noms fictifs (`Jean Dupont`, `marie claire`, `Jean (Work) Smith`) ; aucun `.env`. - Correction : chaque test fait ce que son nom dit ; `PriceFetchControl.test.tsx` passe entier sous le harnais, et le test de rendu existant garde ses six assertions. - Tests : aucun `.only` ni `.skip` ; aucune régression (suite verte). - Qualité : commits conventionnels (`test:`, `docs:`) ; aucune chaîne visible ; mot-clé de fermeture en première ligne du corps et dans le dernier commit, nulle part ailleurs ; la timeline de l'issue porte un seul `pull_ref` en `closes`, celui de cette PR. - Données : aucune migration. - Zones de `REVIEW.md` : « i18n et documentation » (rien de visible, donc pas de CHANGELOG ; `architecture.md` et l'ADR 0021 à jour). « Vie privée » : la règle « un message du Journal nomme un fichier, jamais son dossier » a une exception préexistante, que la PR documente sans changer le code (suggestion 1). ### Constat corrigé 1. `src/components/balance/PriceFetchControl.test.tsx:1-6` : l'en-tête disait encore que tout rendu React du fichier était contourné, alors que ses tests « displayed texts » rendent le contrôle, hooks fournis par le harnais. Corrigé dans `dad81fa`, avec une précision de formulation dans `docs/architecture.md` (préréglages « commentés dans son fichier »). Corrigé aussi dans le corps de la PR avant ce verdict : la ligne M5 disait que `LicenseCard.render.test.tsx` laissait passer l'oubli par une assertion en sous-chaîne ; ses assertions `license.activate` visent le bouton « Activer » des Machines, déjà épinglé. ### Suggestions (non bloquantes) 1. **Seconde limite de `withoutFolders`** (défaut 3 de la partie 1, maintenant dans l'ADR 0021 § 7) : un nom de dossier qui contient l'un des arrêts laisse ce nom, ou son début, dans la ligne du Journal (`Jean (Work) x.db`). Cas rare, et le côté Rust remplace déjà le dossier des profils par `<profile folder>` ; le correctif changerait le comportement, ce que l'issue exclut. À Max de décider d'une issue de suivi. 2. La liste « Utilisateurs » du harnais dans `docs/architecture.md` était déjà incomplète avant cette PR (neuf fichiers de test plus récents n'y figurent pas, `PriceFetchControl.test.tsx` s'y ajoute) : à rafraîchir avec un autre suivi de documentation.
Author
Owner

CI lue par l'orchestrateur du run /autopilot du 2026-10-18 : check-frontend vert sur la tête dad81fa (run 584).

  • vitest : 152 fichiers et 2465 tests, tous verts. Les fichiers épinglés ont tourné : db.test.ts (60), PriceFetchControl.test.tsx (19), TransactionTable.render.test.tsx (8), TransactionTable.wiring.test.ts (6), LicenseKeyForm.render.test.tsx (5), DashboardPage.render.test.tsx (7), PriceFetchConsentToggle.test.tsx (12) et useOnboardingChecklist.wiring.test.ts (18).
  • check-rust ne s'applique pas à ce maillon (aucun chemin Rust touché).
  • À trancher par Max, relevé par la relecture de 86eff9b : un nom de dossier qui contient un caractère d'arrêt (), accent grave…) laisse ce nom, ou son début, dans la ligne du Journal (C:\Users\Jean (Work) Smith\AppData\x.db donne Jean (Work) x.db). Le cas est documenté comme limite dans l'ADR 0021 §7 et n'est pas corrigé ici, puisque l'issue exclut tout changement de comportement.
CI lue par l'orchestrateur du run `/autopilot` du 2026-10-18 : `check-frontend` **vert** sur la tête `dad81fa` (run 584). - vitest : 152 fichiers et 2465 tests, tous verts. Les fichiers épinglés ont tourné : `db.test.ts` (60), `PriceFetchControl.test.tsx` (19), `TransactionTable.render.test.tsx` (8), `TransactionTable.wiring.test.ts` (6), `LicenseKeyForm.render.test.tsx` (5), `DashboardPage.render.test.tsx` (7), `PriceFetchConsentToggle.test.tsx` (12) et `useOnboardingChecklist.wiring.test.ts` (18). - `check-rust` ne s'applique pas à ce maillon (aucun chemin Rust touché). - À trancher par Max, relevé par la relecture de `86eff9b` : un nom de dossier qui contient un caractère d'arrêt (`)`, accent grave…) laisse ce nom, ou son début, dans la ligne du Journal (`C:\Users\Jean (Work) Smith\AppData\x.db` donne `Jean (Work) x.db`). Le cas est documenté comme limite dans l'ADR 0021 §7 et n'est pas corrigé ici, puisque l'issue exclut tout changement de comportement.
Author
Owner

Niveau : normal

Verdict : APPROVE

Résumé. Les six clés survivantes de la revue 23499 et l'arrêt \r sont épinglés sous la forme marquée : chaque mutation « t retiré » que j'ai rejouée rougit le test du composant sur la tête dad81fa et restait verte sur la base 8a9d990. Les faits ajoutés à l'ADR 0021, à architecture.md et aux commentaires tiennent à la sonde, sauf une phrase sur le test #[ignore] (suggestion 1). Aucun changement de comportement ; les suggestions relèvent d'issues de suivi, pas d'un tour de plus.

Niveau. Aucun fichier n'entre dans le tableau Haut : des tests, docs/adr/** et docs/architecture.md (au moins normaux), un commentaire seul dans src/services/db.ts (normal). La ligne « code livré » ne s'applique pas : PriceFetchControl.test.tsx et PriceFetchConsentToggle.test.tsx ne changent que du test et des commentaires, sans appel réseau ni consentement touché.

Rejoué (copie hors dépôt)

  • npm ci, npm run build (tsc + vite) vert ; vitest run : 152 fichiers, 2465 tests verts (2458 sur la base, soit +7) ; sonde rc=1.
  • CI check-frontend run 584 sur dad81fa, journal lu : build, 152 fichiers, 2465 tests.
  • Mutations du relecteur, une à la fois, suite complète à chaque fois, restauration par git, arbre propre après chacune :
# Mutation Tête Base
X1 \r retiré de PATH_STOP 1 rouge (db.test.ts) vert
X2b icône de transfert aussi sur la 1re ligne quand des liens sont passés 1 rouge vert
X3 aria-label de l'icône : clé brute, sans t 1 rouge vert
X18 title du bouton de notes : clé brute 2 rouges (render, wiring) vert
X5 title du bouton de notes sur la 1re ligne seulement 2 rouges —
X6 placeholder de la textarea : autre clé 1 rouge (wiring) —
X7 un clic déplie les notes de toutes les lignes 1 rouge (wiring) —
X9 placeholder du champ de clé écrit en dur 1 rouge vert
X10 bouton d'envoi : clé brute 1 rouge vert
X14 consent.accept : clé brute 1 rouge vert
X13 useEffect ajouté avant showConsentModal (décalage des emplacements) 1 rouge —
X15, X16 titre des KPI écrit en dur, puis clé brute 1 rouge chacune X16 vert
X17 bestEffortNotice brut (test existant, passé sous le harnais) 1 rouge —
X4 infobulle de l'icône (transferIcon.tooltip) : clé brute vert —
X11 common.cancel de LicenseKeyForm : clé brute vert —
X8 le clic sur les notes de la ligne 2 déplie la ligne 1 vert —
X12 « Annuler » de la fenêtre de consentement appelle onAccept vert —
Y1 handleClick ne regarde plus le consentement (if (false)) vert —
Y2 « Annuler » lance quand même la récupération vert —
Y3 garde Premium retirée (!isPremium) vert —
Y4 hasConsent() rend toujours true vert —

Une première version de X2 plantait sans table de liens (13 rouges sans rapport avec l'épingle) : remplacée par X2b.

  • Sondes de withoutFolders sur les exemples ajoutés : dossier/sous/x.db → x.db, dossier/sous dossier/x.db → dossier-sous dossier-x.db, C:\Users\Jean (Work) Smith\AppData\x.db → Jean (Work) x.db, C:\Users\jean\My;Docs\x.db → My;Docs-x.db. Le commentaire corrigé de db.ts décrit bien la ligne 371 (parenthèse fermante non suivie d'un séparateur).
  • architecture.md : les six hooks couverts prennent chacun un emplacement (slot de fakeReact) ; la liste des préréglages est complète (slots[ dans src/ : ces cinq fichiers, rien d'autre ; mountWith et les écritures des l. 360 et 384 ; deux préréglages dans SystemsSettingsPage.test.tsx) ; la section et le point cités de l'ADR 0021 existent. Les quatre commentaires d'ordre des hooks correspondent aux composants (showConsentModal ; hasConsent, showConfirm, loading ; version ; le useReducer en premier).
  • Les dix clés épinglées existent dans fr.json et en.json.
  • Partie 1, par sondage : appelants de closeDb() dans ProfileContext, closeUnlocked, motifs de la garde i18n : conformes au corps de la PR.
  • Fermeture : un seul pull_ref en closes sur #437, celui de cette PR.

Suggestions (non bloquantes)

  1. architecture.md, « Mesure du rattrapage » : « n'asserte rien » est inexact. a_large_profile_catch_up_duration asserte que le rattrapage aboutit (catch_up_error à None et plancher 6, profile_db.rs:1755-1756) ; il n'asserte rien sur la durée. Proposé : « n'asserte rien sur la durée, qu'il imprime après avoir vérifié que le rattrapage aboutit ». Le commentaire Rust (« Prints, never asserts », l. 1706) porte la même imprécision. Phrase inchangée au sommet de la pile (#475).
  2. Épingles du même ordre, à grouper dans une issue : le nouveau rendu de TransactionTable.render.test.tsx affiche l'infobulle de l'icône sans l'asserter (X4), et transactions-transfer-icon.test.ts ne lit que la source, donc une clé brute passe. Une ligne dans le même test l'épingle, avec la clé de direction : expect(bodyRows(html)[1]).toContain('title="t(transactions.transferIcon.tooltip): CELI (t(balance.transfers.direction.in))"') (balisage relevé par sonde). Même cas pour common.cancel, rendu par le nouveau test de LicenseKeyForm (X11). Le test des notes ne dit pas quelle ligne se déplie (X8) : les Fragment portent key={row.id}, chercher la textarea sous celui de la ligne 2 le dirait.
  3. Consentement et garde Premium de PriceFetchControl (zone Vie privée) : aucun test n'exerce le parcours de consentement ni la garde Premium (X12 et Y1 à Y4 restent verts sur la suite complète). Les six describes autres que « displayed texts » appellent les mocks et recalculent les conditions, sans appeler le composant ; l'en-tête réécrit par dad81fa dit encore qu'ils « cover the component's internal logic ». Ce consentement n'est vérifié que côté front, fetch_price ne le revérifie pas (REVIEW.md). Le fichier étant maintenant sous le harnais, une issue de suivi peut tester handleClick, « Accepter » et « Annuler » par l'arbre rendu (appeler le onClick du bouton, attendre, rendre de nouveau, lire la fenêtre et fetchPrice), avec ces cinq mutations pour critère, et corriger l'en-tête.
  4. Seconde limite de withoutFolders, pour la décision de Max : une issue de suivi en priorité basse. withoutFolders est la seconde barrière derrière scrub (Rust), qui remplace déjà le dossier des profils par <profile folder> ; et un nom de compte local Windows ne peut contenir ni ;, ni |, ni ,, ni :. Le cas réaliste est un nom de compte avec des parenthèses suivies d'un autre mot, dans un chemin que scrub n'a pas remplacé.
  5. La liste « Utilisateurs » du harnais (architecture.md) n'inclut pas PriceFetchControl.test.tsx ; écart signalé dans le corps de la PR, à joindre au suivi.

Actions faites

  • Clone local dans /tmp/pr473-review (npm ci), supprimé en fin de revue avec les fichiers /tmp/pr473-*.
  • #437 : status:review → status:approved.
Niveau : normal **Verdict : APPROVE** **Résumé.** Les six clés survivantes de la revue 23499 et l'arrêt `\r` sont épinglés sous la forme marquée : chaque mutation « `t` retiré » que j'ai rejouée rougit le test du composant sur la tête `dad81fa` et restait verte sur la base `8a9d990`. Les faits ajoutés à l'ADR 0021, à `architecture.md` et aux commentaires tiennent à la sonde, sauf une phrase sur le test `#[ignore]` (suggestion 1). Aucun changement de comportement ; les suggestions relèvent d'issues de suivi, pas d'un tour de plus. **Niveau.** Aucun fichier n'entre dans le tableau Haut : des tests, `docs/adr/**` et `docs/architecture.md` (au moins normaux), un commentaire seul dans `src/services/db.ts` (normal). La ligne « code livré » ne s'applique pas : `PriceFetchControl.test.tsx` et `PriceFetchConsentToggle.test.tsx` ne changent que du test et des commentaires, sans appel réseau ni consentement touché. ### Rejoué (copie hors dépôt) - `npm ci`, `npm run build` (tsc + vite) vert ; `vitest run` : 152 fichiers, 2465 tests verts (2458 sur la base, soit +7) ; sonde rc=1. - CI `check-frontend` run 584 sur `dad81fa`, journal lu : build, 152 fichiers, 2465 tests. - Mutations du relecteur, une à la fois, suite complète à chaque fois, restauration par git, arbre propre après chacune : | # | Mutation | Tête | Base | |---|---|---|---| | X1 | `\r` retiré de `PATH_STOP` | 1 rouge (`db.test.ts`) | vert | | X2b | icône de transfert aussi sur la 1re ligne quand des liens sont passés | 1 rouge | vert | | X3 | `aria-label` de l'icône : clé brute, sans `t` | 1 rouge | vert | | X18 | `title` du bouton de notes : clé brute | 2 rouges (render, wiring) | vert | | X5 | `title` du bouton de notes sur la 1re ligne seulement | 2 rouges | — | | X6 | `placeholder` de la `textarea` : autre clé | 1 rouge (wiring) | — | | X7 | un clic déplie les notes de toutes les lignes | 1 rouge (wiring) | — | | X9 | `placeholder` du champ de clé écrit en dur | 1 rouge | vert | | X10 | bouton d'envoi : clé brute | 1 rouge | vert | | X14 | `consent.accept` : clé brute | 1 rouge | vert | | X13 | `useEffect` ajouté avant `showConsentModal` (décalage des emplacements) | 1 rouge | — | | X15, X16 | titre des KPI écrit en dur, puis clé brute | 1 rouge chacune | X16 vert | | X17 | `bestEffortNotice` brut (test existant, passé sous le harnais) | 1 rouge | — | | X4 | infobulle de l'icône (`transferIcon.tooltip`) : clé brute | **vert** | — | | X11 | `common.cancel` de `LicenseKeyForm` : clé brute | **vert** | — | | X8 | le clic sur les notes de la ligne 2 déplie la ligne 1 | **vert** | — | | X12 | « Annuler » de la fenêtre de consentement appelle `onAccept` | **vert** | — | | Y1 | `handleClick` ne regarde plus le consentement (`if (false)`) | **vert** | — | | Y2 | « Annuler » lance quand même la récupération | **vert** | — | | Y3 | garde Premium retirée (`!isPremium`) | **vert** | — | | Y4 | `hasConsent()` rend toujours `true` | **vert** | — | Une première version de X2 plantait sans table de liens (13 rouges sans rapport avec l'épingle) : remplacée par X2b. - Sondes de `withoutFolders` sur les exemples ajoutés : `dossier/sous/x.db` → `x.db`, `dossier/sous dossier/x.db` → `dossier-sous dossier-x.db`, `C:\Users\Jean (Work) Smith\AppData\x.db` → `Jean (Work) x.db`, `C:\Users\jean\My;Docs\x.db` → `My;Docs-x.db`. Le commentaire corrigé de `db.ts` décrit bien la ligne 371 (parenthèse fermante non suivie d'un séparateur). - `architecture.md` : les six hooks couverts prennent chacun un emplacement (`slot` de `fakeReact`) ; la liste des préréglages est complète (`slots[` dans `src/` : ces cinq fichiers, rien d'autre ; `mountWith` et les écritures des l. 360 et 384 ; deux préréglages dans `SystemsSettingsPage.test.tsx`) ; la section et le point cités de l'ADR 0021 existent. Les quatre commentaires d'ordre des hooks correspondent aux composants (`showConsentModal` ; `hasConsent`, `showConfirm`, `loading` ; `version` ; le `useReducer` en premier). - Les dix clés épinglées existent dans `fr.json` et `en.json`. - Partie 1, par sondage : appelants de `closeDb()` dans `ProfileContext`, `closeUnlocked`, motifs de la garde i18n : conformes au corps de la PR. - Fermeture : un seul `pull_ref` en `closes` sur #437, celui de cette PR. ### Suggestions (non bloquantes) 1. **`architecture.md`, « Mesure du rattrapage »** : « n'asserte rien » est inexact. `a_large_profile_catch_up_duration` asserte que le rattrapage aboutit (`catch_up_error` à `None` et plancher 6, `profile_db.rs:1755-1756`) ; il n'asserte rien sur la durée. Proposé : « n'asserte rien sur la durée, qu'il imprime après avoir vérifié que le rattrapage aboutit ». Le commentaire Rust (« Prints, never asserts », l. 1706) porte la même imprécision. Phrase inchangée au sommet de la pile (#475). 2. **Épingles du même ordre, à grouper dans une issue** : le nouveau rendu de `TransactionTable.render.test.tsx` affiche l'infobulle de l'icône sans l'asserter (X4), et `transactions-transfer-icon.test.ts` ne lit que la source, donc une clé brute passe. Une ligne dans le même test l'épingle, avec la clé de direction : `expect(bodyRows(html)[1]).toContain('title="t(transactions.transferIcon.tooltip): CELI (t(balance.transfers.direction.in))"')` (balisage relevé par sonde). Même cas pour `common.cancel`, rendu par le nouveau test de `LicenseKeyForm` (X11). Le test des notes ne dit pas quelle ligne se déplie (X8) : les `Fragment` portent `key={row.id}`, chercher la `textarea` sous celui de la ligne 2 le dirait. 3. **Consentement et garde Premium de `PriceFetchControl`** (zone Vie privée) : aucun test n'exerce le parcours de consentement ni la garde Premium (X12 et Y1 à Y4 restent verts sur la suite complète). Les six describes autres que « displayed texts » appellent les mocks et recalculent les conditions, sans appeler le composant ; l'en-tête réécrit par `dad81fa` dit encore qu'ils « cover the component's internal logic ». Ce consentement n'est vérifié que côté front, `fetch_price` ne le revérifie pas (`REVIEW.md`). Le fichier étant maintenant sous le harnais, une issue de suivi peut tester `handleClick`, « Accepter » et « Annuler » par l'arbre rendu (appeler le `onClick` du bouton, attendre, rendre de nouveau, lire la fenêtre et `fetchPrice`), avec ces cinq mutations pour critère, et corriger l'en-tête. 4. **Seconde limite de `withoutFolders`**, pour la décision de Max : une issue de suivi en priorité basse. `withoutFolders` est la seconde barrière derrière `scrub` (Rust), qui remplace déjà le dossier des profils par `<profile folder>` ; et un nom de compte local Windows ne peut contenir ni `;`, ni `|`, ni `,`, ni `:`. Le cas réaliste est un nom de compte avec des parenthèses suivies d'un autre mot, dans un chemin que `scrub` n'a pas remplacé. 5. La liste « Utilisateurs » du harnais (`architecture.md`) n'inclut pas `PriceFetchControl.test.tsx` ; écart signalé dans le corps de la PR, à joindre au suivi. ### Actions faites - Clone local dans `/tmp/pr473-review` (`npm ci`), supprimé en fin de revue avec les fichiers `/tmp/pr473-*`. - #437 : `status:review` → `status:approved`.
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 2m2s
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin issue-437-test-pins:issue-437-test-pins
git checkout issue-437-test-pins

Merge

Merge the changes and update on Forgejo.
git checkout issue-393-category-hierarchy
git merge --no-ff issue-437-test-pins
git checkout issue-393-category-hierarchy
git merge --ff-only issue-437-test-pins
git checkout issue-437-test-pins
git rebase issue-393-category-hierarchy
git checkout issue-393-category-hierarchy
git merge --no-ff issue-437-test-pins
git checkout issue-393-category-hierarchy
git merge --squash issue-437-test-pins
git checkout issue-393-category-hierarchy
git merge --ff-only issue-437-test-pins
git checkout issue-393-category-hierarchy
git merge issue-437-test-pins
git push origin issue-393-category-hierarchy
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/Simpl-Resultat#473
No description provided.