9 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| e702e21296 |
fix(layout): barre de navigation mobile en icônes seules (#105)
All checks were successful
Sur téléphone, l'onglet « Liste de courses » (16 caractères) passait sur 2 lignes dans un onglet à ~90px alors que « Planning »/« Recettes »/« Plus » tenaient sur 1 ligne : son bloc icône+libellé centré était plus haut, donc son icône visiblement plus haute que les autres. `AppLayout.scss` `.app-bottom-nav` : le `.label` est masqué visuellement (à la manière du rail desktop replié — `position: absolute; clip; …`), pas retiré du DOM, donc chaque `<NavLink>`/bouton garde son nom accessible (un lecteur d'écran annonce toujours « Planning », « Liste de courses »…) sans `aria-label` qui dupliquerait la chaîne i18n. Icônes légèrement agrandies (1.375rem → 1.5rem) puisqu'elles sont désormais seules. Tests : `layout.cy.ts` — l'onglet expose son `span.label` dans le DOM mais `not.be.visible`, l'icône `svg` visible (mise à jour de l'assertion qui attendait le libellé visible). `sidebar.cy.ts` / `planning-page.cy.ts` (nav desktop) inchangés. Suite layout/sidebar/planning revérifiée, 27/27. Closes #105 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
|||
| b8cbf2d777 |
fix(test): fige l'horloge dans le spec vue-mobile-jour de layout.cy.ts
All checks were successful
`PlanningDayView` ouvre sur le jour *courant* de la semaine affichée (`defaultDayIndexForWeek`, dérivé de `Date`). Le test « shows the one-day mobile view » ne figeait pas l'horloge : il ne passait que quand la CI tournait un lundi (UTC), et échouait les autres jours (`Curry de lentilles`, moqué sur « lundi », hors du jour affiché). `cy.clock(new Date(2026-08-17T09:00:00.000Z), [Date])` avant le `cy.visit` — même lundi de référence que `planning-page.cy.ts` ; `[Date]` seulement, les timers/debounces tournent toujours. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
|||
| 964269d3f3 |
feat(planning): vue mobile dédiée "un jour à la fois" pour la grille (#88)
Some checks failed
La grille planning (7 colonnes × 5 repas, min-width: 62rem) était le principal écran inaccessible sur téléphone : sous ce seuil elle ne se réorganisait pas, elle scrollait juste horizontalement — un tableau desktop rétréci, pas un vrai écran mobile. Sous le breakpoint phone (useIsMobileViewport()), PlanningPage bascule désormais entièrement sur PlanningDayView : un sélecteur de jour (jour précédent/suivant, borné au lundi/dimanche de la semaine affichée, pas de bouclage vers la semaine adjacente — ça reste le rôle des flèches du WeekNavigator) suivi des 5 repas du jour sélectionné, empilés en cartes. Le contenu de chaque case (pastilles de recettes + bouton "+") est mutualisé entre les deux layouts via une fonction non-hook partagée, mealCellBody, appelée aussi bien par MealCell (<td>, grille desktop) que par le nouveau MealCellRow (<div>, vue jour) — même logique de drop-target @dnd-kit (useDroppable) des deux côtés, donc le glisser- déposer d'un reste continue de fonctionner à l'identique sur mobile. Mise à jour de layout.cy.ts : son test #39 "la grille reste scrollable horizontalement sur phone" décrivait un comportement désormais remplacé par ce ticket — réécrit pour vérifier la bascule vers la vue jour au lieu du scroll horizontal. Closes #88 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
|||
| 967be6df4a |
test(cypress): convention de viewports telephone/tablette
Some checks failed
Ticket #83 du chantier UI mobile & tablette. Le repo n'avait aucun override de viewportWidth/Height ni pour e2e ni pour les tests de composants - tout tournait a la taille par defaut, jamais un vrai telephone/une vraie tablette. - cypress/support/viewports.ts : PHONE_VIEWPORT (390x844) et TABLET_VIEWPORT (900x1200), tailles Android reelles plutot que les presets iPhone/iPad de Cypress (appli Android uniquement) - dans les bandes de _breakpoints.scss ($phone/$tablet du ticket #91), pas collees au pixel de bordure. Commande cy.setViewport("phone" | "tablet") (pas de surcharge du cy.viewport natif). Importe par support/e2e.ts et support/component.ts, disponible dans les deux modes. - layout.cy.ts : les cy.viewport(...) en dur pour du telephone (deux tests ajoutes par #91, plus les deux plus anciens du passage #39) et le test "au-dessus du point de rupture telephone" migrent vers la commande partagee - ce dernier passe a un vrai viewport tablette (900px, dans la bande 641-1024) plutot qu'un 1000x700 arbitraire, prouvant au passage que le preset tablette fonctionne. - Nouveau cypress/component/Dialog.cy.tsx : premier test de Dialog en isolation (jusqu'ici seulement couvert indirectement via RecipePickerDialog) - verifie le plein-ecran sur telephone du ticket #91, qui n'avait pas encore son propre test, et prouve au passage que cy.setViewport fonctionne en mode composant. Trouvaille en verifiant : le mode composant de Cypress a son propre viewport par defaut, plus petit que celui du mode e2e (1000x660) - deja sous le seuil telephone. Le premier essai du test "desktop" de Dialog echouait pour cette raison (le CSS plein-ecran s'appliquait sans meme appeler setViewport). Corrige en fixant un viewport large explicite pour ce cas plutot que de compter sur un defaut implicite - note ajoutee a dev-environment-gotchas pour la prochaine fois. Verifie en local : tsc -b --force, biome check, build de prod, suite Cypress e2e complete (140/140) et composants (65/65, incluant les 2 nouveaux tests de Dialog.cy.tsx). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
|||
| 0fd4928efc |
feat(layout): socle UI mobile - nav, feuille et dialogs plein ecran
All checks were successful
Fondation du chantier UI mobile & tablette (#91) : jusqu'ici, toute adaptation mobile de ce repo etait du CSS pur sur le meme DOM (aucun composant ne branchait son JSX selon la largeur/plateforme). Ce ticket introduit le premier vrai branchement, et les primitifs que les 8 tickets suivants du chantier reutiliseront. - useIsMobileViewport() (apps/web/src/lib/) : point de verite unique, base sur matchMedia, live (reagit a un resize/une rotation). - _breakpoints.scss : $phone/$tablet Sass + mixins phone/phone-up/ tablet-down, remplacant les nombres magiques 640/1024 repetes en dur dans 6 fichiers (AppLayout, landing, recipes, recipe-picker-dialog, planning-page, dialog, tours-page). Les deux occurrences de 860px (landing hero, tours-page) sont deliberement laissees telles quelles - un collapse de grille 2 colonnes qui n'a rien a voir avec le breakpoint tablette du catalogue recettes, les unifier aurait change un comportement visuel reel sans raison. - useNativeDialogBehavior : mecanique (showModal/close event/clic exterieur) extraite de Dialog.tsx, partagee avec le nouveau BottomSheet.tsx (feuille mobile plein-largeur, meme fondation <dialog> natif que Dialog, juste ancree en bas). - AppLayout : sur telephone, la sidebar n'est plus reflow-ee en CSS en barre horizontale (l'ancien traitement) - elle est remplacee par une vraie barre d'onglets basse (Planning/Recettes/Liste de courses + Plus), le "Plus" ouvrant une BottomSheet combinant Parametres et Compte (deux dropdowns flottants separes cote desktop -> un seul point d'entree mobile, IA plus simple, un seul emplacement d'onglet). - dialog.scss : vrai plein-ecran (bord a bord, sans arrondi) sous le breakpoint phone au lieu d'une marge simplement reduite. Verifie en local : pnpm --filter web exec tsc -b --force, biome check, pnpm --filter web build, suite Cypress e2e complete (140/140) et composants (63/63) - y compris layout.cy.ts, reecrit pour tester la nouvelle barre basse (l'ancien test de la barre horizontale n'a plus de sens, ce traitement n'existe plus). Closes #91 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
|||
| a8d86c7099 |
feat(web): passe responsive téléphone pour le contenu des pages (#39 phase 3)
Réutilise la philosophie déjà en place pour la sidebar (défilement horizontal plutôt que compression illisible) au lieu d'un nouveau patron par page. Tout est strictement additif sous 640px — le rendu desktop est inchangé. - `AppLayout.scss` : `.app-content` passe de `--space-xl` (32px) à `--space-md` (16px) sous 640px — 64px de largeur utile récupérés sur un écran de ~375px. - `planning-page.scss` : la grille 7 jours défile déjà horizontalement (`overflow: auto` + `min-width: 62rem`) ; ce qui casse au tactile, c'est le `✕` de suppression d'une recette (`opacity: 0` hors survol) — épinglé visible + cible tactile agrandie sous 640px, idem le bouton « + ». - `dialog.scss` : `.dialog-panel` garde une gouttière latérale et gagne en hauteur utile sous 640px (le `--space-2xl` vertical est trop cher sur un écran court). - `recipe-picker-dialog.scss` : le split 2 colonnes forcé du catalogue (plus spécifique que le `@media` de recipes.scss) repasse à une colonne sous 640px. Tests : `layout.cy.ts` gagne un bloc « page content under 640px » — padding de `.app-content`, grille sur son propre scroll sans déborder la page, `✕` visible au tactile. 10/10 en local. Refs #39 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
|||
|
|
109dde9c7b
|
feat(shopping-list): liste de courses agrégée depuis le planning (#73)
GET /shopping-list?date= (shopping-list.service.ts/.routes.ts) somme les ingrédients de chaque recette planifiée sur la semaine, mis à l'échelle par les portions de chaque créneau (PlanningItem.portions / Recipe.portions), regroupés par paire (ingredientId, unitId) — jamais null contrairement à GET /planning, une semaine vide redescend en items: []. Côté web, ShoppingListPage rend cette liste groupée par rayon (même IngredientCategory que IngredientPicker), triée alphabétiquement en français à l'intérieur d'un rayon (shopping-list.ts, logique pure extraite du composant). WeekNavigator (flèches + calendrier) est extrait de PlanningPage vers features/planning/ pour être partagé entre les deux pages ; ses libellés migrent de planning.* vers common.weekNav.*/ common.calendar.*/common.days.*, plus génériques pour une page qui n'est plus seulement le planning. ComingSoonPage retiré (plus aucun appelant, Liste de courses avait le dernier stub restant). Tests : Mocha (agrégation, mise à l'échelle par portions, unités non fusionnées) + Cucumber (shopping-list.feature : liste vide, groupement/tri, navigation de semaine) + mise à jour de layout.cy.ts/planning-page.cy.ts pour le nouveau rendu. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> |
||
| 1c99e18ce7 |
fix(e2e): update layout test for settings-page's dropped max-width
layout.cy.ts still asserted .settings-page was a centered column
capped at 896px (max-width: 56rem) — that cap was removed in
|
|||
|
|
f1fefc1f38
|
refactor: sépare les tests Cypress en parcours utilisateur / layout / composants (#25)
* chore: point de départ pour le refactor des tests Cypress
Sépare les tests Cypress en trois catégories, comme discuté :
1. Parcours utilisateur (cypress/e2e/) — scénarios Gherkin/Cucumber,
pilotés par @badeball/cypress-cucumber-preprocessor@22.2.0 (validé
sur experiment/cucumber-cypress, mergée). Ex. "En tant
qu'utilisateur, je peux créer un compte".
2. Layout applicatif (nouveau dossier à définir) — specs Cypress
classiques (pas de Gherkin), cy.visit() sur une vraie page, mais
centrées sur la disposition/visibilité des éléments, indépendamment
d'un parcours utilisateur scripté.
3. Composants génériques (cypress/component/, nouveau) — vrai
Component Testing Cypress, composant React monté isolément (pas de
routeur, pas de backend). Composants concernés aujourd'hui :
components/ui/{Checkbox,Radio,Dialog}.tsx.
Premier pas : mise en place de l'infra Component Testing (config +
devServer Vite + adapter React 18), validée sur un composant simple
avant de construire le reste.
* feat(web): infra Cypress Component Testing, premier test sur CheckboxOption
Étape 1 du refactor (voir PR) : met en place le vrai mode Component
Testing de Cypress, séparé de l'e2e — monte un composant React isolé
(pas de routeur, pas de backend), pour tester les composants
génériques (components/ui/) indépendamment de tout parcours
utilisateur.
- cypress.config.ts : nouveau bloc `component` (devServer Vite, réutilise
vite.config.ts de l'appli — même plugin React, même Sass). Le hook
GPU-disable est factorisé (`disableGpu`) puisque e2e et component ont
chacun leur propre `setupNodeEvents`, pas de config partagée par défaut.
- cypress/support/component.ts + component-index.html : fichiers de
support standards Cypress CT — importe le vrai global.scss de l'appli
(les composants génériques sont stylés via lui, pas de CSS scopé à eux).
- cypress/component/CheckboxOption.cy.tsx : 4 scénarios sur
components/ui/Checkbox.tsx (rendu du label, reflet du prop `checked`
sur l'input natif + la classe `is-selected`, callback `onChange` avec
la valeur inversée, comportement contrôlé via un wrapper avec état).
Dépendance ajoutée, épinglée : @cypress/vite-dev-server@5.2.1 (dernière
version sans peer dependency cypress >=14 — 6.0.3+ l'exige explicitement,
on est sur cypress@13.17.0).
Testé en local jusqu'au mur GPU/Electron habituel (config + devServer
Vite chargent sans erreur) — l'exécution réelle du montage reste à
vérifier via la CI.
* ci: exécute les tests de composants Cypress
Sans ça, `cypress/component/CheckboxOption.cy.tsx` (commit précédent)
ne tournait jamais en CI : `pnpm --filter web e2e` lance `cypress run`
sans `--component`, donc uniquement la suite e2e par défaut.
- apps/web/package.json : nouveau script `cy:run:component`
- ci.yml : étape dédiée après `pnpm --filter web e2e`, sans
start-server-and-test (Cypress lance son propre dev server Vite en
interne pour le component testing, pas besoin d'attendre l'appli
comme pour l'e2e)
* test(web): refactor user journeys into Cucumber scenarios
Convertit les parcours utilisateur (goal-driven, "en tant que X je peux
Y") en scénarios Gherkin, en réutilisant l'infra Cucumber déjà validée
par le smoke test (PR #24). Retire le smoke test jetable maintenant
superflu.
8 fichiers .feature ajoutés, chacun avec son fichier de step definitions
au même basename (convention de découverte du préprocesseur — voir
login-smoke.ts) :
- auth.feature : inscription (succès, erreur validation, email déjà
pris), connexion (succès, identifiants invalides), déconnexion
- onboarding.feature : les 3 scénarios déjà couverts (wizard complet,
étapes sautées, rejoindre un foyer pendant l'onboarding) — dépend de
household-settings.ts et preferences.ts pour ses steps de
création/rejoint de foyer et de sélection de régime/allergies
- household-settings.feature : créer un foyer, rejoindre par code
d'invitation, renommer (autosave), retirer un membre, supprimer le
foyer, quitter le foyer
- account.feature : suppression de compte (mauvais mot de passe,
succès, annulation)
- recipe-form.feature : les 4 scénarios déjà couverts inchangés (ajout
d'ingrédient + création, régression crypto.randomUUID, exclusion/
réinclusion d'ingrédient, préchargement + édition d'une recette
existante)
- recipes.feature : bascule favori, suppression d'une recette
- preferences.feature : autosave du régime, autosave des allergies
- user-preferences.feature : changement de thème (autosave)
En contrepartie, les anciens .cy.ts perdent uniquement les it() migrés
vers Gherkin — les scénarios de layout/affichage pur (catalogue de
recettes, tabs, recherche, panneau de détail, sidebar, planning grid,
etc.) restent en Cypress classique, conformément au découpage
"parcours utilisateur (Cucumber) vs layout (Cypress pur)" déjà en
place pour les component tests. auth.cy.ts, onboarding.cy.ts et
recipe-form.cy.ts sont supprimés : 100% de leur contenu a migré.
Les commentaires "voir auth.cy.ts pour la justification" désormais
obsolètes (fichier supprimé) sont remplacés par une explication
autonome du mock cy.intercept.
Vérifié statiquement : les 246 steps Gherkin des 8 .feature résolvent
chacun vers exactement une définition (0 non résolu, 0 ambigu) et
`pnpm exec biome check` est propre sur tout cypress/. Reste à confirmer
en CI que les scénarios passent réellement (pas seulement qu'ils se
résolvent).
* fix(web): fix cross-feature step discovery and slash-alternation bug
La CI de la refonte précédente (commit
|