+
{group.label}
@@ -40,8 +40,16 @@
{/each}
- {#if $query.hasNextPage && !$query.isFetchingNextPage}
-
$query.fetchNextPage()} />
+ {#if query.hasNextPage}
+ query.fetchNextPage()}
+ />
+ {#if query.isFetchingNextPage}
+ Loading more…
+ {/if}
+ {:else if flatEvents.length > 0}
+ End of history
{/if}
{/if}
diff --git a/web/src/routes/library/history/page.test.ts b/web/src/routes/library/history/page.test.ts
index 94090c94..5210ea6a 100644
--- a/web/src/routes/library/history/page.test.ts
+++ b/web/src/routes/library/history/page.test.ts
@@ -108,10 +108,18 @@ describe('library/history page', () => {
mockData = { pages: [{ events: [mkEvent('a', new Date())], has_more: false }] };
mockHasNextPage = false;
const { container } = render(HistoryPage);
- // Sentinel renders an empty — assert by absence of the call.
- // (We can't easily query for the sentinel itself in the DOM since it has
- // no aria role; instead, verify the page renders the song without error.)
+ // InfiniteScrollSentinel renders
.
+ // When hasNextPage is false, no such div should be in the DOM.
+ expect(container.querySelector('div[aria-hidden="true"].h-px')).toBeNull();
+ // Confirm the page rendered the row so we know we hit the success branch.
expect(screen.getByText('Song a')).toBeInTheDocument();
- expect(container).toBeTruthy();
+ });
+
+ it('renders the InfiniteScrollSentinel when hasNextPage is true', () => {
+ mockData = { pages: [{ events: [mkEvent('a', new Date())], has_more: true }] };
+ mockHasNextPage = true;
+ mockIsFetchingNextPage = false;
+ const { container } = render(HistoryPage);
+ expect(container.querySelector('div[aria-hidden="true"].h-px')).not.toBeNull();
});
});