Deux volets de l'issue #38. **Bug de bouclage** — l'`IntersectionObserver` de `SourceItemTable` n'a que `[hasMore]` comme dépendance et ne se réabonne donc jamais pendant un scroll normal (`hasMore` reste `true`). Il figeait la toute première closure `onLoadMore`, laquelle rappelait indéfiniment le même curseur périmé — la liste s'allongeait en boucle avec les mêmes éléments et `nextCursor` n'atteignait jamais son vrai `null`. - `SourceItemTable` lit maintenant `onLoadMore` via une ref réassignée à chaque rendu : l'observer appelle toujours la closure fraîche, sans réabonnement inutile (intention d'origine du `biome-ignore` conservée, le commentaire n'étant plus nécessaire). - `RecipeSourcesPanel` dédoublonne le merge par `externalId` et traite « cette page n'a rien apporté de nouveau » comme une fin de liste même si la source renvoie encore un `nextCursor` — garde-fou contre une éventuelle heuristique de fin imparfaite côté adaptateur. **Couverture recherche vide** — `theMealDbAdapter.list()` tapait `/search.php?s=` même sans requête, ce que TheMealDB borne à ~25 recettes (`nextCursor` toujours `null`). Une requête vide déroule désormais la liste des catégories (`/list.php?c=list` puis `/filter.php?c=…`), une catégorie par pas de curseur, pour un vrai « tout parcourir ». Tests : nouveau scénario Cypress à 3 pages avec curseurs distincts réellement vérifiés (aucun curseur redemandé) ; nouveaux cas Mocha pour la marche par catégories (première page + curseur, suivi du curseur, arrêt sur la dernière catégorie, page vide au-delà, requête blanche = requête vide). Closes #38 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
92 lines
4.1 KiB
Gherkin
92 lines
4.1 KiB
Gherkin
Feature: Browsing external recipe sources
|
|
As a signed-in user
|
|
I want to browse the recipes available from my household's enabled sources
|
|
So that I can find new recipes to import, or jump straight to ones I already have
|
|
|
|
Background:
|
|
Given I am signed in as "Alice" "Martin"
|
|
And my household id is 1
|
|
And the disliked ingredients list is empty
|
|
And the planning request returns nothing
|
|
|
|
Scenario: Shows no source tab when the household hasn't enabled any
|
|
Given the recipe catalog contains nothing
|
|
And the sources reference list has options
|
|
And the household's enabled sources are empty
|
|
When I visit "/recettes"
|
|
Then I should not see "TheMealDB"
|
|
|
|
Scenario: Browses an enabled source, distinguishing already-imported items from new ones
|
|
Given the recipe catalog contains nothing
|
|
And the sources reference list has options
|
|
And the household has enabled TheMealDB
|
|
And browsing TheMealDB returns some items
|
|
And recipe 2's detail is available
|
|
When I visit "/recettes"
|
|
And I click the button "TheMealDB"
|
|
Then I should see the source item "Chicken Handi"
|
|
And I should see the source item "Fish Pie"
|
|
And the source item "Chicken Handi" should be marked as already imported
|
|
|
|
When I click the source item "Chicken Handi"
|
|
Then the URL should include "/recettes/2"
|
|
And the recipe detail panel heading should be "Omelette"
|
|
|
|
Scenario: Previews a not-yet-imported item, highlighting its detected techniques
|
|
Given the recipe catalog contains nothing
|
|
And the sources reference list has options
|
|
And the household has enabled TheMealDB
|
|
And browsing TheMealDB returns some items
|
|
And previewing TheMealDB item "9999" is available
|
|
When I visit "/recettes"
|
|
And I click the button "TheMealDB"
|
|
And I click the source item "Fish Pie"
|
|
Then the URL should include "/recettes/sources/theMealDb/9999"
|
|
And the recipe detail panel heading should be "Fish Pie"
|
|
And I should see the highlighted technique "Cuire"
|
|
|
|
Scenario: Loads further pages automatically, with no "load more" button
|
|
Given the recipe catalog contains nothing
|
|
And the sources reference list has options
|
|
And the household has enabled TheMealDB
|
|
And browsing TheMealDB returns two pages of items
|
|
When I visit "/recettes"
|
|
And I click the button "TheMealDB"
|
|
Then I should see the source item "Chicken Handi"
|
|
And I should see the source item "Beef Wellington"
|
|
And I should not see "Voir plus"
|
|
|
|
Scenario: Walks several pages with distinct cursors, then stops, without re-requesting a page
|
|
Given the recipe catalog contains nothing
|
|
And the sources reference list has options
|
|
And the household has enabled TheMealDB
|
|
And browsing TheMealDB returns three pages, each addressed by its own cursor
|
|
When I visit "/recettes"
|
|
And I click the button "TheMealDB"
|
|
Then I should see the source item "Page One Dish"
|
|
And I should see the source item "Page Two Dish"
|
|
And I should see the source item "Page Three Dish"
|
|
And no browse cursor should have been requested more than once
|
|
|
|
Scenario: Offers a retry when loading the next page fails
|
|
Given the recipe catalog contains nothing
|
|
And the sources reference list has options
|
|
And the household has enabled TheMealDB
|
|
And browsing TheMealDB's next page fails once, then succeeds
|
|
When I visit "/recettes"
|
|
And I click the button "TheMealDB"
|
|
Then I should see the source item "Chicken Handi"
|
|
And I should see a message to retry loading more
|
|
When I click the button "Réessayer"
|
|
Then I should see the source item "Beef Wellington"
|
|
|
|
Scenario: Deep-links straight to a not-yet-imported item's own page, with no import affordance at all
|
|
Given the recipe catalog contains nothing
|
|
And the sources reference list has options
|
|
And the household has enabled TheMealDB
|
|
And browsing TheMealDB returns some items
|
|
And previewing TheMealDB item "9999" is available
|
|
When I visit "/recettes/sources/theMealDb/9999"
|
|
Then the recipe detail panel heading should be "Fish Pie"
|
|
And I should not see "Importer cette recette"
|
|
And I should see a discreet link to the item's original page
|