Files
Musify/web-player/src/lib/state/liked.test.ts
T

81 lines
2.2 KiB
TypeScript

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);
});
});