import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/svelte'; import QueueDrawer from './QueueDrawer.svelte'; import type { TrackRef } from '$lib/api/types'; const closeQueueDrawer = vi.fn(); let queueValue: TrackRef[] = []; let indexValue = 0; let openValue = true; vi.mock('$lib/player/store.svelte', () => ({ closeQueueDrawer: (...args: unknown[]) => closeQueueDrawer(...args), player: { get queue() { return queueValue; }, get index() { return indexValue; }, get queueDrawerOpen() { return openValue; } }, // QueueTrackRow imports these from the store; provide stubs so its // module-load doesn't break when QueueDrawer renders rows. playFromQueueIndex: vi.fn(), removeFromQueue: vi.fn(), moveQueueItem: vi.fn() })); const t = (id: string): TrackRef => ({ id, title: `Song ${id}`, album_id: `al-${id}`, album_title: 'A', artist_id: `ar-${id}`, artist_name: `Artist ${id}`, duration_sec: 200, stream_url: `/stream/${id}` }); describe('QueueDrawer', () => { beforeEach(() => { closeQueueDrawer.mockClear(); queueValue = []; indexValue = 0; openValue = true; }); it('renders Queue title and track-count summary', () => { queueValue = [t('a'), t('b'), t('c')]; render(QueueDrawer); expect(screen.getByText(/^Queue$/i)).toBeInTheDocument(); expect(screen.getByText(/3 tracks/i)).toBeInTheDocument(); }); it('renders one row per queue entry', () => { queueValue = [t('a'), t('b')]; render(QueueDrawer); expect(screen.getByText('Song a')).toBeInTheDocument(); expect(screen.getByText('Song b')).toBeInTheDocument(); }); it('shows empty-state copy when queue is empty', () => { queueValue = []; render(QueueDrawer); expect(screen.getByText(/no tracks queued/i)).toBeInTheDocument(); }); it('clicking the close button calls closeQueueDrawer', async () => { render(QueueDrawer); const close = screen.getByLabelText(/close queue/i); await fireEvent.click(close); expect(closeQueueDrawer).toHaveBeenCalled(); }); it('clicking the backdrop calls closeQueueDrawer', async () => { render(QueueDrawer); const backdrop = screen.getByLabelText(/close queue backdrop/i); await fireEvent.click(backdrop); expect(closeQueueDrawer).toHaveBeenCalled(); }); it('drawer is hidden (aria-hidden=true) when queueDrawerOpen is false', () => { openValue = false; queueValue = [t('a')]; render(QueueDrawer); const aside = screen.getByLabelText(/playback queue/i, { hidden: true }); expect(aside).toHaveAttribute('aria-hidden', 'true'); }); it('drawer has inert attribute when closed', () => { openValue = false; queueValue = [t('a')]; render(QueueDrawer); const aside = document.querySelector('aside[aria-label="Playback queue"]'); expect(aside).not.toBeNull(); expect(aside!.hasAttribute('inert')).toBe(true); }); });