mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[AO][BUG] Disable view rule details when the rule is deleted (#163183)
## Summary
Fixes #163084
<img width="1397" alt="Screenshot 2023-08-04 at 17 33 34"
src="8075da4d
-633d-4916-b6db-491f7c87c363">
### Release note
Disable the "View rule details" option from the Alert Details' Actions
list when the rule is deleted.
This commit is contained in:
parent
69579014a3
commit
03303940f2
7 changed files with 77 additions and 60 deletions
|
@ -61,12 +61,10 @@ export function useFetchRule({ ruleId }: { ruleId?: string }): UseFetchRuleRespo
|
|||
onError: (error: Error) => {
|
||||
toasts.addError(error, {
|
||||
title: i18n.translate('xpack.observability.ruleDetails.ruleLoadError', {
|
||||
defaultMessage: 'Unable to load rule. Reason: {message}',
|
||||
values: {
|
||||
message:
|
||||
error instanceof Error ? error.message : typeof error === 'string' ? error : '',
|
||||
},
|
||||
defaultMessage: 'Unable to load rule',
|
||||
}),
|
||||
toastMessage:
|
||||
error instanceof Error ? error.message : typeof error === 'string' ? error : '',
|
||||
});
|
||||
},
|
||||
}
|
||||
|
|
|
@ -65,13 +65,11 @@ export function useFetchRuleTypes({
|
|||
refetchOnWindowFocus: false,
|
||||
onError: (error: Error) => {
|
||||
toasts.addError(error, {
|
||||
title: i18n.translate('xpack.observability.ruleDetails.ruleLoadError', {
|
||||
defaultMessage: 'Unable to load rule. Reason: {message}',
|
||||
values: {
|
||||
message:
|
||||
error instanceof Error ? error.message : typeof error === 'string' ? error : '',
|
||||
},
|
||||
title: i18n.translate('xpack.observability.ruleDetails.ruleTypeLoadError', {
|
||||
defaultMessage: 'Unable to load rule type.',
|
||||
}),
|
||||
toastMessage:
|
||||
error instanceof Error ? error.message : typeof error === 'string' ? error : '',
|
||||
});
|
||||
},
|
||||
}
|
||||
|
|
|
@ -14,13 +14,16 @@ import { render } from '../../../utils/test_helper';
|
|||
import { useKibana } from '../../../utils/kibana_react';
|
||||
import { kibanaStartMock } from '../../../utils/kibana_react.mock';
|
||||
import { alertWithTags, mockAlertUuid } from '../mock/alert';
|
||||
import { useFetchRule } from '../../../hooks/use_fetch_rule';
|
||||
|
||||
import { HeaderActions } from './header_actions';
|
||||
import { CasesUiStart } from '@kbn/cases-plugin/public';
|
||||
|
||||
jest.mock('../../../utils/kibana_react');
|
||||
jest.mock('../../../hooks/use_fetch_rule');
|
||||
|
||||
const useKibanaMock = useKibana as jest.Mock;
|
||||
const useFetchRuleMock = useFetchRule as jest.Mock;
|
||||
const mockCases = casesPluginMock.createStartContract();
|
||||
|
||||
const mockKibana = () => {
|
||||
|
@ -33,61 +36,82 @@ const mockKibana = () => {
|
|||
});
|
||||
};
|
||||
|
||||
const ruleId = '123';
|
||||
const ruleName = '456';
|
||||
const mockRuleId = '123';
|
||||
const mockRuleName = '456';
|
||||
|
||||
jest.mock('../../../hooks/use_fetch_rule', () => {
|
||||
return {
|
||||
useFetchRule: () => ({
|
||||
reloadRule: jest.fn(),
|
||||
rule: {
|
||||
id: ruleId,
|
||||
name: ruleName,
|
||||
},
|
||||
}),
|
||||
};
|
||||
});
|
||||
const mockUseFetchRuleWithData = () => {
|
||||
useFetchRuleMock.mockReturnValue({
|
||||
reloadRule: jest.fn(),
|
||||
rule: {
|
||||
id: mockRuleId,
|
||||
name: mockRuleName,
|
||||
},
|
||||
});
|
||||
};
|
||||
const mockUseFetchRuleWithoutData = () => {
|
||||
useFetchRuleMock.mockReturnValue({
|
||||
reloadRule: jest.fn(),
|
||||
rule: null,
|
||||
});
|
||||
};
|
||||
|
||||
describe('Header Actions', () => {
|
||||
beforeEach(() => {
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks();
|
||||
mockKibana();
|
||||
});
|
||||
|
||||
it('should display an actions button', () => {
|
||||
const { queryByTestId } = render(<HeaderActions alert={alertWithTags} />);
|
||||
expect(queryByTestId('alert-details-header-actions-menu-button')).toBeTruthy();
|
||||
});
|
||||
describe('Header Actions - Enabled', () => {
|
||||
beforeEach(() => {
|
||||
mockKibana();
|
||||
mockUseFetchRuleWithData();
|
||||
});
|
||||
|
||||
describe('when clicking the actions button', () => {
|
||||
it('should offer an "add to case" button which opens the add to case modal', async () => {
|
||||
let attachments: any[] = [];
|
||||
it('should display an actions button', () => {
|
||||
const { queryByTestId } = render(<HeaderActions alert={alertWithTags} />);
|
||||
expect(queryByTestId('alert-details-header-actions-menu-button')).toBeTruthy();
|
||||
});
|
||||
|
||||
const useCasesAddToExistingCaseModalMock: any = jest.fn().mockImplementation(() => ({
|
||||
open: ({ getAttachments }: { getAttachments: () => any[] }) => {
|
||||
attachments = getAttachments();
|
||||
},
|
||||
})) as CasesUiStart['hooks']['useCasesAddToExistingCaseModal'];
|
||||
describe('when clicking the actions button', () => {
|
||||
it('should offer an "add to case" button which opens the add to case modal', async () => {
|
||||
let attachments: any[] = [];
|
||||
|
||||
mockCases.hooks.useCasesAddToExistingCaseModal = useCasesAddToExistingCaseModalMock;
|
||||
|
||||
const { getByTestId, findByRole } = render(<HeaderActions alert={alertWithTags} />);
|
||||
|
||||
fireEvent.click(await findByRole('button', { name: 'Actions' }));
|
||||
|
||||
fireEvent.click(getByTestId('add-to-case-button'));
|
||||
|
||||
expect(attachments).toEqual([
|
||||
{
|
||||
alertId: mockAlertUuid,
|
||||
index: '.internal.alerts-observability.metrics.alerts-*',
|
||||
rule: {
|
||||
id: ruleId,
|
||||
name: ruleName,
|
||||
const useCasesAddToExistingCaseModalMock: any = jest.fn().mockImplementation(() => ({
|
||||
open: ({ getAttachments }: { getAttachments: () => any[] }) => {
|
||||
attachments = getAttachments();
|
||||
},
|
||||
type: 'alert',
|
||||
},
|
||||
]);
|
||||
})) as CasesUiStart['hooks']['useCasesAddToExistingCaseModal'];
|
||||
|
||||
mockCases.hooks.useCasesAddToExistingCaseModal = useCasesAddToExistingCaseModalMock;
|
||||
|
||||
const { getByTestId, findByRole } = render(<HeaderActions alert={alertWithTags} />);
|
||||
|
||||
fireEvent.click(await findByRole('button', { name: 'Actions' }));
|
||||
|
||||
fireEvent.click(getByTestId('add-to-case-button'));
|
||||
|
||||
expect(attachments).toEqual([
|
||||
{
|
||||
alertId: mockAlertUuid,
|
||||
index: '.internal.alerts-observability.metrics.alerts-*',
|
||||
rule: {
|
||||
id: mockRuleId,
|
||||
name: mockRuleName,
|
||||
},
|
||||
type: 'alert',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('Header Actions - Disabled', () => {
|
||||
beforeEach(() => {
|
||||
mockKibana();
|
||||
mockUseFetchRuleWithoutData();
|
||||
});
|
||||
it("should disable the 'View rule details' when the rule is not available/delete", async () => {
|
||||
const { queryByTestId, findByRole } = render(<HeaderActions alert={alertWithTags} />);
|
||||
fireEvent.click(await findByRole('button', { name: 'Actions' }));
|
||||
expect(queryByTestId('view-rule-details-button')).toHaveAttribute('disabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -95,7 +95,7 @@ export function HeaderActions({ alert }: HeaderActionsProps) {
|
|||
<EuiButtonEmpty
|
||||
size="s"
|
||||
color="text"
|
||||
disabled={!alert?.fields[ALERT_RULE_UUID]}
|
||||
disabled={!alert?.fields[ALERT_RULE_UUID] || !rule}
|
||||
onClick={handleViewRuleDetails}
|
||||
data-test-subj="view-rule-details-button"
|
||||
>
|
||||
|
|
|
@ -27279,7 +27279,6 @@
|
|||
"xpack.observability.enableInfrastructureHostsViewDescription": "{betaLabel} Activez la vue \"Hôtes\" dans l’application \"Infrastructure\".",
|
||||
"xpack.observability.inspector.stats.queryTimeValue": "{queryTime} ms",
|
||||
"xpack.observability.pages.alertDetails.pageTitle.title": "{ruleCategory} {ruleCategory, select, Anomaly {détecté} Inventory {seuil dépassé} other {dépassé}}",
|
||||
"xpack.observability.ruleDetails.ruleLoadError": "Impossible de charger la règle. Raison : {message}",
|
||||
"xpack.observability.slo.alerting.burnRate.reason": "{actionGroupName} : Le taux d'avancement pour le (les) dernier(s) {longWindowDuration} est de {longWindowBurnRate} et pour le (les) dernier(s) {shortWindowDuration} est de {shortWindowBurnRate}. Alerter si supérieur à {burnRateThreshold} pour les deux fenêtres",
|
||||
"xpack.observability.slo.burnRateWindow.thresholdTip": "Le seuil est {target}x",
|
||||
"xpack.observability.slo.clone.errorNotification": "Échec du clonage de {name}",
|
||||
|
|
|
@ -27279,7 +27279,6 @@
|
|||
"xpack.observability.enableInfrastructureHostsViewDescription": "{betaLabel}インフラアプリでホストビューを有効にします。",
|
||||
"xpack.observability.inspector.stats.queryTimeValue": "{queryTime}ms",
|
||||
"xpack.observability.pages.alertDetails.pageTitle.title": "{ruleCategory} {ruleCategory, select, Anomaly {が検出されました} Inventory {しきい値を超えました} other {を超えました}}",
|
||||
"xpack.observability.ruleDetails.ruleLoadError": "ルールを読み込めません。理由:{message}",
|
||||
"xpack.observability.slo.alerting.burnRate.reason": "{actionGroupName}:過去{longWindowDuration}のバーンレートは{longWindowBurnRate}で、過去{shortWindowDuration}のバーンレートは{shortWindowBurnRate}です。両期間とも{burnRateThreshold}を超えたらアラート",
|
||||
"xpack.observability.slo.burnRateWindow.thresholdTip": "しきい値は{target}xです",
|
||||
"xpack.observability.slo.clone.errorNotification": "{name}を複製できませんでした",
|
||||
|
|
|
@ -27277,7 +27277,6 @@
|
|||
"xpack.observability.enableInfrastructureHostsViewDescription": "{betaLabel} 在 Infrastructure 应用中启用主机视图。",
|
||||
"xpack.observability.inspector.stats.queryTimeValue": "{queryTime}ms",
|
||||
"xpack.observability.pages.alertDetails.pageTitle.title": "{ruleCategory} {ruleCategory, select, Anomaly {已检测到} Inventory {超出阈值} other {超出}}",
|
||||
"xpack.observability.ruleDetails.ruleLoadError": "无法加载规则。原因:{message}",
|
||||
"xpack.observability.slo.alerting.burnRate.reason": "{actionGroupName}:过去 {longWindowDuration} 的消耗速度为 {longWindowBurnRate} 且过去 {shortWindowDuration} 为 {shortWindowBurnRate}。两个窗口超出 {burnRateThreshold} 时告警",
|
||||
"xpack.observability.slo.burnRateWindow.thresholdTip": "阈值为 {target}x",
|
||||
"xpack.observability.slo.clone.errorNotification": "无法克隆 {name}",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue