Skip to content
This repository was archived by the owner on Feb 28, 2026. It is now read-only.

Commit add45cb

Browse files
committed
Error tests for exports
1 parent 2f8fe8b commit add45cb

File tree

1 file changed

+69
-19
lines changed

1 file changed

+69
-19
lines changed

packages/player/src/views/PlaylistDetail/PlaylistDetail.test.tsx

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ vi.mock('@tauri-apps/plugin-fs', () => ({
2121
writeTextFile: vi.fn(),
2222
}));
2323

24+
const toastError = vi.fn();
25+
vi.mock('sonner', () => ({
26+
toast: { error: (...args: unknown[]) => toastError(...args) },
27+
}));
28+
2429
const defaultPlaylist = () =>
2530
new PlaylistBuilder()
2631
.withId('test-playlist')
@@ -34,6 +39,7 @@ describe('PlaylistDetail view', () => {
3439
useQueueStore.setState({ items: [], currentIndex: 0 });
3540
PlaylistDetailWrapper.seedPlaylist(defaultPlaylist());
3641
(dialog.save as Mock).mockResolvedValue(null);
42+
toastError.mockClear();
3743
});
3844

3945
it('(Snapshot) renders playlist detail with tracks', async () => {
@@ -182,28 +188,72 @@ describe('PlaylistDetail view', () => {
182188
expect(queueItems[2]?.title).toBe('So What');
183189
});
184190

185-
it('exports playlist as JSON file via save dialog', async () => {
186-
const expectedPath = '/downloads/Test Playlist.json';
187-
(dialog.save as Mock).mockResolvedValue(expectedPath);
191+
describe('JSON export', () => {
192+
it('exports playlist as JSON file via save dialog', async () => {
193+
const expectedPath = '/downloads/Test Playlist.json';
194+
(dialog.save as Mock).mockResolvedValue(expectedPath);
195+
196+
await PlaylistDetailWrapper.mount('test-playlist');
197+
await PlaylistDetailWrapper.exportJsonOption.click();
198+
199+
expect(dialog.save).toHaveBeenCalledWith(
200+
expect.objectContaining({
201+
defaultPath: 'Test Playlist.json',
202+
filters: [{ name: 'JSON Files', extensions: ['json'] }],
203+
}),
204+
);
205+
206+
expect(fs.writeTextFile).toHaveBeenCalledWith(
207+
expectedPath,
208+
expect.any(String),
209+
);
210+
211+
const writtenJson = (fs.writeTextFile as Mock).mock.calls[0][1];
212+
const parsed = JSON.parse(writtenJson);
213+
expect(parsed.name).toBe('Test Playlist');
214+
expect(parsed.tracks).toHaveLength(2);
215+
});
188216

189-
await PlaylistDetailWrapper.mount('test-playlist');
190-
await PlaylistDetailWrapper.exportJsonOption.click();
217+
it('does nothing when the user cancels the save dialog', async () => {
218+
(dialog.save as Mock).mockResolvedValueOnce(null);
191219

192-
expect(dialog.save).toHaveBeenCalledWith(
193-
expect.objectContaining({
194-
defaultPath: 'Test Playlist.json',
195-
filters: [{ name: 'JSON Files', extensions: ['json'] }],
196-
}),
197-
);
220+
await PlaylistDetailWrapper.mount('test-playlist');
221+
await PlaylistDetailWrapper.exportJsonOption.click();
198222

199-
expect(fs.writeTextFile).toHaveBeenCalledWith(
200-
expectedPath,
201-
expect.any(String),
202-
);
223+
expect(fs.writeTextFile).not.toHaveBeenCalled();
224+
});
225+
226+
it('shows an error toast when writing the file fails', async () => {
227+
(dialog.save as Mock).mockResolvedValueOnce(
228+
'/downloads/Test Playlist.json',
229+
);
230+
(fs.writeTextFile as Mock).mockRejectedValueOnce(
231+
new Error('Permission denied'),
232+
);
233+
234+
await PlaylistDetailWrapper.mount('test-playlist');
235+
await PlaylistDetailWrapper.exportJsonOption.click();
236+
237+
await vi.waitFor(() => {
238+
expect(toastError).toHaveBeenCalledWith('Failed to export playlist', {
239+
description: 'Permission denied',
240+
});
241+
});
242+
});
203243

204-
const writtenJson = (fs.writeTextFile as Mock).mock.calls[0][1];
205-
const parsed = JSON.parse(writtenJson);
206-
expect(parsed.name).toBe('Test Playlist');
207-
expect(parsed.tracks).toHaveLength(2);
244+
it('shows an error toast when the save dialog fails', async () => {
245+
(dialog.save as Mock).mockRejectedValueOnce(
246+
new Error('Dialog unavailable'),
247+
);
248+
249+
await PlaylistDetailWrapper.mount('test-playlist');
250+
await PlaylistDetailWrapper.exportJsonOption.click();
251+
252+
await vi.waitFor(() => {
253+
expect(toastError).toHaveBeenCalledWith('Failed to export playlist', {
254+
description: 'Dialog unavailable',
255+
});
256+
});
257+
});
208258
});
209259
});

0 commit comments

Comments
 (0)