refactor(web): extract emptyPlaylistsMock + apiClientMock test helpers

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>
This commit is contained in:
2026-05-12 12:45:15 -04:00
parent 1f0f7eee1a
commit 9acad5461e
16 changed files with 73 additions and 56 deletions
+22
View File
@@ -0,0 +1,22 @@
// Default api-client mock for $lib/api/client. Provides spies for
// every HTTP verb so tests don't need to anticipate which methods
// the code under test might reach for.
//
// Usage:
// vi.mock('$lib/api/client', () => apiClientMock());
//
// Tests that need a specific resolved value (e.g. events tests that
// assert on the play_event_id round trip) keep custom mocks inline.
import { vi } from 'vitest';
export function apiClientMock() {
return {
api: {
get: vi.fn(),
post: vi.fn(),
put: vi.fn(),
del: vi.fn()
}
};
}
+23
View File
@@ -0,0 +1,23 @@
// Default empty-playlists mock for $lib/api/playlists. The
// dominant shape across the menu / card tests: no playlists for
// the user, append/create as resolved spies.
//
// Usage:
// vi.mock('$lib/api/playlists', () => emptyPlaylistsMock());
//
// Tests that exercise richer return payloads (AddToPlaylistMenu's
// full PlaylistDetail return, PlaylistCard's getPlaylist, route
// tests that need owned playlists pre-populated) keep custom
// mocks inline.
import { readable } from 'svelte/store';
import { vi } from 'vitest';
export function emptyPlaylistsMock() {
return {
createPlaylistsQuery: () =>
readable({ data: { owned: [], public: [] }, isPending: false, isError: false }),
appendTracks: vi.fn().mockResolvedValue({ id: 'p1', tracks: [] }),
createPlaylist: vi.fn().mockResolvedValue({ id: 'p1', name: 'New' })
};
}