diff --git a/web/src/hooks/queries/catalog.test.tsx b/web/src/hooks/queries/catalog.test.tsx index 0dccdcb4..ebdf5e78 100644 --- a/web/src/hooks/queries/catalog.test.tsx +++ b/web/src/hooks/queries/catalog.test.tsx @@ -132,6 +132,43 @@ describe("useCatalogWindow", () => { expect(markup).toContain('data-total="360"'); }); + it("does not count empty buffered pages as loaded items when total is omitted", () => { + const state = createCatalogSearchState("query", { library_id: 7 }); + const limit = 60; + + function Harness() { + const result = useCatalogWindow(state, { limit, includeTotal: false }); + return
; + } + + mocks.useQuery.mockReturnValue({ + data: { + ...makePage(0, 3), + total: 0, + total_exact: false, + has_more: false, + snapshot: "2026-01-01T00:00:00Z", + }, + isLoading: false, + }); + mocks.useQueries.mockReturnValue([ + { + data: { + ...makePage(60, 0), + total: 0, + total_exact: false, + has_more: false, + items: [], + }, + isLoading: false, + }, + ]); + + const markup = renderToStaticMarkup(); + + expect(markup).toContain('data-total="3"'); + }); + it("requests follow-on pages for non-snapshot sources after page 0 loads", () => { const state = createCatalogSearchState("history"); const limit = 60; diff --git a/web/src/hooks/queries/catalog.ts b/web/src/hooks/queries/catalog.ts index bca6ef31..d94571bd 100644 --- a/web/src/hooks/queries/catalog.ts +++ b/web/src/hooks/queries/catalog.ts @@ -197,7 +197,9 @@ export function useCatalogWindow( let highestPageIndex = -1; let highestPageHasMore = false; pageResults.forEach((page, pageIndex) => { - maxLoadedEnd = Math.max(maxLoadedEnd, pageIndex * limit + page.items.length); + if (page.items.length > 0) { + maxLoadedEnd = Math.max(maxLoadedEnd, pageIndex * limit + page.items.length); + } if (pageIndex >= highestPageIndex) { highestPageIndex = pageIndex; highestPageHasMore = page.has_more;