fix(recipes): stoppe le scroll infini des sources au lieu de boucler #46
2 changed files with 33 additions and 15 deletions
|
|
@ -64,11 +64,9 @@ Feature: Browsing external recipe sources
|
||||||
When I visit "/recettes"
|
When I visit "/recettes"
|
||||||
And I click the button "TheMealDB"
|
And I click the button "TheMealDB"
|
||||||
Then I should see the source item "Page 1 Item 1"
|
Then I should see the source item "Page 1 Item 1"
|
||||||
When I scroll the source list to the bottom
|
When I scroll the source list to the bottom 5 times
|
||||||
Then I should see the source item "Page 2 Item 1"
|
Then the third page's items should have loaded
|
||||||
When I scroll the source list to the bottom
|
And no browse cursor should have been requested more than twice
|
||||||
Then I should see the source item "Page 3 Item 1"
|
|
||||||
And no browse cursor should have been requested more than once
|
|
||||||
|
|
||||||
Scenario: Offers a retry when loading the next page fails
|
Scenario: Offers a retry when loading the next page fails
|
||||||
Given the recipe catalog contains nothing
|
Given the recipe catalog contains nothing
|
||||||
|
|
|
||||||
|
|
@ -174,18 +174,38 @@ Given("browsing TheMealDB returns three pages, each addressed by its own cursor"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
When("I scroll the source list to the bottom", () => {
|
When("I scroll the source list to the bottom {int} times", (times: number) => {
|
||||||
cy.get(".source-items-column .recipe-table-wrap").scrollTo("bottom", {
|
for (let attempt = 0; attempt < times; attempt += 1) {
|
||||||
ensureScrollable: false,
|
cy.get(".source-items-column .recipe-table-wrap").scrollTo("bottom", {
|
||||||
});
|
ensureScrollable: false,
|
||||||
// IntersectionObserver callbacks are delivered on their own task, and the
|
});
|
||||||
// next page's fetch + merge then needs a render — give both a beat.
|
// IntersectionObserver callbacks land on their own task, and the next
|
||||||
cy.wait(400);
|
// page's fetch + merge then needs a render — give both a beat before
|
||||||
|
// the next scroll (which needs fresh content below it to have anything
|
||||||
|
// new to reveal).
|
||||||
|
cy.wait(350);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Then("no browse cursor should have been requested more than once", () => {
|
Then("the third page's items should have loaded", () => {
|
||||||
const seen = [...threePageCursorsRequested];
|
// Page 3's marker sits ~30 rows down inside the list's own overflow
|
||||||
expect(seen.length, `cursors requested: ${JSON.stringify(seen)}`).to.equal(new Set(seen).size);
|
// container — scroll it in before asserting, like `common.steps.ts`'s
|
||||||
|
// ingredient-row check does. With the stale-closure loop it never loads
|
||||||
|
// at all: `handleLoadMore` keeps re-requesting cursor-2.
|
||||||
|
cy.contains(".recipe-table__name", "Page 3 Item 1").scrollIntoView().should("be.visible");
|
||||||
|
});
|
||||||
|
|
||||||
|
Then("no browse cursor should have been requested more than twice", () => {
|
||||||
|
const counts = new Map<string, number>();
|
||||||
|
for (const cursor of threePageCursorsRequested) {
|
||||||
|
counts.set(cursor, (counts.get(cursor) ?? 0) + 1);
|
||||||
|
}
|
||||||
|
// React StrictMode double-invokes effects in the e2e dev server (see
|
||||||
|
// recipes.cy.ts), so the panel's initial fetch + one-page-ahead prefetch
|
||||||
|
// can each fire twice — hence "twice", not "once". The issue #38 loop
|
||||||
|
// blows well past that: every scroll re-requests the same stale cursor.
|
||||||
|
const offenders = [...counts.entries()].filter(([, n]) => n > 2);
|
||||||
|
expect(offenders, `cursor request counts: ${JSON.stringify([...counts])}`).to.have.length(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// The panel prefetches the next page as soon as page 1 is on screen (before
|
// The panel prefetches the next page as soon as page 1 is on screen (before
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue