Add tests for API endpoints, liked store, listen tracker and paged list

This commit is contained in:
2026-09-24 14:04:43 +02:00
parent b5c9658d65
commit e5ce63a192
6 changed files with 423 additions and 0 deletions
+80
View File
@@ -0,0 +1,80 @@
import { afterEach, describe, expect, it, vi } from 'vitest';
import type { LikedTrack, Track } from '$lib/types';
function track(id: string): Track {
return {
id,
title: id,
artist: 'Artist',
duration: 100,
explicit: false,
listensCount: 0
} as unknown as Track;
}
function likedTrack(id: string): LikedTrack {
return { ...track(id), likedAt: 1 } as LikedTrack;
}
async function freshStore() {
vi.resetModules();
return (await import('./liked.svelte')).liked;
}
afterEach(() => {
vi.unstubAllGlobals();
});
describe('liked store', () => {
it('hydrates only once', async () => {
const liked = await freshStore();
liked.hydrate([likedTrack('a')]);
liked.hydrate([likedTrack('b')]);
expect(liked.isLiked('a')).toBe(true);
expect(liked.isLiked('b')).toBe(false);
expect(liked.count).toBe(1);
});
it('likes and unlikes a track', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true }));
const liked = await freshStore();
await liked.toggle(track('a'));
expect(liked.isLiked('a')).toBe(true);
await liked.toggle(track('a'));
expect(liked.isLiked('a')).toBe(false);
expect(fetch).toHaveBeenCalledTimes(2);
});
it('reverts a failed like', async () => {
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: false }));
const liked = await freshStore();
await liked.toggle(track('a'));
expect(liked.isLiked('a')).toBe(false);
});
it('reverts a failed unlike', async () => {
const liked = await freshStore();
liked.hydrate([likedTrack('a')]);
vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new Error('offline')));
await liked.toggle(track('a'));
expect(liked.isLiked('a')).toBe(true);
});
it('keeps changes made to other tracks while a request fails', async () => {
const liked = await freshStore();
let rejectFirst: (reason: Error) => void = () => {};
const fetchMock = vi
.fn()
.mockImplementationOnce(() => new Promise((_, reject) => (rejectFirst = reject)))
.mockResolvedValueOnce({ ok: true });
vi.stubGlobal('fetch', fetchMock);
const first = liked.toggle(track('a'));
await liked.toggle(track('b'));
rejectFirst(new Error('offline'));
await first;
expect(liked.isLiked('a')).toBe(false);
expect(liked.isLiked('b')).toBe(true);
});
});