From 0641034be51e25c603a89c96c018607833bdc8cd Mon Sep 17 00:00:00 2001
From: "pulse-triage[bot]"
<249995291+pulse-triage[bot]@users.noreply.github.com>
Date: Sun, 6 Sep 2026 01:37:08 +0100
Subject: [PATCH] test(alerts): exercise overview delivery recovery actions
The overview only asserted that recovery buttons were present. Exercise cancellation, failure and deferred action/health completion so regressions cannot silently clear attention or allow conflicting actions while recovery is pending. APIs remain mocked; this does not qualify installed delivery.
Change-source: pulse-maintainer
---
.../OverviewTab.deliveryactions.test.tsx | 73 ++++++++++++++++++-
1 file changed, 72 insertions(+), 1 deletion(-)
diff --git a/frontend-modern/src/features/alerts/__tests__/OverviewTab.deliveryactions.test.tsx b/frontend-modern/src/features/alerts/__tests__/OverviewTab.deliveryactions.test.tsx
index c177bc613..1851cf704 100644
--- a/frontend-modern/src/features/alerts/__tests__/OverviewTab.deliveryactions.test.tsx
+++ b/frontend-modern/src/features/alerts/__tests__/OverviewTab.deliveryactions.test.tsx
@@ -1,5 +1,5 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
-import { cleanup, render, screen, waitFor } from '@solidjs/testing-library';
+import { cleanup, fireEvent, render, screen, waitFor } from '@solidjs/testing-library';
import { DEFAULT_LOCALE, setActiveLocale } from '@/i18n';
import type { Alert } from '@/types/api';
import type { NotificationHealth } from '@/api/notifications';
@@ -49,6 +49,8 @@ vi.mock('@/components/Alerts/InvestigateAlertButton', () => ({
InvestigateAlertButton: () => null,
}));
+import { notificationStore } from '@/stores/notifications';
+
import { OverviewTab } from '../OverviewTab';
function degradedHealth(): NotificationHealth {
@@ -107,10 +109,15 @@ describe('OverviewTab delivery health actions', () => {
getDeliveryDiagnoses.mockReset();
getDeliveryDiagnoses.mockResolvedValue([]);
getHealth.mockReset();
+ retryTerminalFailures.mockReset();
+ dismissTerminalFailures.mockReset();
+ vi.mocked(notificationStore.success).mockClear();
+ vi.mocked(notificationStore.error).mockClear();
});
afterEach(() => {
cleanup();
+ vi.restoreAllMocks();
setActiveLocale(DEFAULT_LOCALE);
});
@@ -127,4 +134,68 @@ describe('OverviewTab delivery health actions', () => {
expect(screen.queryByRole('button', { name: 'Refresh delivery status' })).toBeNull();
expect(screen.getByRole('alert')).toHaveTextContent('Most recent failures: connectivity (1).');
});
+ for (const action of [
+ { name: 'Retry retained deliveries', api: retryTerminalFailures },
+ { name: 'Dismiss retained failures', api: dismissTerminalFailures },
+ ]) {
+ it(`does not mutate or refresh when ${action.name} is cancelled`, async () => {
+ getHealth.mockResolvedValue(degradedHealth());
+ const confirmation = vi.spyOn(window, 'confirm').mockReturnValue(false);
+ render(() => );
+ fireEvent.click(await screen.findByRole('button', { name: action.name }));
+
+ expect(confirmation).toHaveBeenCalledOnce();
+ expect(action.api).not.toHaveBeenCalled();
+ expect(getHealth).toHaveBeenCalledTimes(1);
+ expect(screen.getByRole('alert')).toBeTruthy();
+ });
+
+ it(`retains attention and enables another attempt when ${action.name} fails`, async () => {
+ getHealth.mockResolvedValue(degradedHealth());
+ vi.spyOn(window, 'confirm').mockReturnValue(true);
+ action.api.mockRejectedValue(new Error('queue action unavailable'));
+ render(() => );
+ fireEvent.click(await screen.findByRole('button', { name: action.name }));
+
+ await waitFor(() => expect(notificationStore.error).toHaveBeenCalledOnce());
+ expect(notificationStore.success).not.toHaveBeenCalled();
+ expect(getHealth).toHaveBeenCalledTimes(1);
+ expect(screen.getByRole('alert')).toHaveTextContent('connectivity (1)');
+ expect(screen.getByRole('button', { name: action.name })).not.toBeDisabled();
+ });
+
+ it(`keeps both actions disabled until ${action.name} and its health refresh finish`, async () => {
+ const healthy = degradedHealth();
+ healthy.overallHealthy = true;
+ healthy.queue = { ...healthy.queue, status: 'healthy', healthy: true, attentionRequired: 0, deadLetter: 0 };
+ let completeAction!: (value: { affected: number }) => void;
+ let completeHealth!: (value: NotificationHealth) => void;
+ action.api.mockReturnValue(new Promise(resolve => { completeAction = resolve; }));
+ getHealth.mockResolvedValueOnce(degradedHealth()).mockReturnValueOnce(
+ new Promise(resolve => { completeHealth = resolve; }),
+ );
+ vi.spyOn(window, 'confirm').mockReturnValue(true);
+ render(() => );
+ fireEvent.click(await screen.findByRole('button', { name: action.name }));
+
+ const expectActionsDisabled = () => {
+ const buttons = screen.getByRole('alert').querySelectorAll('button');
+ expect(buttons.length).toBe(2);
+ for (const button of buttons) expect(button).toBeDisabled();
+ };
+ expectActionsDisabled();
+ expect(getHealth).toHaveBeenCalledTimes(1);
+ completeAction({ affected: 85 });
+ await waitFor(() => expect(getHealth).toHaveBeenCalledTimes(2));
+ expectActionsDisabled();
+ expect(screen.getByRole('alert')).toBeTruthy();
+
+ completeHealth(healthy);
+ await waitFor(() => expect(screen.queryByRole('alert')).toBeNull());
+ expect(action.api).toHaveBeenCalledOnce();
+ expect(notificationStore.success).toHaveBeenCalledOnce();
+ expect(notificationStore.error).not.toHaveBeenCalled();
+ });
+ }
+
});