fix(web): /playlists/{id} page uses $app/state, not legacy $app/stores

svelte-check failed with 8 type errors: $app/stores' page.params.id
is typed `string | undefined`, and the page passed `id` raw to
helpers that need `string`. Two changes:

- Switch to `$app/state` (the project canonical for new pages — see
  routes/albums/[id]/+page.svelte). page.params.id is a direct
  property read, not a store subscription. Fall back to "" so id is
  always a string; SvelteKit won't actually render the page without
  a populated id, but the type-checker doesn't know that.
- Drop the now-unused `writable` import in the test file and update
  the mock to expose the new state-shape (object with .params, not a
  writable store).

The remaining a11y warnings (tabindex on role=menu/dialog, click
handlers without keyboard events, draggable div without role,
autofocus) are svelte-check warnings — they don't block the build.
Some are pre-existing in FlagPopover; others are tech debt from
slice 1's drag-and-drop and modal patterns. Address as a follow-up
polish task.
This commit is contained in:
2026-05-03 11:58:10 -04:00
parent d32e1505c5
commit e0a4d13c45
2 changed files with 11 additions and 5 deletions
+6 -2
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { page } from '$app/stores';
import { page } from '$app/state';
import { goto } from '$app/navigation';
import { Pencil, Trash2 } from 'lucide-svelte';
import { useQueryClient } from '@tanstack/svelte-query';
@@ -18,7 +18,11 @@
import { playQueue } from '$lib/player/store.svelte';
import type { TrackRef } from '$lib/api/types';
const id = $derived($page.params.id);
// SvelteKit types page.params.id as string | undefined (the route
// could in principle render with the slot empty); empty-string fallback
// keeps every downstream call typed and falls back to a 404 if the
// operator ever lands here without a real id.
const id = $derived(page.params.id ?? '');
const queryClient = useQueryClient();
const playlistStore = $derived(createPlaylistQuery(id));
const playlistQuery = $derived($playlistStore);
@@ -1,11 +1,13 @@
import { describe, expect, test, vi } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte';
import { mockQuery } from '../../../test-utils/query';
import { writable } from 'svelte/store';
import type { PlaylistDetail } from '$lib/api/types';
vi.mock('$app/stores', () => ({
page: writable({ params: { id: 'p1' } })
// Project canonical: $app/state (rune-state), not $app/stores (legacy
// reactive store). The page module exports an object with a `params`
// getter rather than a Svelte store.
vi.mock('$app/state', () => ({
page: { params: { id: 'p1' } }
}));
vi.mock('$app/navigation', () => ({ goto: vi.fn() }));