#401 introduced player.current?.id reads into TrackRow.svelte and
PlaylistTrackRow.svelte, breaking 26 test cases across 6 files whose
existing vi.mock('$lib/player/store.svelte', ...) blocks only stubbed
the functions used by the original components.
Added player: { current: undefined } to each affected mock — keeps
the existing function spies and lets the new isCurrent derivation
read a defined (false-y) player.current without blowing up.
Only updated the 6 files that failed; 16 other player-store mocks
exist across the suite but their tests don't render Track/Playlist
rows so the derivation never fires. Future tests that render those
rows will need the same stub (visible at the failure point with a
clear error message).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The DRY pass audit (#375) found two inline mock patterns repeated across the
vitest suite: a default empty-playlists mock for $lib/api/playlists (4 exact
copies in menu/card tests) and an api-client spy mock for $lib/api/client
(9 callers split between get-only and full-RESTy shapes — unified into one
helper that always returns all four verb spies).
Mirrors the existing test-utils/mocks/likes.ts and test-utils/mocks/quarantine.ts
convention. Tests with intentionally divergent shapes (AddToPlaylistMenu's
richer createPlaylist payload, PlaylistCard's getPlaylist, route-specific
mocks, events.svelte's specific resolved value) stay inline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces inline TrackRef literal redefinitions with calls to the
test-utils helper. Tests that asserted on default field values
(e.g. track titles, artist names rendered in the DOM) keep explicit
overrides; tests that only need a stub for shape now use makeTrack()
with no overrides.
PlaylistCard.test.ts, PlaylistTrackRow.test.ts, and playlist.test.ts
SKIPPED — they use PlaylistTrack (with track_id/added_at), not TrackRef.
ArtistCard.svelte and +page.svelte route files (matched by initial grep)
SKIPPED — live code, not test files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Centralizes the inline { page: { get url() { return state.pageUrl } } }
mock shape via test-utils/mocks/appState.ts. The vi.hoisted state
declaration remains per-file (vitest mock-hoisting requires module-
level declaration). Adds a $test-utils alias to svelte.config.js so
the helper can be imported without ../../../ chains.
SKIPPED (mock exposes more than url):
- Shell.test.ts, MobileNavDrawer.test.ts, admin.test.ts: static
page: { url: ... } shape, no hoisted state to centralize.
- album.test.ts, artist.test.ts: page exposes both params and url.
- playlist.test.ts, reset-password.test.ts: page exposes params only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add browser tab titles to all 18 static page routes using the pageTitle()
helper from $lib/branding. Titles follow the Minstrel · Section format.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add Artists and Albums nav entries, rename root label from Library to
Home. Migrate all three ArtistRow call sites (search, search/artists,
library/liked) to ArtistCard with grid wrapper; delete ArtistRow
component and its test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds sort_name/cover_url to ArtistRef, sort_title to AlbumRef (matching
backend Task 5 wire shape), HomePayload type, and qk.home/albumsAlpha/
artistTracks query keys. Updates existing test fixtures to satisfy the
new required fields.
Verified clean via 'npm run check' (0 errors, only pre-existing warnings).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pages that render TrackRow/AlbumCard/ArtistRow/PlayerBar now indirectly
mount LikeButton, which calls useQueryClient(). Route tests need the
same mocks the component-level tests have.
- Added createLikedIdsQuery mock to 7 route test files
- Added useQueryClient mock to all affected route tests
- Added readable store import where needed
/search/artists, /search/albums, /search/tracks each read ?q= and run
their own createSearchInfiniteQuery (limit=50). Load more pulls the
next offset; back link returns to /search?q=. Empty q shows a 'no
query' prompt and fires no request. Tracks overflow uses the onPlay
prop on TrackRow to call playRadio(track.id).
Reads ?q= reactively; runs createSearchQuery (limit=10) when q is
non-empty. Renders Artists/Albums/Tracks sections reusing ArtistRow,
AlbumCard, TrackRow. Track click uses onPlay prop to call
playRadio(track.id) instead of the default playQueue. Empty facets
hide; 'See all N →' link points to overflow pages when total > items.
Empty q shows 'Start typing'; error → ApiErrorBanner; loading →
SearchSkeleton via useDelayed.