chore: prepare local.3 release with query regression coverage
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
import {
|
||||
deleteLibrary,
|
||||
getConfig,
|
||||
getStorage,
|
||||
updateConfig,
|
||||
updateLibrary,
|
||||
type AdminConfigDto,
|
||||
type LibraryResponseDto,
|
||||
} from '@immich/sdk';
|
||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||
import { executeMutation, queryClient } from '$lib/queries/client';
|
||||
import {
|
||||
deleteLibraryMutation,
|
||||
getAllLibrariesQuery,
|
||||
getLibraryStatisticsQuery,
|
||||
updateLibraryMutation,
|
||||
} from '$lib/queries/library.query';
|
||||
import { getStorageQuery } from '$lib/queries/server.query';
|
||||
import { getConfigQuery, updateConfigMutation } from '$lib/queries/system-config.query';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
|
||||
vi.mock('@immich/ui', () => ({ toastManager: { primary: vi.fn(), info: vi.fn() } }));
|
||||
vi.mock('$lib/utils/handle-error', () => ({ handleError: vi.fn() }));
|
||||
vi.mock('$lib/utils/i18n', () => ({ getFormatter: async () => (key: string) => key }));
|
||||
vi.mock('@immich/sdk', () => ({
|
||||
createLibrary: vi.fn(),
|
||||
deleteLibrary: vi.fn(),
|
||||
getAllLibraries: vi.fn(),
|
||||
getLibraryStatistics: vi.fn(),
|
||||
scanLibrary: vi.fn(),
|
||||
updateLibrary: vi.fn(),
|
||||
getAboutInfo: vi.fn(),
|
||||
getVersionHistory: vi.fn(),
|
||||
getStorage: vi.fn(),
|
||||
getServerStatistics: vi.fn(),
|
||||
getConfig: vi.fn(),
|
||||
getConfigDefaults: vi.fn(),
|
||||
updateConfig: vi.fn(),
|
||||
}));
|
||||
|
||||
const first = { id: 'first', name: 'Photos' } as LibraryResponseDto;
|
||||
const second = { id: 'second', name: 'Archive' } as LibraryResponseDto;
|
||||
|
||||
describe('shared queries after the upstream migration', () => {
|
||||
beforeEach(() => {
|
||||
queryClient.clear();
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => queryClient.clear());
|
||||
|
||||
it('clears account data on logout', () => {
|
||||
queryClient.setQueryData(getAllLibrariesQuery().queryKey, [first]);
|
||||
queryClient.setQueryData(getConfigQuery().queryKey, {} as AdminConfigDto);
|
||||
eventManager.emit('AuthLogout');
|
||||
expect(queryClient.getQueryCache().getAll()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('shares a storage request between consumers', async () => {
|
||||
const storage = { diskSizeRaw: 100, diskUseRaw: 20 } as Awaited<ReturnType<typeof getStorage>>;
|
||||
vi.mocked(getStorage).mockResolvedValue(storage);
|
||||
const values = await Promise.all([queryClient.query(getStorageQuery()), queryClient.query(getStorageQuery())]);
|
||||
expect(values).toEqual([storage, storage]);
|
||||
expect(getStorage).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('preserves libraries and statistics when deletion fails', async () => {
|
||||
queryClient.setQueryData(getAllLibrariesQuery().queryKey, [first, second]);
|
||||
queryClient.setQueryData(getLibraryStatisticsQuery(first.id).queryKey, {
|
||||
photos: 5,
|
||||
videos: 0,
|
||||
usage: 100,
|
||||
total: 5,
|
||||
});
|
||||
vi.mocked(deleteLibrary).mockRejectedValue(new Error('offline'));
|
||||
await executeMutation(deleteLibraryMutation, [{ id: first.id }]);
|
||||
expect(queryClient.getQueryData(getAllLibrariesQuery().queryKey)).toEqual([first, second]);
|
||||
expect(queryClient.getQueryData(getLibraryStatisticsQuery(first.id).queryKey)?.photos).toBe(5);
|
||||
expect(handleError).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('removes only the deleted library from the cache after success', async () => {
|
||||
queryClient.setQueryData(getAllLibrariesQuery().queryKey, [first, second]);
|
||||
queryClient.setQueryData(getLibraryStatisticsQuery(first.id).queryKey, {
|
||||
photos: 5,
|
||||
videos: 0,
|
||||
usage: 100,
|
||||
total: 5,
|
||||
});
|
||||
vi.mocked(deleteLibrary).mockResolvedValue(undefined as never);
|
||||
await executeMutation(deleteLibraryMutation, [{ id: first.id }]);
|
||||
expect(queryClient.getQueryData(getAllLibrariesQuery().queryKey)).toEqual([second]);
|
||||
expect(queryClient.getQueryData(getLibraryStatisticsQuery(first.id).queryKey)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('uses the saved library response and refreshes its statistics', async () => {
|
||||
queryClient.setQueryData(getAllLibrariesQuery().queryKey, [first, second]);
|
||||
queryClient.setQueryData(getLibraryStatisticsQuery(first.id).queryKey, {
|
||||
photos: 5,
|
||||
videos: 0,
|
||||
usage: 100,
|
||||
total: 5,
|
||||
});
|
||||
const saved = { ...first, name: 'Renamed' };
|
||||
vi.mocked(updateLibrary).mockResolvedValue(saved);
|
||||
await executeMutation(updateLibraryMutation, [{ id: first.id, updateLibraryDto: { name: saved.name } }]);
|
||||
expect(queryClient.getQueryData(getAllLibrariesQuery().queryKey)).toEqual([saved, second]);
|
||||
expect(queryClient.getQueryState(getLibraryStatisticsQuery(first.id).queryKey)?.isInvalidated).toBe(true);
|
||||
});
|
||||
|
||||
it('merges a settings edit with the latest server configuration', async () => {
|
||||
const current = { server: { externalDomain: 'https://example.com' }, trash: { enabled: true, days: 30 } };
|
||||
const update = { trash: { enabled: true, days: 60 } };
|
||||
const saved = { ...current, ...update } as AdminConfigDto;
|
||||
vi.mocked(getConfig).mockResolvedValue(current as AdminConfigDto);
|
||||
vi.mocked(updateConfig).mockResolvedValue(saved);
|
||||
await executeMutation(updateConfigMutation, update);
|
||||
expect(updateConfig).toHaveBeenCalledWith({ adminConfigDto: saved });
|
||||
expect(queryClient.getQueryData(getConfigQuery().queryKey)).toEqual(saved);
|
||||
});
|
||||
|
||||
it('keeps the previous settings if saving fails', async () => {
|
||||
const current = { trash: { enabled: true, days: 30 } } as AdminConfigDto;
|
||||
queryClient.setQueryData(getConfigQuery().queryKey, current);
|
||||
vi.mocked(getConfig).mockResolvedValue(current);
|
||||
vi.mocked(updateConfig).mockRejectedValue(new Error('offline'));
|
||||
await executeMutation(updateConfigMutation, { trash: { enabled: true, days: 60 } });
|
||||
expect(queryClient.getQueryData(getConfigQuery().queryKey)).toEqual(current);
|
||||
expect(handleError).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user