feat(web/m7-352): home Playlists row — For-You + Songs-like + user playlists
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
import { render, screen } from '@testing-library/svelte';
|
||||
import { readable } from 'svelte/store';
|
||||
import type { Playlist } from '$lib/api/types';
|
||||
|
||||
// Mock all the queries the home page constructs.
|
||||
vi.mock('$lib/api/home', () => ({
|
||||
createHomeQuery: () =>
|
||||
readable({
|
||||
data: {
|
||||
recently_added_albums: [],
|
||||
most_played_tracks: [],
|
||||
rediscover_albums: [],
|
||||
rediscover_artists: [],
|
||||
last_played_artists: []
|
||||
},
|
||||
isPending: false,
|
||||
isError: false,
|
||||
refetch: vi.fn()
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('$lib/api/playlists', () => ({
|
||||
createPlaylistsQuery: vi.fn()
|
||||
}));
|
||||
|
||||
vi.mock('$lib/api/me', () => ({
|
||||
createSystemPlaylistsStatusQuery: vi.fn()
|
||||
}));
|
||||
|
||||
// LikeButton imports — needed because the home renders cards that may use it.
|
||||
vi.mock('$lib/api/likes', () => ({
|
||||
createLikedIdsQuery: () =>
|
||||
readable({ data: { track_ids: [], album_ids: [], artist_ids: [] }, isPending: false, isError: false }),
|
||||
likeEntity: vi.fn().mockResolvedValue(undefined),
|
||||
unlikeEntity: vi.fn().mockResolvedValue(undefined)
|
||||
}));
|
||||
|
||||
vi.mock('@tanstack/svelte-query', async (orig) => {
|
||||
const actual = (await orig()) as Record<string, unknown>;
|
||||
return { ...actual, useQueryClient: () => ({ invalidateQueries: vi.fn() }) };
|
||||
});
|
||||
|
||||
import Page from './+page.svelte';
|
||||
import { createPlaylistsQuery } from '$lib/api/playlists';
|
||||
import { createSystemPlaylistsStatusQuery } from '$lib/api/me';
|
||||
|
||||
const emptyPlaylistsResponse = { owned: [], public: [] };
|
||||
|
||||
beforeEach(() => {
|
||||
(createPlaylistsQuery as unknown as ReturnType<typeof vi.fn>).mockImplementation(() =>
|
||||
readable({ data: emptyPlaylistsResponse, isPending: false, isError: false })
|
||||
);
|
||||
(createSystemPlaylistsStatusQuery as unknown as ReturnType<typeof vi.fn>).mockReturnValue(
|
||||
readable({
|
||||
data: { in_flight: false, last_run_at: null, last_error: null },
|
||||
isPending: false,
|
||||
isError: false
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => vi.clearAllMocks());
|
||||
|
||||
describe('home Playlists section', () => {
|
||||
test('renders 4 placeholder cards when no playlists exist', () => {
|
||||
render(Page);
|
||||
const placeholders = screen.queryAllByTestId('playlist-placeholder-card');
|
||||
expect(placeholders).toHaveLength(4);
|
||||
});
|
||||
|
||||
test('building status sets variant=building on placeholders', () => {
|
||||
(createSystemPlaylistsStatusQuery as unknown as ReturnType<typeof vi.fn>).mockReturnValue(
|
||||
readable({
|
||||
data: { in_flight: true, last_run_at: null, last_error: null },
|
||||
isPending: false,
|
||||
isError: false
|
||||
})
|
||||
);
|
||||
const { container } = render(Page);
|
||||
const buildingPlaceholders = container.querySelectorAll('[data-variant="building"]');
|
||||
expect(buildingPlaceholders.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('renders For-You playlist + 3 placeholders when only for_you exists', () => {
|
||||
const forYou: Playlist = {
|
||||
id: 'fy',
|
||||
user_id: 'u1',
|
||||
owner_username: 'u1',
|
||||
name: 'For You',
|
||||
description: '',
|
||||
is_public: false,
|
||||
kind: 'system',
|
||||
system_variant: 'for_you',
|
||||
seed_artist_id: null,
|
||||
cover_url: '',
|
||||
track_count: 25,
|
||||
duration_sec: 1500,
|
||||
created_at: '2026-05-04T00:00:00Z',
|
||||
updated_at: '2026-05-04T00:00:00Z'
|
||||
};
|
||||
(createPlaylistsQuery as unknown as ReturnType<typeof vi.fn>).mockImplementation(
|
||||
(kind?: string) =>
|
||||
kind === 'system'
|
||||
? readable({
|
||||
data: { owned: [forYou], public: [] },
|
||||
isPending: false,
|
||||
isError: false
|
||||
})
|
||||
: readable({ data: emptyPlaylistsResponse, isPending: false, isError: false })
|
||||
);
|
||||
render(Page);
|
||||
expect(screen.getByText('For You')).toBeInTheDocument();
|
||||
const placeholders = screen.queryAllByTestId('playlist-placeholder-card');
|
||||
expect(placeholders).toHaveLength(3); // 3 songs-like slots
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user