Alerting: Fix 'Rule group does not exist' error toast (#101949) (#114766)

Alerting: Fix "Rule group does not exist" error toast (#101949)
This commit is contained in:
Sonia Aguilar
2025-12-03 12:33:48 +01:00
committed by GitHub
parent f3ed3a999d
commit b74465e428
2 changed files with 98 additions and 0 deletions
@@ -0,0 +1,92 @@
import { HttpResponse, http } from 'msw';
import { render, screen, waitFor } from 'test/test-utils';
import { AppNotificationList } from 'app/core/components/AppNotifications/AppNotificationList';
import { AccessControlAction } from 'app/types/accessControl';
import { GrafanaRuleIdentifier } from 'app/types/unified-alerting';
import { setupMswServer } from '../mockApi';
import { grantUserPermissions } from '../mocks';
import { grafanaRulerNamespace, grafanaRulerRule } from '../mocks/grafanaRulerApi';
import { GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource';
import { useCombinedRule } from './useCombinedRule';
const server = setupMswServer();
beforeAll(() => {
grantUserPermissions([AccessControlAction.AlertingRuleExternalRead, AccessControlAction.AlertingRuleRead]);
});
// Test component that uses useCombinedRule hook
const UseCombinedRuleTestComponent = ({ ruleIdentifier }: { ruleIdentifier: GrafanaRuleIdentifier }) => {
const { loading, error, result } = useCombinedRule({ ruleIdentifier });
return (
<>
<AppNotificationList />
<div data-testid="loading">{loading ? 'loading' : 'not-loading'}</div>
<div data-testid="error">{error ? 'has-error' : 'no-error'}</div>
<div data-testid="result">{result ? 'has-result' : 'no-result'}</div>
</>
);
};
describe('useCombinedRule', () => {
describe('when rule group returns 404', () => {
it('should not show error notification when rule group does not exist', async () => {
// Mock the getAlertRule endpoint to return a valid rule
server.use(
http.get('/api/ruler/grafana/api/v1/rule/:uid', () => {
return HttpResponse.json(grafanaRulerRule);
})
);
// Mock the ruler group endpoint to return 404 (simulating a new or deleted group)
server.use(
http.get('/api/ruler/grafana/api/v1/rules/:namespace/:group', () => {
return HttpResponse.json({ error: 'rule group does not exist' }, { status: 404 });
})
);
// Mock the prometheus rules endpoint
server.use(
http.get('/api/prometheus/grafana/api/v1/rules', () => {
return HttpResponse.json({
status: 'success',
data: { groups: [] },
});
})
);
// Mock the folder endpoint
server.use(
http.get('/api/folders/:uid', () => {
return HttpResponse.json({
uid: grafanaRulerNamespace.uid,
title: grafanaRulerNamespace.name,
});
})
);
const ruleIdentifier: GrafanaRuleIdentifier = {
ruleSourceName: GRAFANA_RULES_SOURCE_NAME,
uid: grafanaRulerRule.grafana_alert.uid,
};
render(<UseCombinedRuleTestComponent ruleIdentifier={ruleIdentifier} />);
// Wait for the hook to finish loading
await waitFor(() => {
expect(screen.getByTestId('loading')).toHaveTextContent('not-loading');
});
// The hook should have an error (404)
expect(screen.getByTestId('error')).toHaveTextContent('has-error');
// Verify that no error notification was shown
// If showErrorAlert was true, we would see an alert with role="status"
expect(screen.queryByRole('status')).not.toBeInTheDocument();
});
});
});
@@ -68,6 +68,9 @@ export function useCloudCombinedRulesMatching(
rulerConfig: rulerConfig,
namespace: nsGroup.namespace.name,
group: nsGroup.group.name,
// Suppress error notifications for 404s - the group may not exist yet (new group)
// or may have been deleted (last rule removed)
notificationOptions: { showErrorAlert: false },
}).unwrap();
rulerGroups.push(rulerGroup);
})
@@ -145,6 +148,9 @@ export function useCombinedRule({ ruleIdentifier, limitAlerts }: Props): Request
rulerConfig: dsFeatures.rulerConfig,
namespace: ruleLocation.namespace,
group: ruleLocation.group,
// Suppress error notifications for 404s - the group may not exist yet (new group)
// or may have been deleted (last rule removed)
notificationOptions: { showErrorAlert: false },
});
}, [dsFeatures, fetchRulerRuleGroup, ruleLocation]);