refactor(web/api): errCode + errMessage helpers; 41 sites migrated (W1)
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { errCode, errMessage } from './errors';
|
||||
import { ERROR_COPY } from './error-copy';
|
||||
|
||||
describe('errCode', () => {
|
||||
test('returns code from object', () => {
|
||||
expect(errCode({ code: 'foo' })).toBe('foo');
|
||||
});
|
||||
|
||||
test("returns 'unknown' for null", () => {
|
||||
expect(errCode(null)).toBe('unknown');
|
||||
});
|
||||
|
||||
test("returns 'unknown' for undefined", () => {
|
||||
expect(errCode(undefined)).toBe('unknown');
|
||||
});
|
||||
|
||||
test("returns 'unknown' for non-object values", () => {
|
||||
expect(errCode('boom')).toBe('unknown');
|
||||
expect(errCode(42)).toBe('unknown');
|
||||
expect(errCode(true)).toBe('unknown');
|
||||
});
|
||||
|
||||
test('handles missing code field', () => {
|
||||
expect(errCode({})).toBe('unknown');
|
||||
expect(errCode({ message: 'hi' })).toBe('unknown');
|
||||
});
|
||||
});
|
||||
|
||||
describe('errMessage', () => {
|
||||
test('returns mapped copy when code is known', () => {
|
||||
const expected = ERROR_COPY.track_not_found;
|
||||
expect(errMessage({ code: 'track_not_found' })).toBe(expected);
|
||||
});
|
||||
|
||||
test('returns the unknown-fallback copy when code is missing', () => {
|
||||
const result = errMessage({ code: 'definitely_not_a_real_code_xyz' });
|
||||
expect(result).toBeTruthy();
|
||||
expect(typeof result).toBe('string');
|
||||
expect(result.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('accepts custom fallback parameter without throwing', () => {
|
||||
// copyForCode itself returns a non-empty string for any input, so the
|
||||
// explicit fallback only matters in narrow cases. Just exercise the
|
||||
// signature.
|
||||
const result = errMessage(null, 'custom fallback');
|
||||
expect(typeof result).toBe('string');
|
||||
expect(result.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
import { copyForCode } from './error-copy';
|
||||
|
||||
/**
|
||||
* Returns the `code` field from an unknown error value, or 'unknown'
|
||||
* when the value isn't shaped like { code: string }.
|
||||
*/
|
||||
export function errCode(err: unknown): string {
|
||||
return (err as { code?: string })?.code ?? 'unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns user-facing copy for an unknown error value. Looks up the
|
||||
* error's code in the error-copy map; falls back to the supplied
|
||||
* fallback (default: "Something went wrong.") when the code is unknown.
|
||||
*/
|
||||
export function errMessage(err: unknown, fallback = 'Something went wrong.'): string {
|
||||
return copyForCode(errCode(err)) ?? fallback;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useQueryClient } from '@tanstack/svelte-query';
|
||||
import { createPlaylistsQuery, appendTracks, createPlaylist } from '$lib/api/playlists';
|
||||
import { qk } from '$lib/api/queries';
|
||||
import { copyForCode } from '$lib/api/error-copy';
|
||||
import { errMessage } from '$lib/api/errors';
|
||||
import TrackMenuItem from './TrackMenuItem.svelte';
|
||||
import TrackMenuDivider from './TrackMenuDivider.svelte';
|
||||
import type { TrackRef } from '$lib/api/types';
|
||||
@@ -37,8 +37,7 @@
|
||||
await queryClient.invalidateQueries({ queryKey: qk.playlists() });
|
||||
onClose();
|
||||
} catch (e: unknown) {
|
||||
const code = (e as { code?: string })?.code ?? 'unknown';
|
||||
error = copyForCode(code);
|
||||
error = errMessage(e);
|
||||
} finally {
|
||||
busy = false;
|
||||
}
|
||||
@@ -57,8 +56,7 @@
|
||||
await queryClient.invalidateQueries({ queryKey: qk.playlists() });
|
||||
onClose();
|
||||
} catch (e: unknown) {
|
||||
const code = (e as { code?: string })?.code ?? 'unknown';
|
||||
error = copyForCode(code);
|
||||
error = errMessage(e);
|
||||
} finally {
|
||||
busy = false;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { Flag } from 'lucide-svelte';
|
||||
import { useQueryClient } from '@tanstack/svelte-query';
|
||||
import { flagTrack } from '$lib/api/quarantine';
|
||||
import { errCode } from '$lib/api/errors';
|
||||
import { qk } from '$lib/api/queries';
|
||||
import type { TrackRef, LidarrQuarantineReason } from '$lib/api/types';
|
||||
|
||||
@@ -34,7 +35,8 @@
|
||||
await client.invalidateQueries({ queryKey: qk.myQuarantine() });
|
||||
onClose();
|
||||
} catch (e) {
|
||||
error = (e as { code?: string }).code ?? 'flag_failed';
|
||||
const code = errCode(e);
|
||||
error = code === 'unknown' ? 'flag_failed' : code;
|
||||
} finally {
|
||||
submitting = false;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import type { Playlist, PlaylistTrack, TrackRef } from '$lib/api/types';
|
||||
import { user } from '$lib/auth/store.svelte';
|
||||
import { getPlaylist, refreshDiscover, refreshForYou } from '$lib/api/playlists';
|
||||
import { errCode } from '$lib/api/errors';
|
||||
import { qk } from '$lib/api/queries';
|
||||
import { playQueue } from '$lib/player/store.svelte';
|
||||
|
||||
@@ -95,7 +96,7 @@
|
||||
await queryClient.invalidateQueries({ queryKey: qk.playlist(playlist.id) });
|
||||
await queryClient.invalidateQueries({ queryKey: qk.playlists() });
|
||||
} catch (err: unknown) {
|
||||
showToast(`Refresh failed: ${(err as { code?: string })?.code ?? 'unknown'}`);
|
||||
showToast(`Refresh failed: ${errCode(err)}`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { Trash2 } from 'lucide-svelte';
|
||||
import { useQueryClient } from '@tanstack/svelte-query';
|
||||
import { removeTrack } from '$lib/api/admin/tracks';
|
||||
import { copyForCode } from '$lib/api/error-copy';
|
||||
import { errMessage } from '$lib/api/errors';
|
||||
import { qk } from '$lib/api/queries';
|
||||
import type { TrackRef } from '$lib/api/types';
|
||||
|
||||
@@ -45,8 +45,7 @@
|
||||
// surface (if any) can pick up the flag.
|
||||
onClose();
|
||||
} catch (e: unknown) {
|
||||
const code = (e as { code?: string })?.code ?? 'unknown';
|
||||
error = copyForCode(code);
|
||||
error = errMessage(e);
|
||||
} finally {
|
||||
busy = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user