diff --git a/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.test.tsx b/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.test.tsx index 8653c39f707..c5923c00c02 100644 --- a/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.test.tsx +++ b/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.test.tsx @@ -17,6 +17,7 @@ import { mockDataSource, mockPluginLinkExtension, mockPromAlertingRule, + mockRulerGrafanaRecordingRule, } from '../../mocks'; import { grafanaRulerRule } from '../../mocks/grafanaRulerApi'; import { grantPermissionsHelper } from '../../test/test-utils'; @@ -184,6 +185,30 @@ describe('RuleViewer', () => { } }); + it('shows paused state correctly for recording rules', async () => { + const recordingRule = getGrafanaRule({ + name: 'Test recording rule', + rulerRule: mockRulerGrafanaRecordingRule( + {}, + { + is_paused: true, + title: 'Test recording', + record: { + metric: 'test_recording', + from: 'A', + }, + } + ), + }); + + const recordingRuleIdentifier = ruleId.fromCombinedRule('grafana', recordingRule); + await renderRuleViewer(recordingRule, recordingRuleIdentifier, ActiveTab.Details); + + expect(await screen.findByText('Test recording rule')).toBeInTheDocument(); + expect(await screen.findByRole('status', { name: 'Alert evaluation currently paused' })).toBeInTheDocument(); + expect(screen.queryByText(/last evaluation duration/i)).not.toBeInTheDocument(); + }); + it('renders silencing form correctly and shows alert rule name', async () => { await renderRuleViewer(mockRule, mockRuleIdentifier); await openSilenceDrawer(); diff --git a/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.tsx b/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.tsx index 82e46f5c574..6a25509e67c 100644 --- a/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.tsx +++ b/public/app/features/alerting/unified/components/rule-viewer/RuleViewer.tsx @@ -73,7 +73,7 @@ const RuleViewer = () => { const isFederatedRule = isFederatedRuleGroup(rule.group); const isProvisioned = rulerRuleType.grafana.rule(rulerRule) && Boolean(rulerRule.grafana_alert.provenance); - const isPaused = rulerRuleType.grafana.alertingRule(rulerRule) && isPausedRule(rulerRule); + const isPaused = rulerRuleType.grafana.rule(rulerRule) && isPausedRule(rulerRule); const showError = hasError && !isPaused; const ruleOrigin = rulerRule ? getRulePluginOrigin(rulerRule) : getRulePluginOrigin(promRule); diff --git a/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.test.tsx b/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.test.tsx new file mode 100644 index 00000000000..ba354f056fd --- /dev/null +++ b/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.test.tsx @@ -0,0 +1,26 @@ +import { render, screen } from 'test/test-utils'; + +import { mockCombinedRule } from '../../../mocks'; +import { alertingFactory } from '../../../mocks/server/db'; +import { setupDataSources } from '../../../testSetup/datasources'; + +import { Details } from './Details'; + +beforeAll(() => { + setupDataSources(); +}); + +describe('render details tab', () => { + it('should show paused rule', () => { + const rule = mockCombinedRule({ + rulerRule: alertingFactory.ruler.grafana.recordingRule.build({ + grafana_alert: { + is_paused: true, + }, + }), + }); + + render(
); + expect(screen.getByText(/Alert evaluation currently paused/i)).toBeInTheDocument(); + }); +}); diff --git a/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx b/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx index 59d4d2d30d1..7e87437d407 100644 --- a/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx +++ b/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx @@ -74,7 +74,7 @@ export const Details = ({ rule }: DetailsProps) => { const hasEvaluationDuration = Number.isFinite(evaluationDuration); const updated = rulerRuleType.grafana.rule(rule.rulerRule) ? rule.rulerRule.grafana_alert.updated : undefined; - const isPaused = rulerRuleType.grafana.alertingRule(rule.rulerRule) && isPausedRule(rule.rulerRule); + const isPaused = rulerRuleType.grafana.rule(rule.rulerRule) && isPausedRule(rule.rulerRule); const pausedIcon = ( diff --git a/public/app/features/alerting/unified/components/rules/RulesTable.tsx b/public/app/features/alerting/unified/components/rules/RulesTable.tsx index b5a0aeabc62..38c390f8e00 100644 --- a/public/app/features/alerting/unified/components/rules/RulesTable.tsx +++ b/public/app/features/alerting/unified/components/rules/RulesTable.tsx @@ -353,7 +353,7 @@ function useRuleStatus(rule: CombinedRule) { const isDeleting = Boolean(hasRuler && rulerRulesLoaded && promRule && !rulerRule); const isCreating = Boolean(hasRuler && rulerRulesLoaded && rulerRule && !promRule); - const isPaused = rulerRuleType.grafana.alertingRule(rulerRule) && isPausedRule(rulerRule); + const isPaused = rulerRuleType.grafana.rule(rulerRule) && isPausedRule(rulerRule); return { isDeleting, isCreating, isPaused }; } diff --git a/public/app/features/alerting/unified/mocks/server/db.ts b/public/app/features/alerting/unified/mocks/server/db.ts index be2e261ba2f..14dac82f6cb 100644 --- a/public/app/features/alerting/unified/mocks/server/db.ts +++ b/public/app/features/alerting/unified/mocks/server/db.ts @@ -5,11 +5,13 @@ import { DataSourceInstanceSettings, PluginType } from '@grafana/data'; import { config } from '@grafana/runtime'; import { FolderDTO } from 'app/types'; import { + GrafanaRecordingRuleDefinition, PromAlertingRuleDTO, PromAlertingRuleState, PromRuleGroupDTO, PromRuleType, RulerAlertingRuleDTO, + RulerGrafanaRuleDTO, RulerRecordingRuleDTO, RulerRuleGroupDTO, } from 'app/types/unified-alerting-dto'; @@ -114,6 +116,25 @@ const grafanaFolderFactory = Factory.define(({ sequence }) => ({ updatedBy: '', })); +const grafanaRecordingRule = Factory.define>(({ sequence }) => ({ + grafana_alert: { + id: String(sequence), + uid: uniqueId(), + title: `Recording rule ${sequence}`, + namespace_uid: 'test-namespace', + rule_group: 'test-group', + condition: 'A', + data: [], + record: { + from: 'vector(1)', + metric: `recording_rule_${sequence}`, + }, + }, + for: '5m', + labels: { 'label-key-1': 'label-value-1' }, + annotations: {}, // @TODO recording rules don't have annotations, we need to fix this type definition +})); + export const alertingFactory = { folder: grafanaFolderFactory, prometheus: { @@ -124,6 +145,9 @@ export const alertingFactory = { group: rulerRuleGroupFactory, alertingRule: rulerAlertingRuleFactory, recordingRule: rulerRecordingRuleFactory, + grafana: { + recordingRule: grafanaRecordingRule, + }, }, dataSource: dataSourceFactory, };