import { describe, expect, test, vi } from 'vitest'; import { render, screen, fireEvent, waitFor } from '@testing-library/svelte'; import { mockQuery } from '../../test-utils/query'; import type { Playlist } from '$lib/api/types'; vi.mock('$lib/api/playlists', () => ({ createPlaylistsQuery: vi.fn(), createPlaylist: vi.fn().mockResolvedValue({ id: 'p-new', name: 'X' }) })); vi.mock('$app/navigation', () => ({ goto: vi.fn() })); import PlaylistsPage from './+page.svelte'; import { createPlaylistsQuery, createPlaylist } from '$lib/api/playlists'; const mockedCreatePlaylistsQuery = createPlaylistsQuery as ReturnType; const mockedCreatePlaylist = createPlaylist as ReturnType; function p(over: Partial): Playlist { return { id: 'p1', user_id: 'u-self', owner_username: 'me', name: 'A', description: '', is_public: false, kind: 'user', system_variant: null, refreshable: false, seed_artist_id: null, cover_url: '', track_count: 0, duration_sec: 0, created_at: '', updated_at: '', ...over }; } describe('Playlists index page', () => { test('renders own + public sections', () => { mockedCreatePlaylistsQuery.mockReturnValue(mockQuery({ data: { owned: [p({ id: 'p1', name: 'Mine' })], public: [p({ id: 'p2', name: 'Theirs', user_id: 'u-other', owner_username: 'bob' })] } })); render(PlaylistsPage); expect(screen.getByText('Mine')).toBeInTheDocument(); expect(screen.getByText('Theirs')).toBeInTheDocument(); expect(screen.getByText(/your playlists/i)).toBeInTheDocument(); expect(screen.getByText(/from other users/i)).toBeInTheDocument(); }); test('empty-state copy when operator has no playlists', () => { mockedCreatePlaylistsQuery.mockReturnValue(mockQuery({ data: { owned: [], public: [] } })); render(PlaylistsPage); expect(screen.getByText(/no playlists yet/i)).toBeInTheDocument(); }); test('hides "From other users" section when empty', () => { mockedCreatePlaylistsQuery.mockReturnValue(mockQuery({ data: { owned: [p({ id: 'p1', name: 'Mine' })], public: [] } })); render(PlaylistsPage); expect(screen.queryByText(/from other users/i)).not.toBeInTheDocument(); }); test('Create button reveals inline form; submit creates and navigates', async () => { mockedCreatePlaylistsQuery.mockReturnValue(mockQuery({ data: { owned: [], public: [] } })); render(PlaylistsPage); await fireEvent.click(screen.getByRole('button', { name: /new playlist/i })); const input = screen.getByPlaceholderText(/saturday morning/i); await fireEvent.input(input, { target: { value: 'Test' } }); await fireEvent.click(screen.getByRole('button', { name: /^create$/i })); await waitFor(() => expect(mockedCreatePlaylist).toHaveBeenCalledWith({ name: 'Test' })); }); });