import { render, screen, waitFor } from '@testing-library/react'; import WeeklySleepChart from '@/components/analytics/WeeklySleepChart'; import apiClient from '@/lib/api/client'; jest.mock('@/lib/api/client'); const mockApiClient = apiClient as jest.Mocked; describe('WeeklySleepChart', () => { beforeEach(() => { jest.clearAllMocks(); }); it('should render loading state initially', () => { mockApiClient.get.mockImplementation(() => new Promise(() => {})); render(); expect(screen.getByRole('progressbar')).toBeInTheDocument(); }); it('should render sleep data successfully', async () => { const mockSleepData = [ { id: 'slp_1', startTime: new Date('2024-01-01T20:00:00Z').toISOString(), endTime: new Date('2024-01-02T06:00:00Z').toISOString(), duration: 600, // 10 hours quality: 4, }, { id: 'slp_2', startTime: new Date('2024-01-02T20:00:00Z').toISOString(), endTime: new Date('2024-01-03T07:00:00Z').toISOString(), duration: 660, // 11 hours quality: 5, }, ]; mockApiClient.get.mockResolvedValueOnce({ data: { data: mockSleepData, }, }); render(); await waitFor(() => { expect(screen.getByText('Weekly Sleep Patterns')).toBeInTheDocument(); }); expect(screen.getByText('Total Sleep Hours')).toBeInTheDocument(); expect(screen.getByText('Sleep Quality Trend')).toBeInTheDocument(); }); it('should handle API error gracefully', async () => { mockApiClient.get.mockRejectedValueOnce({ response: { data: { message: 'Failed to fetch sleep data', }, }, }); render(); await waitFor(() => { expect(screen.getByRole('alert')).toBeInTheDocument(); expect(screen.getByText('Failed to fetch sleep data')).toBeInTheDocument(); }); }); it('should aggregate sleep data by day', async () => { const mockSleepData = [ { id: 'slp_1', startTime: new Date('2024-01-01T20:00:00Z').toISOString(), duration: 600, // Night sleep quality: 4, }, { id: 'slp_2', startTime: new Date('2024-01-01T14:00:00Z').toISOString(), duration: 120, // Nap quality: 3, }, ]; mockApiClient.get.mockResolvedValueOnce({ data: { data: mockSleepData, }, }); render(); await waitFor(() => { expect(mockApiClient.get).toHaveBeenCalledWith( '/api/v1/activities/sleep', expect.objectContaining({ params: expect.objectContaining({ startDate: expect.any(String), endDate: expect.any(String), }), }) ); }); }); it('should display 7 days of data', async () => { mockApiClient.get.mockResolvedValueOnce({ data: { data: [], }, }); render(); await waitFor(() => { expect(screen.getByText('Weekly Sleep Patterns')).toBeInTheDocument(); }); // Chart should request exactly 7 days of data expect(mockApiClient.get).toHaveBeenCalledWith( '/api/v1/activities/sleep', expect.objectContaining({ params: expect.any(Object), }) ); }); it('should calculate quality average correctly', async () => { const mockSleepData = [ { id: 'slp_1', startTime: new Date('2024-01-01T20:00:00Z').toISOString(), duration: 600, quality: 4, }, { id: 'slp_2', startTime: new Date('2024-01-01T14:00:00Z').toISOString(), duration: 120, quality: 2, }, ]; mockApiClient.get.mockResolvedValueOnce({ data: { data: mockSleepData, }, }); render(); await waitFor(() => { expect(screen.getByText('Sleep Quality Trend')).toBeInTheDocument(); }); // Average quality should be (4 + 2) / 2 = 3 }); });