21 — Tests et Storybook
Statut : fait · Phase : transverse · Mis à jour : 30/10/2026.
Décidé le 29/10/2026. Chaque composant et chaque runtime de Récit reçoit une story qui le
spécifie état par état, une fonction play qui prouve son comportement, un contrôle
d'accessibilité et une capture en clair et en sombre. Storybook devient la spécification
exécutable de l'interface : ce que la migration de style (19-style.md) transforme, ces tests le
vérifient ; ce qui vient après s'écrit d'abord dans une story. Le plan inventorie l'existant (§1),
fixe la pyramide et l'outil (§2), structure Storybook (§3), dresse le catalogue des stories (§4),
les conventions (§5), la mesure (§6), le câblage CI (§7), puis les lots et leur imbrication dans les
vagues du plan 19 telles que 20-multi-agents.md §4 les redécoupe (§8). Ce plan ne s'implémente
pas avant la demande de l'utilisateur.
0. Décision, portée et lecture de la demande
0.1 La demande, telle qu'elle est lue
- « Élaborer des tests » : des tests fonctionnels, qui prouvent ce que fait un composant (un clic ouvre, une touche navigue, un état s'affiche), et pas seulement qu'il se rend sans exception.
- « Structurer Storybook » : une arborescence par surface, des décorateurs communs, une story par composant avec ses états, et Storybook comme point d'entrée des tests de composants, pas comme une vitrine à part.
- « Le plus de tests fonctionnels sur le sujet » : le sujet est l'interface de Récit telle que le
plan 19 la réécrit — les primitives
ui/du framework, ses composants et sa navigation, les composants de diapositive, le runtime du deck, les blocs motion,site-kit, les composants des sites et des exemples. Le code non visuel (compilation, config, CLI) garde ses tests Vitest, ce plan ne les refait pas.
0.2 Objectifs
- Une story par composant exporté, avec un export par état (défaut, variantes, vide, erreur,
chargement, long contenu), les
argstypés, l'autodoc. - Une fonction
playpar comportement : ouverture et fermeture, clavier, focus, sélection, copie, navigation ; écrite contre les rôles et les noms accessibles, jamais contre une classe. - L'accessibilité par story (
addon-a11yen mode test, déjàa11y.test: "error"), et le test axe des pages e2e conservé. - Le visuel par story : une capture en clair et en sombre de chaque story, dans le conteneur
Linux, par la spec
e2e/storybook.spec.tsque STY1 a posée ; les stories sont la galerie avant/après du plan 19 au grain du composant. - Un seul outil de plus : l'addon Vitest de Storybook, qui exécute les stories dans Chromium par Playwright, déjà présent. Pas de Jest, pas de second runner.
- Une mesure : un compteur des composants sans story et sans
play, en avertissement puis en erreur, comme le compteur de style du plan 19 ; un cliquet de couverture Vitest par paquet.
0.3 Non-objectifs
- Pas de refonte des tests unitaires existants (1 591 tests, 154 fichiers) : ils restent, on n'ajoute que ce qui manque.
- Pas de tests de rendu Remotion image par image hors des goldens existants (16 clichés).
- Pas de tests de charge, pas de tests de contrat réseau : Récit n'a pas de serveur.
- Pas de couverture à 100 % comme objectif chiffré : la cible est « chaque composant a sa story,
chaque comportement son
play», mesurée par le compteur de §6, pas par un pourcentage de lignes.
0.4 La pyramide cible
| Niveau | Quoi | Outil | Où ça tourne |
|---|---|---|---|
| Unitaire | logique pure : parseurs, config, navigation du deck, horloge motion, scripts | Vitest (node, happy-dom au besoin) | pnpm test |
| Composant | chaque story se rend, ses args tiennent, aucune erreur console | Storybook + addon Vitest, navigateur Chromium | pnpm test (projet storybook) |
| Interaction | fonctions play : clavier, souris, focus, états | storybook/test (userEvent, within, expect) | idem |
| Accessibilité | axe sur chaque story ; axe sur trois pages e2e | addon-a11y en mode test ; @axe-core/playwright | idem ; conteneur e2e |
| Visuel | une capture par story, clair et sombre ; les pages de site ; les diapositives | Playwright sur storybook-static et sur les sites | conteneur e2e (-linux.png) |
| Flux | ce qu'une story ne peut pas prouver : recherche puis navigation, thème persistant, tiroir mobile, deck | Playwright, specs e2e/*.spec.ts sans capture | conteneur e2e |
| Films | un cliché par bloc, deux films, deux thèmes | goldens de @recit/motion-render (pixelmatch, 0,2 %) | build.yaml « Motion goldens » |
| Export | PDF d'un deck : nombre de pages, dimensions | deck-features.spec.ts (existant) | conteneur e2e |
1. Inventaire avant
1.1 L'outillage Vitest
- Racine
vitest.config.ts: trois globs de projets (packages/!(formats|integrations|tools),packages/{formats,integrations,tools}/*,scripts), couverturev8avec quatre rapporteurs dans./coverage, sans seuil. Scripts :pnpm test=vitest run --typecheck,test:coverage;e2eest un projet nx à part (recit-e2e,scope:test). - Configs de projet :
packages/coreetsite-stories(includedes*.test-d.tspour le typecheck),packages/recit,packages/tools/site-kit,packages/site(globals,setupFiles: vitest.setup.tsqui étendexpectavec@testing-library/jest-domet appellecleanup()après chaque test,typecheckpartsgosurtsconfig.app.json). - Environnements : node par défaut ;
happy-dom21.0.4 déclaré par fichier (@vitest-environment happy-dom) dans 21 fichiers depackages/site; aucunjsdom. - Dépendances de test (catalogue) :
@testing-library/dom10.4.2,jest-dom6.10.0,react16.3.3,user-event14.6.7, utilisées parpackages/siteseulement ;@vitest/coverage-v84.1.11 ; Vitest 4.1.11 ;@axe-core/playwrightà la racine ; Playwright 1.64.1. - Volume (29/10) : 154 fichiers, 1 591 tests, en 2 min 30 environ dans
pnpm verify.
| Projet | Fichiers de spec | Ce qu'ils couvrent |
|---|---|---|
core | 23 | parseur, schémas, config (app: inclus), conversion source, JSON Schema |
site | 56 | 24 .test.tsx de composants (ci-dessous), config, routes, SSR, plugins, hooks |
motion | 16 | schéma, timeline, adaptateurs |
site-stories | 11 | plugin, config de site, i18n, composants de récit, motion |
deck | 10 | navigation, first-render (chaîne SSR), presentation-a11y (role="application"), mdx-slide, transitions, peer-messenger |
app | 8 | config Tauri, coquille, serveur, Android, iOS, deck |
motion-blocks | 6 | player, render, horloge, thèmes |
cli, mcp | 5 + 5 | commandes, bundling, serveur MCP |
components | 4 | code-block, mermaid-render, presets, slides (rendu HTML des composants de diapositive) |
site-kit | 4 | config, énumérations, sites, workspace ; aucun composant |
scripts | 6 | frontières, version plans, e2e-linux, paquets publiés, workflows, galerie |
theme, recit | 1 + 1 | thèmes, point d'entrée |
motion-render | 0 | les goldens (§1.3) tiennent lieu de test |
1.2 Les tests de composants existants
Vingt-quatre .test.tsx dans packages/site/src : app/entry.server, processRoutes,
createRedirectRoutes, lib/components/BrowserWindow, Footer, Header, LandingPage, Main,
Markdown, MobileTopNavigation, NotFoundPage, PluginHeads, ScrollableTable, Search,
Slot, TopNavigation, navigation/Navigation, core/transform-config, hooks/useEvent,
plugins/markdown/MdxPage, search-inkeep, search-pagefind, ui/CodeBlock, ui/Stepper. Chacun
monte son harnais à la main : MemoryRouter ou createMemoryRouter + RouterProvider,
QueryClientProvider avec un QueryClient neuf, le contexte de config moqué
(Header.test.tsx:30-45, Footer.test.tsx:15-42). Aucun helper de rendu partagé, aucune story
réutilisée. Dans deck, first-render.spec.tsx et presentation-a11y.spec.tsx rendent par
renderToString et lisent le HTML ; components/src/__tests__/slides.spec.ts vérifie le HTML des
composants de diapositive. Rien ne teste un comportement au clavier ou à la souris hors e2e.
1.3 Les goldens motion
packages/formats/motion-render/scripts/goldens.mjs : un cliché par bloc au milieu de chaque scène,
pour deux films de démonstration (warm-editorial 16:9, saas-product 9:16), rendus depuis le
film.json et depuis le jumeau Markdown ; 16 PNG dans fixtures/goldens, diff pixelmatch à
0,2 % de pixels, les diffs écrits dans fixtures/goldens-diff ; étape « Motion goldens » de
build.yaml, diffs envoyés en artefact. C'est le seul test visuel hors Playwright.
1.4 La suite e2e après STY1
- 15 specs dans
e2e/, 443 références-linux.png(213 avant STY1), trois projets Playwright :chromium(1280×720),chromium-dark(tous lessite-*.spec.ts,colorScheme: "dark"et le choix mémorisétheme/recit-theme, suffixe-dark),mobile(390×844, tests@mobiledesite-docs, suffixe-mobile) ;maxDiffPixelRatio0,02, animations désactivées ; rapporteurjsondanstest-results/linux/report.json. storybook.spec.ts: les 16 stories deindex.json, en clair et en sombre pariframe.html?id=…&globals=theme:…, servies depuissites/storybook/storybook-staticsur le port 4380 ; 32 références ; la liste des ids est codée en dur dans la spec (STORIES), à maintenir à chaque story.accessibility.spec.ts: axe WCAG 2 A/AA et 2.1 A/AA sur trois URL.- Un passage complet en conteneur : 7 à 8 min (copie 1 s, installation 25 à 45 s, construction 2
à 2 min 30, tests 4 min 20 à 5 min 20 pour 444 tests) ; galerie
node scripts/screenshot-gallery.js --serve <port>; règle du skille2e-baselines: deux passages, régénération partest:e2e:update:linux <spec>seulement.
1.5 Storybook
sites/storybook(scope:site, privé) : Storybook 10.6.3 (10.6.5 publié),react-vite, addonsdocs,a11y(a11y.test: "error"),themes(withThemeByClassName,light: "",dark: "dark"),typescript.reactDocgen: "react-docgen",tags: ["autodocs"],controls.expanded. Scriptsdev(port 6006,--no-open),build(storybook-static),typecheck. Construit parpnpm build(nx) : la spec e2e le sert.- Stories : 9 fichiers, 16 stories, toutes dans
packages/components/src/slides/(Callout,CodeBlock,CodeGroup,Cover,Grid,Media,Mermaid,Points,Quote), titresSlides/<Composant>,satisfies Meta<typeof X>,argsetargTypesrenseignés (Callout.stories.tsx:5-16). Le glob demain.tsne lit quepackages/components. - Décorateurs :
withSlide(cadre 16:9,SlideMotion,parameters.slide.fit) avec deuxstyleinline et deux classes (preview.tsx:14-32, le plan 19 STY6.1 le réécrit en module) ;withThemeByClassName.preview.cssimporte Tailwind, les polices, les tokens, le pont Tailwind,page.css,deck.css, et déclare@sourcesurpackages/components/src. - Absents : addon Vitest, test-runner, fonctions
play,storybook/test,composeStories, presets de viewport, décorateur de fournisseurs de site (routeur, query, config), stories horspackages/components.
1.6 Sans test et sans story
| Surface | Composants | Test aujourd'hui |
|---|---|---|
packages/site/src/lib/ui | 54 composants (57 fichiers), dont 27 sans importeur que STY3 supprime ; 27 restent (§4.1) | CodeBlock.test.tsx, Stepper.test.tsx |
packages/site/src/lib/components (+ navigation) | 50 fichiers : Header, Footer, Banner, Search, Pagination, ThemeSwitch, Mermaid, Markdown, Typography, Heading, 12 de navigation… | 14 .test.tsx de rendu, aucun comportement |
packages/site/src/lib/plugins | MdxPage, PagefindSearch, ResultList, IndexingDialog, search-inkeep | 3 .test.tsx |
packages/formats/deck | 10 composants : Presentation, SlideStage, SlideFrame, PresenterView, MobileRemoteView, RemoteQrCodeModal, AnnotationCanvas, DevHud, HtmlSlide, SceneContent | 10 specs sans interaction, e2e deck-features |
packages/formats/motion-blocks | 8 blocs (chapter, compareBars, list, stat, statement, title, uiMock, uiScene), player | player.test.tsx, render.test.tsx, goldens |
packages/components | 9 avec story, 6 sans : Card, Columns/Col, SlideImage, Badge, Kbd, Step (mdx/builtins.tsx), SlideMotion | slides.spec.ts (HTML) |
packages/tools/site-kit | Cards, ExampleHeader, SourceFile, Tutorial | aucun |
| Sites et exemples | www (Hero, FormatGrid, OneSource), docs/StatusBadge, motion/VideoDownloads, components/FormatSupport, deck-mdx (Counter, Timeline), deck-showcase/Metric | captures de pages seulement |
1.7 Le budget CI
build.yaml tourne sur ubuntu-latest dans l'image mcr.microsoft.com/playwright:v1.64.1-noble :
pnpm check, pnpm test, publint et taille des bundles, goldens motion, pnpm test:e2e, rapport
Playwright en artefact ; un second job vérifie les liens. Pas de durée mesurée dans le dépôt ; sur
la machine de travail, pnpm verify prend 3 min 20 et un passage e2e 7 à 8 min : l'ordre de
grandeur du job est 12 à 15 min. Chromium est dans l'image : les tests de stories en navigateur
n'y ajoutent aucune installation.
2. Cible : la pyramide et l'outil
2.1 Les trois façons de tester une story, évaluées
| Option | Ce que ça donne | Dépendances | Verdict |
|---|---|---|---|
@storybook/addon-vitest : chaque story devient un test Vitest, exécuté dans Chromium (mode navigateur de Vitest, fournisseur Playwright) ; play et a11y compris | rendu réel (mise en page, portails, focus), un seul runner avec les tests unitaires, projet Vitest à part, rapport unifié, storybook/test fourni par storybook | @storybook/addon-vitest 10.6.x, @vitest/browser-playwright 4.1.x (Vitest 4.1 du dépôt) ; Chromium déjà là | Retenu. Deux dépendances de dev, aucun runner nouveau, le navigateur est celui des e2e |
@storybook/test-runner 0.26 : Jest + Playwright qui visite chaque story de storybook-static | rendu réel aussi, mais un second runner (Jest) et un second rapport, Storybook construit avant | @storybook/test-runner, jest, jest-playwright | Écarté : double la pile de test (règle « une seule stack »), plus lent (build + visite) |
Stories portables : composeStories de @storybook/react-vite dans un test Vitest happy-dom | réutilise une story comme fixture d'un test unitaire, sans navigateur | aucune | Complément, pas la base : happy-dom n'a ni mise en page ni focus fiable ; réservé à la logique qui a besoin d'une story comme entrée (deck, tableaux) |
Décision : addon Vitest, les stories portables en complément. Le mode navigateur tourne
headless ; en local il faut une fois pnpm exec playwright install chromium (déjà requis par
pnpm test:e2e, documenté dans CONTRIBUTING par TST5).
2.2 Le projet Vitest storybook
sites/storybook/vitest.config.ts(nouveau) :defineProjectavec le pluginstorybookTest({ configDir: ".storybook" }),test.browser = { enabled: true, headless: true, provider: playwright(), instances: [{ browser: "chromium" }] },setupFilesavec levitest.setup.tsde Storybook (setProjectAnnotationsdes annotations depreview.tsx).vitest.config.tsracine :sites/storybookajouté auxprojects;pnpm testl'exécute avec les autres,pnpm test --project storybookl'isole. Les stories n'entrent pas dans la couverture v8 des paquets (fichiers*.stories.tsxexclus), mais le code des composants qu'elles rendent, si : c'est ce qui fait monter la couverture depackages/sitesans écrire un test par composant.- Tags :
parameters.a11y.test = "error"(déjà) fait échouer une story sur une violation axe ; une story qui n'a pas de sens en test portetags: ["!test"](jamais pour cacher un échec : la raison dans la story). storybook/test:expect,within,userEvent,fn,waitFor;fn()pour chaque rappel (onClick,onChange) afin de l'asserter.
2.3 Le visuel
e2e/storybook.spec.ts passe de la liste codée en dur à la lecture de storybook-static/index.json
: chaque story reçoit ses deux captures sans toucher à la spec ; les stories qui se stabilisent
tard (Mermaid attend mermaidReady, le Quote sa transition) portent un tag (wait-mermaid,
wait-motion) que la spec lit dans index.json, qui n'expose pas les parameters. Les captures
suivent la règle du skill e2e-baselines (conteneur, deux passages, galerie, régénération par
spec). Une story qui change d'aspect pendant le plan 19 se régénère à la porte de la vague, après
revue de galerie : c'est le « comparatif avant/après » au grain du composant que l'utilisateur
demandait au plan 19.
2.4 Les flux
Les comportements qu'une story ne peut pas prouver seule (plusieurs pages, stockage, chargement
d'index) gardent une spec Playwright sans capture, dans e2e/ : recherche ouverte au clavier,
résultat choisi, page atteinte ; thème changé puis conservé au rechargement ; tiroir mobile ouvert,
lien suivi, tiroir fermé ; sommaire qui suit le défilement ; deck : flèches, ?slide=N, console
présentateur ouverte en seconde fenêtre, impression. Ce « filet comportemental » (TST-A) s'écrit
avant que le plan 19 ne touche ces composants (vague 2 de 20-multi-agents.md §4), contre les
rôles et les noms : il survit à la migration et la prouve.
3. La structure de Storybook
3.1 Arborescence des titres
| Titre | Source | Décorateurs |
|---|---|---|
Site/UI/<Composant> | packages/site/src/lib/ui/*.stories.tsx | withMantine, withTheme |
Site/Components/<Composant> | packages/site/src/lib/components/*.stories.tsx | withMantine, withTheme, withSite |
Site/Navigation/<Composant> | …/lib/components/navigation/*.stories.tsx | idem |
Site/Plugins/<Plugin> | …/lib/plugins/**/*.stories.tsx | idem |
Slides/<Composant> | packages/components/src/**/*.stories.tsx (existant) | withSlide, withTheme |
Deck/<Composant> | packages/formats/deck/src/**/*.stories.tsx | withDeck (un Story compilé en fixture), withTheme |
Motion/Blocks/<Bloc> | packages/formats/motion-blocks/src/blocks/*.stories.tsx | withFilm (StaticAnim, thème motion) |
Kit/<Composant> | packages/tools/site-kit/src/components/*.stories.tsx | withMantine, withTheme, withSite |
Sites/<site>/<Composant> | sites/*/src/*.stories.tsx, examples/*/components/*.stories.tsx | selon la surface |
Les globs correspondants entrent dans main.ts dès TST0, même vides : un fichier de story posé plus
tard apparaît sans configuration.
3.2 Décorateurs communs (sites/storybook/.storybook/decorators/)
withMantine:MantineProvideraveccreateRecitTheme(plan 19 STY2) et la feuille Mantine en couche ; avant STY2, uncreateTheme({}).withTheme: le mode de couleur parglobals.theme,withThemeByClassNamejusqu'à STY9 puiswithThemeByDataAttribute(data-mantine-color-scheme) ; la spec e2e lit le mêmeglobals.withSite: ce queSiteRootfournit, en fixtures —createMemoryRoutersur une route paramétrable (parameters.site.path),QueryClientProviderneuf, le contexte de config avecsites/storybook/src/harness/config.ts(unrecit.configde fixture, Lorem Ipsum), les slots,MDXProvider; les modules virtuels du framework (virtual:recit-config,virtual:recit-theme.css, navigation, routes) sont fournis par un plugin Vite demain.ts(viteFinal) qui les résout verssrc/harness/virtual/*— c'est le point dur de TST0, prouvé par la story piloteSite/Components/Header.withSlide: l'existant, réécrit en module par STY6.1 ;parameters.slide.fit.withDeck: unStorycompilé depuis une fixture Markdown (examples/deck-starter) et leDeckAppou laPresentationmontée à la diapositiveparameters.deck.slide.withFilm:AnimContextenStaticAnim,ThemeVarsdu thème motion choisi parglobals.motionTheme(warm-editorial,saas-product), cadre 16:9 ou 9:16.withReducedMotion:MotionConfig reducedMotion="always"etprefers-reduced-motionémulé pour les captures et lesplay(les transitions demotion/reactne sont pas ce qu'on teste).- Viewports : presets
mobile390×844,tablet768×1024,desktop1280×720, déclarés une fois ; une story mobile porteparameters.viewport.defaultViewport.
3.3 args, argTypes, autodoc
satisfies Meta<typeof X> et StoryObj<typeof meta> partout (le modèle est Callout.stories.tsx)
; args complets sur meta, chaque export ne pose que ce qui change ; argTypes avec control
pour les énumérations et action pour les rappels (fn()), options depuis les constantes du code
(CALLOUT_TYPES de @recit/core/browser, jamais recopiées) ; tags: ["autodocs"] global ;
parameters.docs.description en une phrase quand le nom ne suffit pas. Contenu Lorem Ipsum, jamais
de nom réel (règle des exemples).
3.4 Storybook et le paquet privé @recit/site
sites/storybook porte scope:site et peut dépendre de tout
(scripts/check-package-boundaries.js, ALLOWED.site) ; l'interdiction d'importer @recit/site ne
vaut que sous packages/** (biome.jsonc, noRestrictedImports). Les stories du framework vivent
à côté des composants dans packages/site/src avec des imports relatifs, et sites/storybook
ajoute @recit/site en devDependencies pour que le typecheck et le glob les voient ; nx reçoit
l'arête (règle ST-20). De même pour chaque site et chaque exemple dont Storybook lit une story
(sites/www, examples/deck-mdx…) : une devDependency par source de stories, sinon un build
affecté peut sauter Storybook.
4. Le catalogue des stories
Chaque ligne : les états (un export par état), les interactions (play), l'accessibilité (ce qu'axe
doit voir), le visuel (ce qui mérite une capture au-delà du défaut). Les composants que STY3
supprime (27 ui/ sans importeur) n'y sont pas.
4.1 Site/UI — les 27 primitives conservées (TST2)
| Composant | États | Interactions (play) | A11y | Visuel |
|---|---|---|---|---|
Button, ButtonGroup | variantes, tailles, icône, désactivé, chargement, asChild/lien | clic (fn), Entrée et Espace, désactivé ne déclenche pas, focus visible | nom accessible, aria-disabled | focus ring, groupe |
Badge, Kbd | variantes | — | contraste | défaut |
Toggle | pressé / non, désactivé | clic bascule aria-pressed, Espace | aria-pressed | les deux états |
Input, InputGroup, Textarea, Label | vide, valeur, invalide, désactivé, avec addon | saisie (userEvent.type), onChange appelé, label clique le champ | association label/champ, aria-invalid | invalide |
Separator | horizontal, vertical, décoratif | — | role="separator" ou none | — |
Card | en-tête, contenu, pied, cliquable | — | titre | défaut |
Alert, Callout | chaque type/couleur, avec et sans titre, long contenu | — | role="alert" ou note | tous les types |
Dialog, Drawer | fermé, ouvert, avec formulaire, non fermable par clic extérieur | ouvrir, Échap ferme, clic extérieur, focus piégé puis rendu au déclencheur | aria-modal, titre, focus | ouvert (clair et sombre) |
Popover, Tooltip | fermé, ouvert, positions | survol et focus ouvrent le tooltip, clic ouvre le popover, Échap ferme | aria-describedby, role="tooltip" | ouvert |
DropdownMenu | items, séparateurs, raccourcis, sous-menu, désactivé | ouvrir au clic, flèches, Entrée sélectionne (fn), Échap ferme | role="menu", menuitem | ouvert |
Command (→ Spotlight) | vide, résultats, aucun résultat, groupes | saisie filtre, flèches, Entrée choisit, Échap ferme, Ctrl+K | role="dialog", listbox/option | ouvert avec résultats |
Collapsible | fermé, ouvert | clic bascule, aria-expanded | aria-expanded, aria-controls | les deux |
NavigationMenu | items, actif, déroulant | survol et clavier | role="navigation" | déroulé |
CodeBlock, EmbeddedCodeBlock | langage, titre, lignes surlignées, long, bouton copier | copier écrit dans le presse-papiers (navigator.clipboard moqué), retour visuel | bouton nommé | surlignage, sombre |
CodeTabs, CodeTabPanel | 2 et 5 onglets, onglet mémorisé | clic et flèches changent d'onglet, aria-selected | role="tablist", tab, tabpanel | onglet actif |
SyntaxHighlight | chaque langue configurée, thème clair et sombre | — | contraste des tokens | les deux thèmes |
Stepper | 1, 3 et 10 étapes, étape courante | — | liste ordonnée | défaut |
4.2 Site/Components, Navigation, Plugins (TST3)
| Composant | États | Interactions | A11y |
|---|---|---|---|
Header, TopNavigation, HeaderNavigation | logo, liens, actif, avec et sans recherche, bannière, mode sombre | lien actif marqué, ThemeSwitch bascule le mode (globals non requis), recherche ouvre | banner, navigation nommée |
MobileTopNavigation, MobileTopNavigationDrawer | fermé, ouvert, arborescence profonde | bouton ouvre, lien ferme, Échap ferme, focus piégé | aria-expanded, dialog |
Footer, Banner | 1 à 3 colonnes, logo, variables, bannière fermable | fermer la bannière, mémorisation | contentinfo |
Search, PagefindSearch, ResultList, IndexingDialog | fermé, ouvert, vide, résultats (index Pagefind de fixture), indexation en cours | Ctrl+K, saisie, flèches, Entrée navigue (fn sur le routeur), Échap | combobox, listbox |
Sidebar, NavigationItem, SidebarToggle, Toc | plié, déplié, item actif, catégories imbriquées, sommaire à 3 niveaux | plier/déplier, clavier, le Toc suit IntersectionObserver (moqué) | tree ou list, aria-current |
Pagination, Anchor, CategoryHeading | première, milieu, dernière page ; ancre survolée | lien d'ancre copie l'URL | nav nommée |
PageProgress, Spinner | 0, 50, 100 % | — | progressbar |
BrowserWindow, Framed | avec URL, sans, contenu long | — | — |
ScrollableTable, InlineCode, Markdown, Mermaid, LanguageIcon | tableau large, code inline, Markdown riche, diagramme, erreur Mermaid | défilement horizontal au clavier | table avec en-têtes |
NotFoundPage, ErrorPage, DeveloperHint | 404, erreur avec et sans détail | — | h1 |
MdxPage | page avec sommaire, sans, avec métadonnées, boutons « copier en Markdown » | menu « ouvrir dans ChatGPT/Claude » (fn), copie | main, article |
Typography, Heading, MdxComponents (TST5, après STY5) | chaque niveau, prose complète (titres, listes, tableaux, code, citations) | ancres des titres | hiérarchie des titres |
4.3 Slides (TST1), Deck et Motion (TST4a), Kit et Sites (TST4b)
| Surface | Composant | États | Interactions |
|---|---|---|---|
| Slides | les 9 existants, réécrits ; Card, Columns/Col, SlideImage, Badge, Kbd, Step, SlideMotion | chaque variante, fit, contenu long, image manquante | CodeGroup : onglets ; CodeBlock : copier ; Mermaid : rendu puis erreur |
| Deck | Presentation (dans withDeck) | diapositive 1, milieu, dernière, mode ?print=1, notes | flèches, Espace, Home/End, Maj+D et c (stylo, effacer), s ouvre la console (ouverture moquée), ?slide=N |
| Deck | SlideStage, SlideFrame, HtmlSlide, SceneContent | 16:9 et 4:3, à l'échelle dans trois tailles de cadre, fond, progression | redimensionnement du cadre (ResizeObserver moqué) recalcule l'échelle |
| Deck | PresenterView | diapositive courante et suivante, notes, minuteur à 0 et après 10 min | touches de navigation, minuteur démarre et se remet à zéro |
| Deck | MobileRemoteView, RemoteQrCodeModal, AnnotationCanvas, DevHud | connecté, déconnecté, QR affiché, tracé, HUD avec diagnostics | boutons précédent/suivant (fn), tracé par pointeur, effacer |
| Motion | les 8 blocs dans withFilm | chaque thème, 16:9 et 9:16, contenu minimal et maximal | — (état final StaticAnim ; le mouvement reste aux goldens) |
| Motion | player | en pause, en lecture, fin | lecture/pause, barre de progression |
| Kit | Cards, ExampleHeader, SourceFile, Tutorial | 1 à 6 cartes, en-tête avec et sans badge, fichier long, tutoriel à 5 étapes | — |
| Sites | www/Hero, FormatGrid, OneSource, docs/StatusBadge, motion/VideoDownloads, components/FormatSupport, deck-mdx/Counter, Timeline, deck-showcase/Metric | défaut, variantes | Counter : incrémente ; Timeline : étape active |
5. Conventions
5.1 Fichiers
X.stories.tsxà côté deX.tsx; un fichier par composant, un export par état, les interactions dans la story qui les concerne.X.test.tsxseulement pour ce qu'une story ne couvre pas (logique sans DOM, SSR parrenderToString) ; un test qui a besoin d'un composant monté réutilise la story (composeStories) au lieu de remonter un harnais.- Les 24
.test.tsxdepackages/sitequi ne font que rendre migrent vers des stories (TST3) ; ceux qui testent la logique (transform-config,useEvent,processRoutes, SSR) restent. - Pas de dossier
__stories__: la story suit le composant, comme le module CSS du plan 19.
5.2 Ce qu'une story ou un test affirme
- Des rôles et des noms (
getByRole("button", { name: /copy/i })), jamais une classe, jamais un sélecteur CSS, jamais un texte de classe de module. - Aucun snapshot de DOM (
toMatchSnapshotsur du HTML interdit) : un snapshot ne dit pas ce qui compte ; le visuel est la capture, le comportement est leplay. data-testidinterdit sauf sur un élément sans sémantique et sans texte (un cadre de diapositive, un canevas), listé dansscripts/check-stories.js; undata-testidajouté sans cette entrée fait échouer le compteur.- Une classe de module s'affirme en important
classesdans le test et en vérifianttoHaveClass(classes.open): le nom haché ne s'écrit jamais en dur ; cela ne sert qu'aux états sans rôle (open/closedd'un conteneur), et leplaypréfèrearia-expanded. - Les rappels sont des
fn()d'argset s'affirment partoHaveBeenCalledWith. - Le presse-papiers,
IntersectionObserver,ResizeObserver,matchMedia,localStorageetBroadcastChannelsont moqués dansvitest.setup.tsde Storybook, une seule fois. - Aucune erreur console pendant une story : le harnais échoue sur
console.error(le React #418 intermittent connu s'observe en e2e, pas ici : le rendu Storybook n'hydrate pas).
5.3 La loi du plan 19 s'applique aux stories
Une story est un .tsx de packages/ ou de sites/storybook : le compteur
scripts/check-style-rule.js la lit. Pas de style={{ display: "grid" }} pour disposer les
variantes (Callout.stories.tsx:26 aujourd'hui) : un décorateur withGrid adossé à
decorators/grid.module.css, ou parameters.layout. Les décorateurs sont des composants comme les
autres : un module chacun.
5.4 Nommage et langue
Titres de stories en anglais (Site/UI/Button, exports Default, Disabled, Loading,
WithIcon), texte des stories en Lorem Ipsum, commentaires en anglais comme le code. Les play
s'appellent par le comportement (opens on click and closes on Escape), pas par l'implémentation.
6. Mesure
6.1 scripts/check-stories.js (TST0, en avertissement ; TST5, en erreur)
Entré dans check:other. Pour chaque fichier de composant des surfaces de §3.1 (un .tsx qui
exporte un composant React, hors *.test.tsx, *.stories.tsx, index.ts, hooks, utilitaires), il
signale : (1) pas de X.stories.tsx à côté ; (2) une story sans play pour un composant
interactif (il reçoit onClick, onChange, onOpenChange, ou rend un button, input, a,
dialog, menu) ; (3) data-testid hors liste ; (4) toMatchSnapshot sur du HTML ; (5)
tags: ["!test"] sans commentaire la ligne au-dessus. Compte par surface, total, baseline
scripts/stories-baseline.json qui refuse toute hausse ; --strict à TST5. Test
scripts/__tests__/check-stories.spec.ts.
6.2 Le cliquet de couverture
test:coverage mesure déjà ; TST0 note la couverture par paquet dans le journal (lignes, branches)
; TST5 pose dans chaque vitest.config.ts de projet coverage.thresholds au niveau mesuré
(arrondi à l'unité inférieure), avec autoUpdate: true : la couverture ne peut que monter. Pas
d'objectif chiffré : le compteur de §6.1 dit ce qui manque, la couverture dit que rien ne régresse.
6.3 Ce qui est compté comme « fait »
| Indicateur | Avant (29/10) | Après TST5 (cible) |
|---|---|---|
| Fichiers de story | 9 | environ 110 (27 ui, 45 framework, 16 slides, 10 deck, 9 motion, 4 kit, 9 sites) |
| Stories (exports) | 16 | 400 à 500 |
Stories avec play | 0 | une par composant interactif (environ 60) |
Captures Storybook -linux.png | 32 | 800 à 1 000 (clair et sombre) |
| Specs e2e de flux sans capture | 2 (deck-features, accessibility) | 4 (+ site-behaviour, deck-behaviour) |
| Composants sans story (compteur) | environ 120 | 0 |
7. Câblage CI et durées
| Étape | Commande | Où | Durée estimée |
|---|---|---|---|
| Unitaires et stories | pnpm test (projets Vitest, storybook inclus) | pnpm verify, build.yaml « test » | + 1 à 2 min pour 400 stories dans Chromium |
| Compteur de stories | node scripts/check-stories.js | pnpm check | secondes |
| Build Storybook | nx run recit-storybook:build | pnpm build (déjà) | environ 1 min |
| Captures Storybook | playwright test e2e/storybook.spec.ts | conteneur e2e (-linux.png) | + 4 à 8 min à 1 000 captures ; par surface en vague |
| Flux | playwright test e2e/*-behaviour.spec.ts | conteneur e2e | + 1 min |
| Goldens | inchangé | build.yaml | inchangé |
pnpm verify gagne 1 à 2 min ; le job build.yaml passe de 12–15 à 18–25 min. Si les captures
Storybook dépassent 5 min, la spec se découpe par surface (storybook-site, storybook-slides, …)
et les vagues ne rejouent que la leur, comme 20-multi-agents.md §3.2 le prévoit pour les sites.
8. Lots
Chaque lot nomme ses fichiers possédés, ce dont il dépend, ce qu'il fournit, sa
vérification et sa vague dans le découpage de 20-multi-agents.md §4 (les lots TST
s'intercalent dans les vagues STY : un lot TST n'entre dans une vague que si tous ses fichiers sont
libres de tout lot STY de cette vague). Tailles S, M, L. Règles de 20-multi-agents.md §3 : un lot,
un agent, ses fichiers ; relire avant d'écrire ; jamais de git ; note ### TSTn — <titre> — <date>
en fin de journal.md ; BROWSER=none pour tout serveur local.
TST-A — Le filet comportemental e2e (M), vague 2
Dépend de : rien (les sites sont construits à chaque passage). Parallèle avec : STY2, STY6.1, STY7a. Agent frais.
Fichiers : e2e/site-behaviour.spec.ts (nouveau), e2e/deck-behaviour.spec.ts (nouveau),
e2e/support.ts (helpers ajoutés seulement), la note de journal.
- A.1 — Site (
sites/docsen preview) :Ctrl+Kouvre la recherche, saisie, flèche, Entrée mène à la page ; leThemeSwitchpasse en sombre et le rechargement le garde ; le tiroir mobile (projetmobile) s'ouvre, un lien navigue, le tiroir est fermé ; le sommaire marque la section visible après défilement ; le bouton copier d'un bloc de code remplit le presse-papiers (permission accordée au contexte) ; les onglets deCodeTabschangent au clavier ; la pagination précédent/suivant. - A.2 — Deck (
examples/deck-starterparrecit-site previewd'un site qui le publie, ou lepresent/*desites/presentation) : flèches, Espace,Home/End,?slide=N,souvre la console présentateur (context.waitForEvent("page")), la console suit la diapositive, mode?print=1: autant de.print-slideque de diapositives. - A.3 — Aucune capture : assertions de rôle, d'URL, de
localStorageet de presse-papiers ; deux passages en conteneur verts.
Fournit : la preuve comportementale qui traverse le plan 19 ; chaque vague STY rejoue ces deux specs à sa porte.
Vérification : pnpm test:e2e:linux e2e/site-behaviour.spec.ts e2e/deck-behaviour.spec.ts deux fois
; pnpm -F recit-e2e typecheck ; pnpm check.
TST0 — Le socle Storybook test (M), vague 3
Dépend de : STY6.1 (qui réécrit .storybook/* sans Tailwind et pose le module de withSlide),
STY0a (Mantine dans le framework). Parallèle avec : STY3a-c, STY6.2, STY7b — STY6.2 possède
packages/components/src/**, TST0 n'y touche pas. Agent frais avec un brief long : la vague 3 a
déjà ses trois agents lourds (STY3a-c), et §2, §3 et §1 de ce plan suffisent à décrire le harnais.
Fichiers : sites/storybook/.storybook/main.ts (addon, globs de §3.1, plugin des modules virtuels),
preview.tsx (décorateurs de §3.2 importés), .storybook/decorators/* (nouveau, un module CSS
chacun), .storybook/vitest.setup.ts (nouveau), sites/storybook/vitest.config.ts (nouveau),
sites/storybook/package.json (addon, @recit/site en dev, test script), pnpm-workspace.yaml
(catalogue : @storybook/addon-vitest, @vitest/browser-playwright ; Storybook aligné sur 10.6.5
si l'addon l'exige), pnpm-lock.yaml, vitest.config.ts racine (projet), package.json racine
(check:other), sites/storybook/src/harness/** (config de fixture, modules virtuels, index
Pagefind de fixture), packages/site/src/lib/components/Header.stories.tsx (la story pilote du
site, fichier nouveau que STY4a ne possède pas en vague 3), e2e/storybook.spec.ts (lecture de
index.json), scripts/check-stories.js, scripts/stories-baseline.json,
scripts/__tests__/check-stories.spec.ts, .github/workflows/build.yaml (rien si pnpm test
suffit ; sinon une étape), la note de journal.
- 0.1 — L'addon et le projet Vitest (§2.2) :
pnpm test --project storybookexécute les 16 stories existantes dans Chromium, a11y en erreur. - 0.2 — Les décorateurs de §3.2 et les presets de viewport ;
withMantinebranché sur le thème de STY2. - 0.3 — Le harnais du site :
withSite, le plugin des modules virtuels, la story piloteSite/Components/Headeravec unplay(le lien actif, l'ouverture de la recherche) qui passe dans Chromium ; c'est la preuve que les stories du framework sont possibles. - 0.4 —
storybook.spec.tslitindex.json: les 16 + 1 stories ont leurs captures, baseline régénérée à la porte de la vague. - 0.5 —
check-stories.jsen avertissement, baseline écrite, test ; couverture par paquet notée au journal (§6.2). - 0.6 — Durée de
pnpm testavant et après, notée.
Fournit : le runner, les décorateurs, le harnais, le compteur ; les lots TST1 à TST5 n'écrivent plus que des stories.
Vérification : pnpm test --project storybook ; pnpm test complet ;
pnpm -F recit-storybook build && pnpm -F recit-storybook typecheck ;
pnpm exec vitest run scripts/__tests__ ; pnpm check ;
pnpm test:e2e:linux e2e/storybook.spec.ts à la porte.
TST1 — Les stories de @recit/components (M), vague 4
Dépend de : TST0, STY6.2. Parallèle avec : STY4a-b, STY6.3a-b, STY8, TST2a-b. Agent frais.
Fichiers : packages/components/src/**/*.stories.tsx (les 9 réécrits selon §3.3 et §5.3, les 6
nouveaux de §1.6), sites/storybook/.storybook/decorators/grid.module.css si withGrid n'existe
pas encore (demander à TST0 sinon), la note de journal.
- 1.1 — Chaque composant : ses états ;
playpourCodeGroup(onglets),CodeBlock(copier),Mermaid(rendu, erreur),Step. - 1.2 —
slides.spec.tsréduit à ce que les stories ne disent pas (HTML des presets) ;code-block.spec.tsxréutilise la story parcomposeStories. - 1.3 — Compteur à zéro sur
packages/components.
Vérification : pnpm test --project storybook, pnpm exec vitest run packages/components,
node scripts/check-stories.js packages/components, captures à la porte.
TST2 — Les stories de Site/UI (L, deux agents), vague 4
Dépend de : TST0, STY3a-c. Parallèle avec : STY4a-b (qui possèdent lib/components, pas ui/),
TST1. Agents frais.
-
TST2a :
Button,ButtonGroup,Badge,Kbd,Toggle,Input,InputGroup,Label,Textarea,Separator,Card,Alert,Callout,Stepper,CodeBlock,EmbeddedCodeBlock,CodeTabs,CodeTabPanel,SyntaxHighlight— fichierspackages/site/src/lib/ui/<X>.stories.tsx. -
TST2b :
Dialog,Drawer,Popover,Tooltip,DropdownMenu,Command/Spotlight,Collapsible,NavigationMenu— idem ; les surcouches sont lesplayles plus riches (§4.1). -
2.1 — États et
playde §4.1 ;CodeBlock.test.tsxetStepper.test.tsxmigrés verscomposeStoriesou supprimés s'ils ne disent rien de plus. -
2.2 — Compteur à zéro sur
packages/site/src/lib/ui.
Vérification : pnpm test --project storybook, pnpm exec vitest run packages/site,
node scripts/check-stories.js packages/site/src/lib/ui, captures à la porte.
TST3 — Les stories du framework (L, deux agents), vague 5
Dépend de : TST0, STY4a-b. Parallèle avec : STY5a-b (qui possèdent Typography, Heading,
MdxComponents, main.css : TST3 ne les touche pas), TST4a-b. Agents frais.
- TST3a, pages et mise en page :
Header,TopNavigation,HeaderNavigation,MobileTopNavigation(+Drawer),Footer,Banner,PageProgress,Spinner,BrowserWindow,Framed,Anchor,Pagination,Search,DeveloperHint,CategoryHeading,NotFoundPage,ErrorPage,LanguageIcon,ScrollableTable,InlineCode,Markdown,Mermaid,ThemeSwitch,Slot—packages/site/src/lib/components/<X>.stories.tsx; les.test.tsxde rendu correspondants migrés ou supprimés (§5.1). - TST3b, navigation et plugins :
lib/components/navigation/*.stories.tsx,lib/plugins/markdown/MdxPage.stories.tsx,search-pagefind/*.stories.tsx(index de fixture du harnais),search-inkeep(story!test: widget tiers, raison écrite).
Vérification : comme TST2 sur packages/site/src/lib/components et lib/plugins ; pnpm test
complet ; captures à la porte.
TST4 — Deck, motion, kit, sites (M, deux agents), vague 5
Dépend de : TST0, STY6.3a-b, STY7b, STY8. Parallèle avec : STY5a-b, TST3a-b. Agents frais.
- TST4a, deck et motion :
packages/formats/deck/src/**/*.stories.tsx(withDeck),packages/formats/motion-blocks/src/blocks/*.stories.tsxetplayer.stories.tsx(withFilm),sites/storybook/.storybook/decorators/deck.tsxetfilm.tsxs'ils ne sont que des squelettes après TST0, la note de journal.first-render.spec.tsxetpresentation-a11y.spec.tsxrestent (SSR) ;player.test.tsxréutilise la story. - TST4b, kit, sites, exemples :
packages/tools/site-kit/src/components/*.stories.tsx(les six composants des sites y ont été déplacés : un site, c'est du Markdown et de la config),examples/{deck-mdx,deck-showcase}/components/*.stories.tsx(les globs sont dansmain.tsdepuis TST0 ; les exemples sont des fixtures e2e : Lorem Ipsum, rien d'autre ne bouge).
Vérification : pnpm test --project storybook,
pnpm exec vitest run packages/formats/deck packages/formats/motion-blocks packages/tools/site-kit,
pnpm -F @recit/motion-render goldens:check (rien ne doit bouger), compteur sur ces surfaces,
captures à la porte.
TST5 — Clôture (M), vague 6
Dépend de : STY5a (typographie), TST1 à TST4. Parallèle avec : STY9, STY10.2 (qui possède
CONTRIBUTING.md, NOTICE.md, sites/docs/sidebar.ts : TST5 lui demande une ligne de sidebar et
une phrase de CONTRIBUTING). Agent frais.
Fichiers : packages/site/src/lib/components/Typography.stories.tsx, Heading.stories.tsx,
packages/site/src/lib/util/MdxComponents.stories.tsx, scripts/check-stories.js (mode erreur,
baseline supprimée), les vitest.config.ts de projet (seuils de couverture, §6.2),
sites/docs/pages/documentation/testing.mdx (nouveau : la pyramide, écrire une story, un play,
lancer les tests, lire la galerie), .claude/skills/testing/SKILL.md (nouveau : la recette d'une
story et d'un play, les moqueries disponibles, les interdits de §5.2, la liste de contrôle), la
note de journal.
- 5.1 — Les trois stories de typographie après STY5a ; compteur à zéro partout, en erreur.
- 5.2 — Seuils de couverture posés au niveau mesuré,
autoUpdate(dans levitest.config.tsracine, un glob par paquet : Vitest ne lit les seuils que là). - 5.3 — Docs (
documentation/reference/testing.mdx), skill ;AGENTS.mdreçoit une ligne « Tests » dans la section « Styling » ou à côté (via STY10.2, même vague : demander). - 5.4 — Durées finales de
pnpm test, du build Storybook et des captures notées ; découpage destorybook.spec.tspar surface si > 5 min (§7) : six specsstorybook-<surface>.spec.ts.
Vérification : pnpm verify ; pnpm test:e2e:linux complet deux fois ; pnpm check en mode
strict.
8.1 Les vagues, imbriquées dans 20-multi-agents.md §4
| Vague (plan 20) | Lots STY de la vague | Lots TST ajoutés | Agents en plus | Condition d'entrée des TST |
|---|---|---|---|---|
| 2 | STY2, STY6.1, STY7a | TST-A | 1 frais | aucune : e2e sur les sites construits |
| 3 | STY3a-c, STY6.2, STY7b | TST0 | 1 frais | STY6.1 et STY0a vérifiés |
| 4 | STY4a-b, STY6.3a-b, STY8 | TST1, TST2a, TST2b | 3 frais | TST0 vérifié, STY3a-c et STY6.2 vérifiés |
| 5 | STY5a-b | TST3a, TST3b, TST4a, TST4b | 4 frais | STY4a-b, STY6.3a-b, STY7b, STY8 vérifiés |
| 5' | STY5c | — | — | (TST3-4 peuvent déborder ici : aucun fichier commun avec STY5c) |
| 6 | STY9, STY10.2 | TST5 | 1 frais | STY5a, TST1 à TST4 vérifiés |
Au plus six agents dans une vague (vague 5 : STY5a-b et TST3a-b, TST4a-b), ce qui dépasse le
plafond de cinq de 20-multi-agents.md §4 : la vague 5 se joue en deux temps (TST3a-b avec STY5a-b,
puis TST4a-b) si la limite d'usage le demande, sans changer les dépendances. Les portes restent
celles du plan 20 §3.2 : e2e en conteneur sur un arbre stable, galerie, revue ; les captures
Storybook s'y ajoutent. Neuf lots TST, douze agents, aucun nouveau jalon humain.
8.2 Version plan
Les stories et les specs ne changent aucun contrat publié ; sites/storybook est privé. Seuls
packages/components/package.json (script test, devDependency Storybook déjà là) et les
vitest.config.ts des paquets (seuils) bougent : pas de version plan pour ce plan, sauf si
TST4a exporte une fixture de @recit/deck pour withDeck (alors prerelease, dans le plan du plan
19).
8.3 Effort
| Lot | Taille | Stories (ordre de grandeur) | play |
|---|---|---|---|
| TST-A | M | — | 12 flux e2e |
| TST0 | M | 1 (pilote) | 1 |
| TST1 | M | 40 | 5 |
| TST2a-b | L | 120 | 25 |
| TST3a-b | L | 160 | 20 |
| TST4a-b | M + M | 90 | 10 |
| TST5 | M | 20 | 2 |
Environ 430 stories et 75 play, dix agents, répartis sur les vagues 2 à 6 du plan 19 : le plan 21
n'allonge pas le calendrier du plan 19, il remplit ses vagues.
9. Risques
| Risque | Parade |
|---|---|
| Le harnais du site (modules virtuels, config, routeur) est trop lourd à maintenir | TST0 le prouve sur Header avant tout ; les fixtures sont un recit.config ordinaire ; repli : stories du framework limitées à ui/ et aux composants sans config |
Mode navigateur de Vitest instable (portails, focus, timing des play) | waitFor et findBy* plutôt que getBy* après une interaction ; withReducedMotion ; retry: 1 sur le projet storybook seulement |
Durée de pnpm test et du job CI | mesure à TST0.6 et TST5.4 ; projet storybook isolable (--project) ; captures découpées par surface |
| Chromium absent sur un poste | message clair de Vitest ; pnpm exec playwright install chromium dans CONTRIBUTING ; le conteneur e2e l'a |
Versions : addon 10.6.5 contre Storybook 10.6.3 du catalogue, @vitest/browser-playwright contre Vitest 4.1 | TST0 aligne le catalogue (Storybook 10.6.5) et vérifie la matrice de versions ; une incompatibilité arrête TST0 et se note au journal |
| Les stories deviennent la seule doc des composants et vieillissent | le compteur, l'autodoc, la capture : une story fausse échoue |
play écrits contre l'implémentation (classes, structure) | §5.2 ; revue de diff ; le skill testing |
| Le React #418 intermittent brouille les portes | il ne concerne que l'hydratation e2e ; les stories n'hydratent pas |
Doublon entre une story et un .test.tsx de rendu | §5.1 : le test de rendu migre ou meurt ; composeStories pour le reste |
10. Questions ouvertes
pnpm testinclut-il le projetstorybook(proposé : oui, Chromium requis en local), ou un scripttest:storiesséparé pour garderpnpm verifysans navigateur ?- Les 24
.test.tsxde rendu depackages/site: migrer vers des stories (proposé) ou les garder en double le temps du plan 19 ? - Storybook pour les sites (
Sites/www/Hero…) : utile, ou leurs captures de page suffisent ? Proposé : oui pour les composants réutilisés par plusieurs sites (site-kit), au cas par cas pour les autres. - Captures Storybook : une par story en clair et en sombre (proposé, 800 à 1 000 images), ou
seulement les stories marquées
parameters.screenshot? - Seuils de couverture : cliquet au niveau mesuré (proposé) ou un plancher commun (70 % de lignes) ?
withDeck: exporter une fixture depuis@recit/deck(version plan) ou compiler la fixture danssites/storybookavec@recit/core(proposé, aucun contrat publié ne bouge) ?- Storybook publié : déployer
storybook-staticcomme un site (storybook.recit.dev) avec les autres ? Hors de ce plan, à noter dans07-domaines.