import { describe, it, expect, beforeEach, vi } from 'vitest'; import { renderHook, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import type { ReactNode } from 'react'; import { useEnvironmentStore } from '../environment-store'; vi.mock('../client', () => ({ api: { GET: vi.fn(), POST: vi.fn() }, })); import { api as apiClient } from '../client'; import { useAlerts, useUnreadCount } from './alerts'; function wrapper({ children }: { children: ReactNode }) { const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } }); return {children}; } describe('useAlerts', () => { beforeEach(() => { vi.clearAllMocks(); useEnvironmentStore.setState({ environment: 'dev' }); }); it('forwards state + severity filters to the server as query params', async () => { (apiClient.GET as any).mockResolvedValue({ data: [], error: null }); const { result } = renderHook( () => useAlerts({ state: 'FIRING', severity: ['CRITICAL', 'WARNING'] }), { wrapper }, ); await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(apiClient.GET).toHaveBeenCalledWith( '/environments/{envSlug}/alerts', expect.objectContaining({ params: expect.objectContaining({ path: { envSlug: 'dev' }, query: { limit: 200, state: ['FIRING'], severity: ['CRITICAL', 'WARNING'], }, }), }), ); }); it('omits state + severity when no filter is set', async () => { (apiClient.GET as any).mockResolvedValue({ data: [], error: null }); const { result } = renderHook(() => useAlerts(), { wrapper }); await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(apiClient.GET).toHaveBeenCalledWith( '/environments/{envSlug}/alerts', expect.objectContaining({ params: expect.objectContaining({ path: { envSlug: 'dev' }, query: { limit: 200 }, }), }), ); }); it('still applies ruleId client-side via select', async () => { const dataset = [ { id: '1', ruleId: 'R1', state: 'FIRING', severity: 'WARNING', title: 'a' }, { id: '2', ruleId: 'R2', state: 'FIRING', severity: 'WARNING', title: 'b' }, ]; (apiClient.GET as any).mockResolvedValue({ data: dataset, error: null }); const { result } = renderHook( () => useAlerts({ ruleId: 'R2' }), { wrapper }, ); await waitFor(() => expect(result.current.isSuccess).toBe(true)); const ids = (result.current.data ?? []).map((a: any) => a.id); expect(ids).toEqual(['2']); }); it('does not fetch when no env is selected', () => { useEnvironmentStore.setState({ environment: undefined }); const { result } = renderHook(() => useAlerts(), { wrapper }); expect(result.current.fetchStatus).toBe('idle'); expect(apiClient.GET).not.toHaveBeenCalled(); }); }); describe('useUnreadCount', () => { beforeEach(() => { vi.clearAllMocks(); useEnvironmentStore.setState({ environment: 'dev' }); }); it('returns the server payload unmodified', async () => { (apiClient.GET as any).mockResolvedValue({ data: { count: 3 }, error: null, }); const { result } = renderHook(() => useUnreadCount(), { wrapper }); await waitFor(() => expect(result.current.isSuccess).toBe(true)); expect(result.current.data).toEqual({ count: 3 }); }); });