mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +00:00
0feb54ac33
Merge album/FTS/track sources for title search (any-word LIKE + prefix FTS), dedupe cluster text hits by album id instead of album_key, route scoped cluster browse through per-server advanced search, and prefer the local index over network race when the library index is enabled.
102 lines
3.5 KiB
TypeScript
102 lines
3.5 KiB
TypeScript
import { renderHook, waitFor } from '@testing-library/react';
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const runLocalBrowseAlbums = vi.fn();
|
|
const runNetworkBrowseAlbums = vi.fn();
|
|
const isClusterMultiLibraryScopeBrowse = vi.fn();
|
|
const isClusterMode = vi.fn();
|
|
|
|
vi.mock('../utils/library/browseTextSearch', () => ({
|
|
BROWSE_TEXT_DEBOUNCE_RACE_MS: 0,
|
|
BROWSE_TEXT_DEBOUNCE_NETWORK_MS: 0,
|
|
runLocalBrowseAlbums: (...args: unknown[]) => runLocalBrowseAlbums(...args),
|
|
runNetworkBrowseAlbums: (...args: unknown[]) => runNetworkBrowseAlbums(...args),
|
|
}));
|
|
|
|
vi.mock('../utils/serverCluster/clusterScope', () => ({
|
|
isClusterMode: () => isClusterMode(),
|
|
}));
|
|
|
|
vi.mock('../utils/serverCluster/clusterLibraryScopes', () => ({
|
|
isClusterMultiLibraryScopeBrowse: () => isClusterMultiLibraryScopeBrowse(),
|
|
}));
|
|
|
|
import { useBrowseAlbumTextSearch } from './useBrowseAlbumTextSearch';
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
isClusterMultiLibraryScopeBrowse.mockReturnValue(false);
|
|
isClusterMode.mockReturnValue(false);
|
|
runLocalBrowseAlbums.mockResolvedValue([
|
|
{ id: 'al-1', name: 'Local', artist: 'A', artistId: 'a', songCount: 1, duration: 1 },
|
|
]);
|
|
runNetworkBrowseAlbums.mockResolvedValue([
|
|
{ id: 'net-1', name: 'Net', artist: 'B', artistId: 'b', songCount: 1, duration: 1 },
|
|
]);
|
|
});
|
|
|
|
describe('useBrowseAlbumTextSearch', () => {
|
|
it('uses local cluster index only when multi-library scope is active', async () => {
|
|
isClusterMultiLibraryScopeBrowse.mockReturnValue(true);
|
|
|
|
const { result } = renderHook(() =>
|
|
useBrowseAlbumTextSearch('beatles', true, 'srv-a'),
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(result.current.textSearchLoading).toBe(false);
|
|
expect(runLocalBrowseAlbums).toHaveBeenCalled();
|
|
});
|
|
|
|
expect(runLocalBrowseAlbums).toHaveBeenCalledWith('srv-a', 'beatles', undefined, false, true);
|
|
expect(runNetworkBrowseAlbums).not.toHaveBeenCalled();
|
|
expect(result.current.textSearchAlbums).toHaveLength(1);
|
|
expect(result.current.textSearchAlbums![0].id).toBe('al-1');
|
|
});
|
|
|
|
it('uses local index only in cluster mode', async () => {
|
|
isClusterMode.mockReturnValue(true);
|
|
|
|
const { result } = renderHook(() =>
|
|
useBrowseAlbumTextSearch('beatles', true, 'srv-a'),
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(result.current.textSearchLoading).toBe(false);
|
|
expect(runLocalBrowseAlbums).toHaveBeenCalled();
|
|
});
|
|
|
|
expect(runNetworkBrowseAlbums).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('prefers local index when enabled and falls back to network only when local is unavailable', async () => {
|
|
const { result } = renderHook(() =>
|
|
useBrowseAlbumTextSearch('beatles', true, 'srv-a'),
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(result.current.textSearchLoading).toBe(false);
|
|
expect(runLocalBrowseAlbums).toHaveBeenCalled();
|
|
});
|
|
|
|
expect(runLocalBrowseAlbums).toHaveBeenCalledWith('srv-a', 'beatles', undefined, false, false);
|
|
expect(runNetworkBrowseAlbums).not.toHaveBeenCalled();
|
|
expect(result.current.textSearchAlbums![0].id).toBe('al-1');
|
|
});
|
|
|
|
it('falls back to network when the local index cannot serve the query', async () => {
|
|
runLocalBrowseAlbums.mockResolvedValueOnce(null);
|
|
|
|
const { result } = renderHook(() =>
|
|
useBrowseAlbumTextSearch('beatles', true, 'srv-a'),
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(result.current.textSearchLoading).toBe(false);
|
|
expect(runNetworkBrowseAlbums).toHaveBeenCalled();
|
|
});
|
|
|
|
expect(result.current.textSearchAlbums![0].id).toBe('net-1');
|
|
});
|
|
});
|