import { screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { render } from 'utils/testRenderer'; import { testServerRoute, testServerSetup } from 'utils/testServer'; import { useImpactMetricsState } from './useImpactMetricsState.ts'; import type { FC } from 'react'; import type { ImpactMetricsState } from '../types.ts'; const server = testServerSetup(); const TestComponent: FC<{ enableActions?: boolean; }> = ({ enableActions = false }) => { const { charts, layout, loading, error, addChart, updateChart, deleteChart, } = useImpactMetricsState(); return (
{charts.length} {layout.length} {loading.toString()} {error ? 'has-error' : 'no-error'} {enableActions && ( )} {enableActions && charts.length > 0 && ( )} {enableActions && charts.length > 0 && ( )}
); }; const mockSettings: ImpactMetricsState = { charts: [ { id: 'test-chart', metricName: 'test-series', timeRange: 'day' as const, yAxisMin: 'zero', aggregationMode: 'count', labelSelectors: {}, title: 'Test Chart', }, ], layout: [ { i: 'test-chart', x: 0, y: 0, w: 6, h: 4, minW: 4, minH: 2, maxW: 12, maxH: 8, }, ], }; const emptySettings: ImpactMetricsState = { charts: [], layout: [], }; describe('useImpactMetricsState', () => { beforeEach(() => { testServerRoute(server, '/api/admin/ui-config', {}); }); it('loads settings from API', async () => { testServerRoute( server, '/api/admin/impact-metrics/settings', mockSettings, ); render(); await waitFor(() => { expect(screen.getByTestId('charts-count')).toHaveTextContent('1'); expect(screen.getByTestId('layout-count')).toHaveTextContent('1'); expect(screen.getByTestId('loading')).toHaveTextContent('false'); expect(screen.getByTestId('error')).toHaveTextContent('no-error'); }); }); it('handles empty settings', async () => { testServerRoute( server, '/api/admin/impact-metrics/settings', emptySettings, ); render(); await waitFor(() => { expect(screen.getByTestId('charts-count')).toHaveTextContent('0'); expect(screen.getByTestId('layout-count')).toHaveTextContent('0'); expect(screen.getByTestId('loading')).toHaveTextContent('false'); expect(screen.getByTestId('error')).toHaveTextContent('no-error'); }); }); it('handles API errors', async () => { testServerRoute( server, '/api/admin/impact-metrics/settings', { message: 'Server error' }, 'get', 500, ); render(); await waitFor(() => { expect(screen.getByTestId('error')).toHaveTextContent('has-error'); }); }); it('adds a chart successfully', async () => { testServerRoute( server, '/api/admin/impact-metrics/settings', emptySettings, ); render(); await waitFor(() => { expect(screen.getByTestId('charts-count')).toHaveTextContent('0'); }); testServerRoute( server, '/api/admin/impact-metrics/settings', { charts: [ { id: 'new-chart-id', metricName: 'test-series', timeRange: 'day', yAxisMin: 'zero', mode: 'count', labelSelectors: {}, title: 'Test Chart', }, ], layout: [ { i: 'new-chart-id', x: 0, y: 0, w: 6, h: 4, minW: 4, minH: 2, maxW: 12, maxH: 8, }, ], }, 'put', 200, ); testServerRoute( server, '/api/admin/impact-metrics/settings', { charts: [ { id: 'new-chart-id', metricName: 'test-series', timeRange: 'day', yAxisMin: 'zero', mode: 'count', labelSelectors: {}, title: 'Test Chart', }, ], layout: [ { i: 'new-chart-id', x: 0, y: 0, w: 6, h: 4, minW: 4, minH: 2, maxW: 12, maxH: 8, }, ], }, 'get', 200, ); const addButton = screen.getByTestId('add-chart'); await userEvent.click(addButton); await waitFor( () => { expect(screen.getByTestId('charts-count')).toHaveTextContent( '1', ); }, { timeout: 5000 }, ); }); it('updates a chart successfully', async () => { testServerRoute( server, '/api/admin/impact-metrics/settings', mockSettings, ); testServerRoute( server, '/api/admin/impact-metrics/settings', { charts: [ { ...mockSettings.charts[0], title: 'Updated Chart', }, ], layout: mockSettings.layout, }, 'put', 200, ); render(); await waitFor(() => { expect(screen.getByTestId('charts-count')).toHaveTextContent('1'); }); const updateButton = screen.getByTestId('update-chart'); await userEvent.click(updateButton); await waitFor(() => { expect(screen.getByTestId('charts-count')).toHaveTextContent('1'); }); }); it('deletes a chart successfully', async () => { testServerRoute( server, '/api/admin/impact-metrics/settings', mockSettings, ); render(); await waitFor(() => { expect(screen.getByTestId('charts-count')).toHaveTextContent('1'); }); testServerRoute( server, '/api/admin/impact-metrics/settings', emptySettings, 'put', 200, ); testServerRoute( server, '/api/admin/impact-metrics/settings', emptySettings, 'get', 200, ); const deleteButton = screen.getByTestId('delete-chart'); await userEvent.click(deleteButton); await waitFor( () => { expect(screen.getByTestId('charts-count')).toHaveTextContent( '0', ); }, { timeout: 5000 }, ); }); });