Files
minstrel/web/src/lib/components/AddToPlaylistMenu.test.ts
T
bvandeusenandClaude Opus 5.5 ca9917d8cd
release / govulncheck (push) Successful in 23s
release / web (push) Successful in 1m22s
release / go (push) Successful in 1m41s
release / integration (push) Successful in 4m49s
release / android (push) Successful in 5m32s
release / Build signed APK (releases and dev) (push) Successful in 5m39s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 28s
release / Verify release artifacts (tag releases only) (push) Skipped
chore(web): clear kit 3's alias and Vite's config-loader deprecations (#5021)
CI run 8789 warned on both:

- kit 3 deprecates `config.alias`. The $test-utils alias becomes a
  `#test-utils/*` subpath import, matching #lib, and its 43 import sites
  move with it.
- Vite's coming native config loader needs the extension on
  vitest.config.ts's import of vite.config.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 11:03:38 -04:00

103 lines
3.1 KiB
TypeScript

import { describe, expect, test, vi } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte';
import { readable } from 'svelte/store';
import { makeTrack } from '#test-utils/fixtures/track.js';
const playlistsData = vi.hoisted(() => ({
owned: [
{
id: 'p1',
user_id: 'u-self',
owner_username: 'me',
name: 'B-list',
description: '',
is_public: false,
kind: 'user',
system_variant: null,
refreshable: false,
seed_artist_id: null,
cover_url: '',
track_count: 3,
duration_sec: 0,
created_at: '',
updated_at: ''
},
{
id: 'p2',
user_id: 'u-self',
owner_username: 'me',
name: 'A-list',
description: '',
is_public: false,
kind: 'user',
system_variant: null,
refreshable: false,
seed_artist_id: null,
cover_url: '',
track_count: 5,
duration_sec: 0,
created_at: '',
updated_at: ''
}
],
public: [] as unknown[]
}));
vi.mock('#lib/auth/store.svelte.js', () => ({
user: { value: { id: 'u-self', username: 'me', is_admin: false } }
}));
vi.mock('#lib/api/playlists.js', () => ({
createPlaylistsQuery: () =>
readable({ data: playlistsData, isPending: false, isError: false }),
appendTracks: vi.fn().mockResolvedValue({ id: 'p1', tracks: [] }),
createPlaylist: vi.fn().mockResolvedValue({
id: 'p3',
user_id: 'u-self',
owner_username: 'me',
name: 'New',
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: ''
})
}));
import AddToPlaylistMenu from './AddToPlaylistMenu.svelte';
const track = makeTrack();
describe('AddToPlaylistMenu', () => {
test('lists own playlists alphabetically followed by "New playlist…"', () => {
render(AddToPlaylistMenu, { props: { tracks: [track], onClose: vi.fn() } });
const items = screen.getAllByRole('menuitem');
// First two should be the playlists in alpha order, then "New playlist…".
expect(items[0].textContent).toContain('A-list');
expect(items[1].textContent).toContain('B-list');
expect(items[2].textContent).toContain('New playlist');
});
test('clicking a playlist appends and closes', async () => {
const onClose = vi.fn();
const { appendTracks } = await import('#lib/api/playlists.js');
render(AddToPlaylistMenu, { props: { tracks: [track], onClose } });
await fireEvent.click(screen.getByRole('menuitem', { name: /A-list/ }));
await waitFor(() => expect(onClose).toHaveBeenCalled());
expect(appendTracks).toHaveBeenCalledWith('p2', ['t1']);
});
test('"New playlist…" toggles inline create form', async () => {
render(AddToPlaylistMenu, { props: { tracks: [track], onClose: vi.fn() } });
await fireEvent.click(screen.getByRole('menuitem', { name: /New playlist/ }));
expect(screen.getByPlaceholderText(/playlist name/i)).toBeInTheDocument();
expect(screen.getByText(/Create & add/i)).toBeInTheDocument();
});
});