feat(web): replace / placeholder with real artists list

Uses createArtistsQuery (infinite), URL-driven sort dropdown, Load
more pagination, delayed skeleton, and shared error banner. Also
introduces the test-utils/query.ts helpers for subsequent page tests.
This commit is contained in:
2026-04-23 19:43:37 -04:00
parent f94bf26f02
commit 5174b093b9
3 changed files with 253 additions and 2 deletions
+46
View File
@@ -0,0 +1,46 @@
import { readable } from 'svelte/store';
import type { Page } from '$lib/api/types';
// Synthetic infinite-query object shape matching what the SPA reads from
// @tanstack/svelte-query. Enough surface area for component tests;
// real behavior is covered by the TanStack library's own tests.
//
// Returns a Svelte readable store (matching CreateInfiniteQueryResult) so
// the component can subscribe with the $store rune.
export function mockInfiniteQuery<T>(opts: {
pages?: Page<T>[];
isPending?: boolean;
isError?: boolean;
error?: unknown;
hasNextPage?: boolean;
isFetchingNextPage?: boolean;
fetchNextPage?: () => void;
refetch?: () => void;
} = {}) {
return readable({
data: { pages: opts.pages ?? [] },
isPending: opts.isPending ?? false,
isError: opts.isError ?? false,
error: opts.error,
hasNextPage: opts.hasNextPage ?? false,
isFetchingNextPage: opts.isFetchingNextPage ?? false,
fetchNextPage: opts.fetchNextPage ?? (() => {}),
refetch: opts.refetch ?? (() => {})
});
}
export function mockQuery<T>(opts: {
data?: T;
isPending?: boolean;
isError?: boolean;
error?: unknown;
refetch?: () => void;
} = {}) {
return readable({
data: opts.data,
isPending: opts.isPending ?? false,
isError: opts.isError ?? false,
error: opts.error,
refetch: opts.refetch ?? (() => {})
});
}