/** * Component: Admin Settings - Indexers Tab Auto-load Test * Documentation: documentation/testing.md * * This test verifies that indexers are automatically loaded when: * 1. The prowlarr tab becomes active * 2. Prowlarr URL and API key are configured * * @vitest-environment jsdom */ import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import { IndexersTab } from '@/app/admin/settings/tabs/IndexersTab'; import type { Settings, SavedIndexerConfig } from '@/app/admin/settings/lib/types'; import { IndexerFlagConfig } from '@/lib/utils/ranking-algorithm'; // Mock fetchWithAuth const mockFetchWithAuth = vi.fn(); vi.mock('@/lib/utils/api', () => ({ fetchWithAuth: (url: string, options?: any) => mockFetchWithAuth(url, options), })); // Mock child components to simplify testing vi.mock('@/components/admin/indexers/IndexerManagement', () => ({ IndexerManagement: ({ initialIndexers }: { initialIndexers: SavedIndexerConfig[] }) => (
{initialIndexers.length > 0 ? (
{initialIndexers.length} indexers loaded
) : (
No indexers
)}
), })); vi.mock('@/components/admin/FlagConfigRow', () => ({ FlagConfigRow: () =>
Flag Config
, })); vi.mock('@/components/ui/Button', () => ({ Button: ({ children, onClick, loading, disabled, ...props }: any) => ( ), })); vi.mock('@/components/ui/Input', () => ({ Input: (props: any) => , })); describe('IndexersTab - Auto-load Indexers on Tab Activation', () => { const mockSettings: Settings = { backendMode: 'plex', hasLocalUsers: false, audibleRegion: 'us', plex: { url: 'http://plex.local:32400', token: 'test-token', libraryId: '1', triggerScanAfterImport: false, }, audiobookshelf: { serverUrl: '', apiToken: '', libraryId: '', triggerScanAfterImport: false, }, oidc: { enabled: false, providerName: '', issuerUrl: '', clientId: '', clientSecret: '', accessControlMethod: 'open', accessGroupClaim: '', accessGroupValue: '', allowedEmails: '', allowedUsernames: '', adminClaimEnabled: false, adminClaimName: '', adminClaimValue: '', }, registration: { enabled: false, requireAdminApproval: false, }, prowlarr: { url: 'http://prowlarr.local:9696', apiKey: 'test-api-key', }, downloadClient: { type: 'qbittorrent', url: 'http://localhost:8080', username: 'admin', password: 'password', disableSSLVerify: false, remotePathMappingEnabled: false, remotePath: '', localPath: '', }, paths: { downloadDir: '/downloads', mediaDir: '/media', metadataTaggingEnabled: true, chapterMergingEnabled: true, }, ebook: { enabled: false, preferredFormat: 'epub', baseUrl: 'https://annas-archive.gl', flaresolverrUrl: '', }, }; const mockIndexers: SavedIndexerConfig[] = [ { id: 1, name: 'AudioBook Bay', protocol: 'torrent', priority: 10, seedingTimeMinutes: 4320, rssEnabled: true, categories: [3030], }, { id: 2, name: 'MyAnonaMouse', protocol: 'usenet', priority: 15, removeAfterProcessing: true, rssEnabled: false, categories: [3030], }, ]; const mockFlagConfigs: IndexerFlagConfig[] = []; beforeEach(() => { vi.clearAllMocks(); }); it('should display empty indexers when no indexers are loaded', () => { const { container } = render( ); expect(screen.getByTestId('indexers-empty')).toBeInTheDocument(); }); it('should display indexers when indexers prop contains data', () => { render( ); expect(screen.getByTestId('indexers-loaded')).toBeInTheDocument(); expect(screen.getByText('2 indexers loaded')).toBeInTheDocument(); }); it('BUG: should automatically fetch indexers when onRefreshIndexers is called on mount', async () => { const mockOnRefreshIndexers = vi.fn().mockResolvedValue(undefined); render( ); // The bug: onRefreshIndexers should be called automatically when the component mounts // IF prowlarr URL and API key are configured await waitFor(() => { expect(mockOnRefreshIndexers).toHaveBeenCalledTimes(1); }, { timeout: 1000 }); }); it('should NOT auto-fetch indexers if prowlarr URL is missing', async () => { const mockOnRefreshIndexers = vi.fn().mockResolvedValue(undefined); const settingsWithoutUrl = { ...mockSettings, prowlarr: { url: '', apiKey: 'test-api-key' }, }; render( ); // Should NOT call onRefreshIndexers because URL is missing await new Promise((resolve) => setTimeout(resolve, 100)); expect(mockOnRefreshIndexers).not.toHaveBeenCalled(); }); it('should NOT auto-fetch indexers if prowlarr API key is missing', async () => { const mockOnRefreshIndexers = vi.fn().mockResolvedValue(undefined); const settingsWithoutApiKey = { ...mockSettings, prowlarr: { url: 'http://prowlarr.local:9696', apiKey: '' }, }; render( ); // Should NOT call onRefreshIndexers because API key is missing await new Promise((resolve) => setTimeout(resolve, 100)); expect(mockOnRefreshIndexers).not.toHaveBeenCalled(); }); });