import { afterEach, describe, expect, test, vi } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/svelte'; import DiscoverResultCard from './DiscoverResultCard.svelte'; afterEach(() => vi.clearAllMocks()); describe('DiscoverResultCard', () => { test('requestable state renders Request button and calls onRequest on click', async () => { const onRequest = vi.fn(); render(DiscoverResultCard, { props: { kind: 'artist', title: 'Boards of Canada', state: 'requestable', onRequest, }, }); // aria-label includes the title, so the accessible name is // "Request Boards of Canada". const btn = screen.getByRole('button', { name: /request boards of canada/i, }); expect(btn).not.toBeDisabled(); await fireEvent.click(btn); expect(onRequest).toHaveBeenCalledOnce(); }); test('kept state renders disabled "In library" button + Kept pill with role=status', () => { render(DiscoverResultCard, { props: { kind: 'album', title: 'Music Has The Right To Children', state: 'kept', }, }); expect(screen.getByRole('button', { name: /in library/i })).toBeDisabled(); // Kept pill is exposed as a status region so SR users hear it when it appears. const status = screen.getByRole('status'); expect(status).toBeInTheDocument(); expect(status.textContent).toMatch(/kept/i); }); test('requested state renders disabled "Requested" button', () => { render(DiscoverResultCard, { props: { kind: 'track', title: 'Roygbiv', state: 'requested', }, }); expect(screen.getByRole('button', { name: /requested/i })).toBeDisabled(); }); test('does not call onRequest when state is not requestable', async () => { const onRequest = vi.fn(); render(DiscoverResultCard, { props: { kind: 'album', title: 'Geogaddi', state: 'kept', onRequest, }, }); // Button is disabled — the test still verifies onRequest isn't called even // if a click slips through (jsdom does not enforce :disabled at fireEvent level). const btn = screen.getByRole('button'); await fireEvent.click(btn); expect(onRequest).not.toHaveBeenCalled(); }); // NOTE: previous versions of this file asserted .badge-row { min-height: 22px } // and .actions { margin-top: auto } via getComputedStyle, which only worked // because the component shipped inline style="" attributes — a layering // violation. Stylesheet introspection (document.styleSheets) was tried as a // replacement, but vitest's @testing-library/svelte renderer does not inject // the component's scoped