mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-09 18:15:50 +00:00
test(alerts): verify integrated incident history retry lifecycle
The merged panel now consumes the real request error state, but its existing failure test only toggles a mock. Exercise the hook and Refresh button together so failed reads cannot masquerade as empty history and cached evidence survives a failed refresh. Change-source: pulse-maintainer
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
import { cleanup, fireEvent, render, screen } from '@solidjs/testing-library';
|
||||
import { cleanup, fireEvent, render, screen, waitFor } from '@solidjs/testing-library';
|
||||
import { createSignal, type JSX } from 'solid-js';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { AlertResourceIncidentsPanel } from '../AlertResourceIncidentsPanel';
|
||||
import { AlertsAPI } from '@/api/alerts';
|
||||
import type { Incident } from '@/types/api';
|
||||
import type { AlertHistoryState } from '../useAlertHistoryState';
|
||||
import { useAlertResourceIncidentsState } from '../useAlertResourceIncidentsState';
|
||||
import { aiChatStore } from '@/stores/aiChat';
|
||||
|
||||
vi.mock('@solidjs/router', () => ({
|
||||
@@ -22,6 +26,45 @@ describe('AlertResourceIncidentsPanel', () => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('retries through the real hook and retains cached history after a refresh failure', async () => {
|
||||
let state!: ReturnType<typeof useAlertResourceIncidentsState>;
|
||||
const read = vi.spyOn(AlertsAPI, 'getIncidentsForResource');
|
||||
read.mockRejectedValueOnce(new Error('history unavailable'));
|
||||
render(() => {
|
||||
state = useAlertResourceIncidentsState();
|
||||
return <AlertResourceIncidentsPanel state={state as AlertHistoryState} />;
|
||||
});
|
||||
|
||||
await state.openResourceIncidentPanel('resource-1', 'Resource', 'row-1');
|
||||
expect(screen.getByRole('alert')).toHaveTextContent('Use Refresh');
|
||||
expect(screen.queryByText('No incidents recorded for this resource yet.')).toBeNull();
|
||||
|
||||
let resolve!: (incidents: Incident[]) => void;
|
||||
read.mockImplementationOnce(() => new Promise((done) => { resolve = done; }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Refresh' }));
|
||||
expect(screen.queryByRole('alert')).toBeNull();
|
||||
expect(screen.getByRole('button', { name: /Refresh/ })).toBeDisabled();
|
||||
resolve([{
|
||||
id: 'retained', alertType: 'connectivity', level: 'critical',
|
||||
status: 'resolved', acknowledged: false, events: [],
|
||||
openedAt: '2026-09-08T00:00:00Z', message: 'Retained connection incident',
|
||||
} as Incident]);
|
||||
await waitFor(() => expect(screen.getByText('Retained connection incident')).toBeVisible());
|
||||
expect(read).toHaveBeenLastCalledWith('resource-1', 10);
|
||||
|
||||
read.mockRejectedValueOnce(new Error('refresh unavailable'));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Refresh' }));
|
||||
await waitFor(() => expect(screen.getByRole('alert')).toHaveTextContent('Use Refresh'));
|
||||
expect(screen.getByText('Retained connection incident')).toBeVisible();
|
||||
expect(screen.queryByText('No incidents recorded for this resource yet.')).toBeNull();
|
||||
|
||||
read.mockResolvedValueOnce([]);
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Refresh' }));
|
||||
await waitFor(() => expect(screen.getByText('No incidents recorded for this resource yet.')).toBeVisible());
|
||||
expect(screen.queryByRole('alert')).toBeNull();
|
||||
expect(screen.queryByText('Retained connection incident')).toBeNull();
|
||||
});
|
||||
|
||||
it('shows persistent read failure without claiming an empty history', () => {
|
||||
const [failed, setFailed] = createSignal(true);
|
||||
render(() => (
|
||||
|
||||
Reference in New Issue
Block a user