356f8f5d6c
5-slot system row (For-You, Discover, 3× Songs-like) means: - empty state: 5 placeholders (was 4) - For-You only: 4 placeholders (was 3) — Discover + 3 songs-like
112 lines
3.6 KiB
TypeScript
112 lines
3.6 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
||
import { render, screen } from '@testing-library/svelte';
|
||
import { readable } from 'svelte/store';
|
||
import { emptyLikesMock } from '../test-utils/mocks/likes';
|
||
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', () => emptyLikesMock());
|
||
|
||
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 5 placeholder cards when no playlists exist', () => {
|
||
// Slot layout: For-You, Discover, 3× Songs-like.
|
||
render(Page);
|
||
const placeholders = screen.queryAllByTestId('playlist-placeholder-card');
|
||
expect(placeholders).toHaveLength(5);
|
||
});
|
||
|
||
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');
|
||
// 1 Discover + 3 Songs-like slots = 4 placeholders alongside the
|
||
// real For-You tile.
|
||
expect(placeholders).toHaveLength(4);
|
||
});
|
||
});
|