fix(test): profondeur d'assertion + trous de coverage ciblés - #113
Merged
Conversation
…overage ciblés
- auth.test.ts : les tests "should accept apiKey"/"should accept clientId
and clientSecret" n'assertaient que authUrl (invariant quels que soient
les credentials). Remplacés par des assertions sur la valeur réelle du
header authorizationBasicHeaders (Basic <apiKey> / Basic <base64(id:secret)>).
Le code s'exécutait déjà à 100% de couverture ; un mauvais encodage du
header serait passé inaperçu jusqu'ici. Ajout aussi de l'assertion sur le
header Authorization effectivement envoyé par requestAuthenticatedToken.
- docs.test.ts : suppression des describe('notificationCenter')/('filterCenter')
qui ne vérifiaient que typeof x === 'function' — comportement déjà
couvert par notification.test.ts et filter.test.ts.
- index.test.ts : fusion des deux tests "should export ApiCore class" /
"should allow creating an ApiCore instance", le second rendait le
premier redondant.
- QueryBuilder.test.ts : les 19 tests "should return this for chaining"
(x11) et "should not set X when undefined" (x8), un par describe de
setter, remplacés par deux blocs it.each paramétrés.
- request.test.ts : nouveau test pour le chemin status>=300 de fetchText
(get(url, {}, 'text')), jusqu'ici non exercé.
- parseDocument.test.ts : deux nouveaux tests figeant des comportements
non testés — genre en tableau non-vide (garde le premier élément), et
signal: 'cwarn' seul -> undefined (AfpDocumentSignal ne modélise que
'correction'|'update', cwarn en est délibérément exclu).
- shotlist.test.ts : nouveau test pour le repli citation-sans-guillemets
(une description de SOUNDBITE qui commence elle-même par "SOUNDBITE").
- @vitest/coverage-v8 repin sur 4.1.10 (exact) pour matcher vitest@4.1.10
et faire disparaître l'avertissement "mixed versions"; ajout du script
test:coverage.
Trouvaille non corrigée ici (issue séparée #112) : request.ts:80 est du
code mort confirmé — fetchText ne peut jamais détecter un payload
d'erreur AFP sur HTTP 200 car elle parse errorSchema (z.object) contre
une string brute. Changement de comportement runtime volontairement
tenu à l'écart de cette PR de tests.
Coverage : 97.87% -> 98.81% lignes, 89.75% -> 91.3% branches, 99.28% ->
100% fonctions — secondaire par rapport à la profondeur d'assertion
ci-dessus.
Réf: #110
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…aphes parseParagraphBlocks (sous-titre/liste/paragraphe) et numberParagraphs ([¶n], 1-based) étaient dupliqués dans afpnews-deck. Les rendre disponibles ici permet à afpnews-mcp-server de produire un Markdown structuré et numéroté cohérent avec les deep-links ?p=n du deck. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…OURCES extractBase() typait son retour en Omit<AfpDocument, ...> : Omit sur un type union n'est pas distributif, donc `class` s'aplatissait en l'union complète des 8 littéraux au lieu de rester lié à la variante narrowed par le switch. Chaque case assignait alors un `class` trop large à AfpDocument (union discriminée) -> erreurs tsc. extractBase() retourne maintenant Omit<AfpDocumentCommon, ...> (type non discriminé, sans `class`) et chaque branche du switch pose elle-même `class: doc.class`, correctement narrowed à cet endroit. AfpDocumentCommon exporté pour être référencé. FIELD_SOURCES.paragraphs et .caption listaient des dépendances brutes incomplètes par rapport à parseDocument() : paragraphs peut retirer la 1re ligne de `news` comme titre replié quand `headline` est absent (urgency < 4), et caption retombe sur bagItem[0].caption pour picture/graphic. Sans ces champs bruts dans la liste, toApiFields() omettait de les demander à l'API quand seul le champ dérivé était requêté, cassant ces replis silencieusement.
tsdown ne fait pas de vérification de type sémantique (transpilation à la esbuild + .d.ts syntaxique) : lint/build/test ne détectaient donc pas les erreurs de type du commit précédent. Ajoute `npm run typecheck` (tsc --noEmit), branché dans `prepare` et dans la CI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ce qui compte vraiment ici
authorizationBasicHeaders(utilisé pour l'auth par credentials et le refresh) tournait déjà à 100% de couverture de lignes, mais aucun test n'assertait la valeur réellement produite — les deux tests censés le couvrir ("should accept apiKey"/"should accept clientId and clientSecret") ne vérifiaient queauthUrl, invariant quels que soient les credentials passés. Un mauvais encodage du header serait passé inaperçu. Remplacés par des assertions sur le headerBasic <...>réellement construit, plus une assertion sur le header effectivement envoyé parrequestAuthenticatedToken.Le reste (coverage 97.87%→98.81% lignes, 89.75%→91.3% branches) est secondaire — la vraie amélioration est la profondeur d'assertion, pas le pourcentage.
Détail
docs.test.ts: suppression desdescribe('notificationCenter')/('filterCenter')(typeof x === 'function'), déjà couverts comportementalement parnotification.test.ts/filter.test.tsindex.test.ts: fusion de deux tests redondantsQueryBuilder.test.ts: 19 tests répétitifs (should return this for chaining× 11,should not set X when undefined× 8) remplacés par 2 blocsit.eachrequest.test.ts: nouveau test pourfetchText's status≥300 (chemin atteignable, non testé avant)parseDocument.test.ts: deux tests qui figent des comportements existants —genreen tableau non-vide, etsignal: 'cwarn'seul →undefined(intentionnel :AfpDocumentSignalne modélise que'correction'|'update')shotlist.test.ts: le repli citation-sans-guillemets (description de SOUNDBITE qui commence elle-même par "SOUNDBITE")@vitest/coverage-v8repin exact sur4.1.10(matchevitest@4.1.10, fait disparaître l'avertissement de version mixte) + scripttest:coverageTrouvaille non corrigée ici
request.ts:80est du code mort confirmé :fetchTextne peut jamais détecter un payload d'erreur AFP sur HTTP 200, car elle parseerrorSchema(unz.object) contre une string brute (response.text()) au lieu du JSON parsé comme le faitfetchJson. Impact réel potentiel surgetStoryHtml/feed. Tenu à l'écart de cette PR pour ne pas mélanger changement de comportement runtime et travail sur les tests → #112.Closes #110
🤖 Generated with Claude Code