mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-02 20:30:10 +00:00
Add Transmission/NZBGet and per-client paths and much more
Extend multi-download-client support to include Transmission and NZBGet and introduce per-client custom download paths. Adds protocol mapping and new client types, Transmission/NZBGet integration services, API CRUD and validation changes, UI components/modal updates and live path previews, and manager routing by protocol. Includes DB migrations (download_path on download_history, interactive_search_access on users), schema updates, and related processor/service fixes and tests to ensure backward compatibility and proper path resolution.
This commit is contained in:
@@ -51,7 +51,7 @@ describe('IndexerConfigModal', () => {
|
||||
expect(onClose).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('validates that at least one category is selected', () => {
|
||||
it('shows warning when all audiobook categories are deselected but still allows save', () => {
|
||||
const onSave = vi.fn();
|
||||
|
||||
render(
|
||||
@@ -72,11 +72,18 @@ describe('IndexerConfigModal', () => {
|
||||
}
|
||||
|
||||
fireEvent.click(within(audiobookRow).getByRole('switch'));
|
||||
|
||||
// Warning should be shown instead of blocking save
|
||||
expect(screen.getByText(/will not be searched for audiobooks/i)).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Add Indexer' }));
|
||||
|
||||
// Component now shows specific error for audiobook categories
|
||||
expect(screen.getByText('At least one audiobook category must be selected')).toBeInTheDocument();
|
||||
expect(onSave).not.toHaveBeenCalled();
|
||||
// Save should still be called with empty audiobook categories
|
||||
expect(onSave).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
audiobookCategories: [],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('forces RSS to false when the indexer does not support RSS', () => {
|
||||
|
||||
@@ -34,6 +34,22 @@ vi.mock('next/image', () => ({
|
||||
default: (props: any) => <img {...props} />,
|
||||
}));
|
||||
|
||||
vi.mock('@/contexts/PreferencesContext', () => ({
|
||||
usePreferences: () => ({ squareCovers: false, setSquareCovers: vi.fn(), cardSize: 5, setCardSize: vi.fn() }),
|
||||
}));
|
||||
|
||||
vi.mock('@/contexts/AuthContext', () => ({
|
||||
useAuth: () => ({
|
||||
user: { id: 'user-1', role: 'user', permissions: { interactiveSearch: true } },
|
||||
accessToken: 'test-token',
|
||||
isLoading: false,
|
||||
login: vi.fn(),
|
||||
logout: vi.fn(),
|
||||
refreshToken: vi.fn(),
|
||||
setAuthData: vi.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
const baseRequest = {
|
||||
id: 'req-1',
|
||||
status: 'pending',
|
||||
|
||||
@@ -30,13 +30,16 @@ describe('VersionBadge', () => {
|
||||
it('renders semantic version from build-time env var', async () => {
|
||||
process.env.NEXT_PUBLIC_APP_VERSION = '1.0.0';
|
||||
process.env.NEXT_PUBLIC_GIT_COMMIT = 'abcdef1234';
|
||||
const fetchMock = vi.fn();
|
||||
const fetchMock = vi.fn().mockResolvedValue({
|
||||
json: async () => ({ version: '1.0.0' }),
|
||||
});
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
|
||||
render(<VersionBadge />);
|
||||
|
||||
expect(await screen.findByText('v1.0.0')).toBeInTheDocument();
|
||||
expect(fetchMock).not.toHaveBeenCalled();
|
||||
// Should not call /api/version since build-time version is available
|
||||
expect(fetchMock).not.toHaveBeenCalledWith('/api/version');
|
||||
});
|
||||
|
||||
it('falls back to API when build-time version is unavailable', async () => {
|
||||
|
||||
Reference in New Issue
Block a user