batchCooking/apps/web/cypress/e2e/recipe-form.feature
Nicolas 37cf6d4dcd fix(web): fix cross-feature step discovery and slash-alternation bug
La CI de la refonte précédente (commit aaace15) a échoué : la
découverte par défaut du préprocesseur ne charge, pour un fichier
`foo.feature`, QUE `foo.ts` (co-localisé, même basename) et
`cypress/support/step_definitions/**` — pas les autres `.ts` du
dossier `cypress/e2e/`. onboarding.feature référençait donc des steps
qui ne vivaient que dans preferences.ts, household-settings.ts et
auth.ts, introuvables lors de son propre run.

Déplace les steps réellement partagés entre plusieurs .feature vers
cypress/support/step_definitions/ (chargé pour toutes les features) :
- reference-data.steps.ts : mocks des listes de référence régimes/
  allergies (options ou vides) — partagé entre auth.feature et
  onboarding.feature
- household-mutations.steps.ts : création/adhésion à un foyer et leurs
  assertions — partagé entre household-settings.feature et
  onboarding.feature
- profile-mutations.steps.ts : sélection du régime, mise à jour des
  allergies et leur assertion — partagé entre preferences.feature et
  onboarding.feature

Les définitions d'origine sont retirées de auth.ts/household-
settings.ts/onboarding.ts/preferences.ts pour éviter un step
"Ambiguous" (chargé deux fois pour la feature qui les définissait déjà
elle-même).

Corrige aussi un second bug distinct révélé par la même CI :
"the ingredient/diet catalog is available" (recipe-form.feature)
contient un "/" non échappé — en syntaxe Cucumber Expression, "/" hors
d'un paramètre {..} signifie une alternative de texte ("ingredient" OU
"diet catalog is available"), jamais le caractère littéral. Le texte
du .feature ne pouvait donc jamais matcher. Renommé sans "/" :
"the ingredient and diet catalog is available".

Le script de vérification statique utilisé pour valider aaace15 avant
push donnait une fausse confiance : il regroupait tous les steps de
tous les fichiers comme disponibles globalement pour chaque feature,
sans respecter ce scoping réel. Réécrit pour ne charger, par feature,
que son fichier co-localisé + step_definitions/ — et pour détecter les
patterns contenant un "/" non échappé. Résultat : toujours 246 steps,
0 non résolu, 0 ambigu, 0 pattern à slash non échappé, cette fois avec
un modèle de résolution fidèle au comportement réel du préprocesseur.
2026-08-19 13:47:56 +02:00

69 lines
3.6 KiB
Gherkin

Feature: Recipe form — associating ingredients
As a signed-in user
I want to build a recipe by picking ingredients, quantities, and steps
So that I can save a complete recipe in one form
Background:
Given I am signed in as "Alice" "Martin"
And my household id is 1
And the ingredient and diet catalog is available
Scenario: Adds an ingredient from the picker, fills its quantity/unit, and creates the recipe
Given creating the recipe will succeed and return id 42
When I visit "/recettes/nouvelle"
And I fill in the "recipe-name" field with "Salade de tomates"
And I search the ingredient picker for "tomat"
And I select the ingredient "Tomate" from the picker
Then the ingredient "Tomate" should no longer be in the picker
And the recipe should include the ingredient "Tomate"
When I fill in the ingredient's quantity with "3" and unit "unité"
And I add a step
And I fill in the step description with "Couper les tomates."
Then the "Enregistrer" button should not be disabled
When I click the button "Enregistrer"
Then the recipe creation request should have included name "Salade de tomates" and ingredient 1 with quantity 3 and unit "unité"
And the URL should include "/recettes/42"
# Regression test for the exact bug reported: `crypto.randomUUID()` (used
# to mint each ingredient/step draft's client-only React key) throws
# outside a secure context — https, or literally the hostname `localhost`
# — so a LAN IP during on-device testing or a Capacitor WebView's
# `capacitor://` origin hit a black screen with "TypeError:
# crypto.randomUUID is not a function" the instant an ingredient was
# added. Cypress's own origin is secure, so this forces the same failure
# by deleting `crypto.randomUUID` before the app boots — see
# `apps/web/src/lib/client-key.ts`, which replaced it.
Scenario: Still works when crypto.randomUUID is unavailable (insecure-context regression)
When I visit the new recipe form without a secure random UUID
And I fill in the "recipe-name" field with "Recette hors contexte sécurisé"
And I select the ingredient "Tomate" from the picker
And I select the ingredient "Œuf" from the picker
Then there should be 2 ingredient rows
And the recipe should include the ingredient "Tomate"
And the recipe should include the ingredient "Œuf"
When I add a step
And I add a step
Then there should be 2 step editor items
Scenario: Excludes an already-selected ingredient from the picker, and removing it brings it back
When I visit "/recettes/nouvelle"
And I select the ingredient "Carotte" from the picker
Then the ingredient "Carotte" should no longer be in the picker
When I remove the ingredient "Carotte" from the recipe
Then the ingredient "Carotte" should be visible in the picker
And there should be 0 ingredient rows
Scenario: Preloads an existing recipe's ingredients when editing, and lets you add another
Given recipe 7 exists with an egg omelette
And updating recipe 7 will succeed
When I visit "/recettes/7/modifier"
Then the recipe should include the ingredient "Œuf"
And the ingredient's quantity should be "3"
When I select the ingredient "Tomate" from the picker
Then there should be 2 ingredient rows
When I fill in the last ingredient's quantity with "1" and unit "unité"
And I click the button "Enregistrer"
Then the recipe update request should have included these ingredients:
| ingredientId | quantity | unit |
| 2 | 3 | unité |
| 1 | 1 | unité |