From dc953c722b7cbf153308dd81669e92772eb85a6e Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Wed, 7 Jun 2023 21:33:34 +0200 Subject: [PATCH] [Security Solution] Add snooze rule tests (#158195) **Addresses:** https://github.com/elastic/kibana/issues/158196 ## Summary This PR mostly implements a test plan to cover rule snoozing functionality by automation tests. --- x-pack/plugins/alerting/common/index.ts | 7 +- .../alerting/server/routes/snooze_rule.ts | 4 +- .../bulk_duplicate_rules.cy.ts | 68 ++--- .../e2e/detection_rules/rule_snoozing.cy.ts | 278 ++++++++++++++++++ .../cypress/screens/common.ts | 8 + .../cypress/screens/rule_snoozing.ts | 20 ++ .../cypress/tasks/api_calls/rules.ts | 30 +- .../cypress/tasks/rule_snoozing.ts | 132 +++++++++ .../security_solution/cypress/urls/routes.ts | 11 + .../rule_snooze_badge/rule_snooze_badge.tsx | 13 +- 10 files changed, 519 insertions(+), 52 deletions(-) create mode 100644 x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_snoozing.cy.ts create mode 100644 x-pack/plugins/security_solution/cypress/screens/common.ts create mode 100644 x-pack/plugins/security_solution/cypress/screens/rule_snoozing.ts create mode 100644 x-pack/plugins/security_solution/cypress/tasks/rule_snoozing.ts create mode 100644 x-pack/plugins/security_solution/cypress/urls/routes.ts diff --git a/x-pack/plugins/alerting/common/index.ts b/x-pack/plugins/alerting/common/index.ts index a13e15b7d5615..ce9886a178371 100644 --- a/x-pack/plugins/alerting/common/index.ts +++ b/x-pack/plugins/alerting/common/index.ts @@ -61,8 +61,11 @@ export interface AlertingFrameworkHealth { export const LEGACY_BASE_ALERT_API_PATH = '/api/alerts'; export const BASE_ALERTING_API_PATH = '/api/alerting'; -export const INTERNAL_BASE_ALERTING_API_PATH = '/internal/alerting'; -export const INTERNAL_ALERTING_API_FIND_RULES_PATH = `${INTERNAL_BASE_ALERTING_API_PATH}/rules/_find`; +export const INTERNAL_BASE_ALERTING_API_PATH = '/internal/alerting' as const; +export const INTERNAL_ALERTING_SNOOZE_RULE = + `${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_snooze` as const; +export const INTERNAL_ALERTING_API_FIND_RULES_PATH = + `${INTERNAL_BASE_ALERTING_API_PATH}/rules/_find` as const; export const INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH = `${INTERNAL_BASE_ALERTING_API_PATH}/rules/maintenance_window` as const; diff --git a/x-pack/plugins/alerting/server/routes/snooze_rule.ts b/x-pack/plugins/alerting/server/routes/snooze_rule.ts index 17208ed9c01fa..1ffac168fcd00 100644 --- a/x-pack/plugins/alerting/server/routes/snooze_rule.ts +++ b/x-pack/plugins/alerting/server/routes/snooze_rule.ts @@ -10,7 +10,7 @@ import { schema } from '@kbn/config-schema'; import { ILicenseState, RuleMutedError } from '../lib'; import { verifyAccessAndContext, rRuleSchema } from './lib'; import { SnoozeOptions } from '../rules_client'; -import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../types'; +import { AlertingRequestHandlerContext, INTERNAL_ALERTING_SNOOZE_RULE } from '../types'; import { validateSnoozeSchedule } from '../lib/validate_snooze_schedule'; const paramSchema = schema.object({ @@ -42,7 +42,7 @@ export const snoozeRuleRoute = ( ) => { router.post( { - path: `${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_snooze`, + path: INTERNAL_ALERTING_SNOOZE_RULE, validate: { params: paramSchema, body: bodySchema, diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/bulk_duplicate_rules.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/bulk_duplicate_rules.cy.ts index 038a6c6d32853..d906838996c18 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/bulk_duplicate_rules.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/bulk_duplicate_rules.cy.ts @@ -61,40 +61,40 @@ describe('Detection rules, bulk duplicate', () => { resetRulesTableState(); deleteAlertsAndRules(); esArchiverResetKibana(); - createRule<{ id: string }>( - getNewRule({ name: RULE_NAME, ...defaultRuleData, rule_id: '1' }) - ).then((response) => { - createRuleExceptionItem(response.body.id, [ - { - description: 'Exception item for rule default exception list', - entries: [ - { - field: 'user.name', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - name: EXPIRED_EXCEPTION_ITEM_NAME, - type: 'simple', - expire_time: expiredDate, - }, - { - description: 'Exception item for rule default exception list', - entries: [ - { - field: 'user.name', - operator: 'included', - type: 'match', - value: 'some value', - }, - ], - name: NON_EXPIRED_EXCEPTION_ITEM_NAME, - type: 'simple', - expire_time: futureDate, - }, - ]); - }); + createRule(getNewRule({ name: RULE_NAME, ...defaultRuleData, rule_id: '1' })).then( + (response) => { + createRuleExceptionItem(response.body.id, [ + { + description: 'Exception item for rule default exception list', + entries: [ + { + field: 'user.name', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + name: EXPIRED_EXCEPTION_ITEM_NAME, + type: 'simple', + expire_time: expiredDate, + }, + { + description: 'Exception item for rule default exception list', + entries: [ + { + field: 'user.name', + operator: 'included', + type: 'match', + value: 'some value', + }, + ], + name: NON_EXPIRED_EXCEPTION_ITEM_NAME, + type: 'simple', + expire_time: futureDate, + }, + ]); + } + ); visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_snoozing.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_snoozing.cy.ts new file mode 100644 index 0000000000000..f2015a1b4ecb9 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_snoozing.cy.ts @@ -0,0 +1,278 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { INTERNAL_ALERTING_API_FIND_RULES_PATH } from '@kbn/alerting-plugin/common'; +import type { RuleResponse } from '../../../common/detection_engine/rule_schema'; +import { createRule, snoozeRule as snoozeRuleViaAPI } from '../../tasks/api_calls/rules'; +import { cleanKibana, deleteAlertsAndRules, deleteConnectors } from '../../tasks/common'; +import { login, visitWithoutDateRange } from '../../tasks/login'; +import { getNewRule } from '../../objects/rule'; +import { ruleDetailsUrl, ruleEditUrl, SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation'; +import { internalAlertingSnoozeRule } from '../../urls/routes'; +import { RULES_MANAGEMENT_TABLE, RULE_NAME } from '../../screens/alerts_detection_rules'; +import { + expectRuleSnoozed, + expectRuleSnoozedInTable, + expectRuleUnsnoozed, + expectRuleUnsnoozedInTable, + expectSnoozeErrorToast, + expectSnoozeSuccessToast, + expectUnsnoozeSuccessToast, + snoozeRule, + snoozeRuleInTable, + unsnoozeRuleInTable, +} from '../../tasks/rule_snoozing'; +import { createSlackConnector } from '../../tasks/api_calls/connectors'; +import { duplicateFirstRule, importRules } from '../../tasks/alerts_detection_rules'; +import { goToActionsStepTab } from '../../tasks/create_new_rule'; +import { goToRuleEditSettings } from '../../tasks/rule_details'; +import { actionFormSelector } from '../../screens/common/rule_actions'; +import { RULE_INDICES } from '../../screens/create_new_rule'; +import { addEmailConnectorAndRuleAction } from '../../tasks/common/rule_actions'; +import { saveEditedRule } from '../../tasks/edit_rule'; +import { DISABLED_SNOOZE_BADGE } from '../../screens/rule_snoozing'; +import { TOOLTIP } from '../../screens/common'; + +const RULES_TO_IMPORT_FILENAME = 'cypress/fixtures/7_16_rules.ndjson'; + +describe('rule snoozing', () => { + before(() => { + cleanKibana(); + }); + + beforeEach(() => { + login(); + deleteAlertsAndRules(); + }); + + it('ensures the rule is snoozed on the rules management page, rule details page and rule editing page', () => { + createRule(getNewRule({ name: 'Test on all pages' })); + + visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL); + + snoozeRuleInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Test on all pages', + duration: '1 hours', + }); + + // Open rule detail page + cy.get(RULE_NAME).contains('Test on all pages').click(); + + expectRuleSnoozed('1 hours'); + + // Open rule editing page actions tab + goToRuleEditSettings(); + goToActionsStepTab(); + + expectRuleSnoozed('1 hours'); + }); + + describe('Rules management table', () => { + it('snoozes a rule without actions for 3 hours', () => { + createRule(getNewRule({ name: 'Test rule without actions' })); + + visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL); + + snoozeRuleInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Test rule without actions', + duration: '3 hours', + }); + + expectSnoozeSuccessToast(); + expectRuleSnoozedInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Test rule without actions', + duration: '3 hours', + }); + }); + + it('snoozes a rule with actions for 2 days', () => { + createRuleWithActions({ name: 'Test rule with actions' }, createRule); + + visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL); + + snoozeRuleInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Test rule with actions', + duration: '2 days', + }); + + expectSnoozeSuccessToast(); + expectRuleSnoozedInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Test rule with actions', + duration: '2 days', + }); + }); + + it('unsnoozes a rule with actions', () => { + createSnoozedRule(getNewRule({ name: 'Snoozed rule' })); + + visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL); + + unsnoozeRuleInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Snoozed rule', + }); + + expectUnsnoozeSuccessToast(); + expectRuleUnsnoozedInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Snoozed rule', + }); + }); + + it('ensures snooze settings persist after page reload', () => { + createRule(getNewRule({ name: 'Test persistence' })); + + visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL); + + snoozeRuleInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Test persistence', + duration: '3 days', + }); + + cy.reload(); + + expectRuleSnoozedInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Test persistence', + duration: '3 days', + }); + }); + + it('ensures a duplicated rule is not snoozed', () => { + createRule(getNewRule({ name: 'Test rule' })); + + visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL); + + duplicateFirstRule(); + + // Make sure rules table is shown as it navigates to rule editing page after successful duplication + visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL); + + expectRuleUnsnoozedInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Test rule', + }); + }); + }); + + describe('Rule editing page / actions tab', () => { + beforeEach(() => { + deleteConnectors(); + }); + + it('adds an action to a snoozed rule', () => { + createSnoozedRule(getNewRule({ name: 'Snoozed rule' })).then(({ body: rule }) => { + visitWithoutDateRange(ruleEditUrl(rule.id)); + // Wait for rule data being loaded + cy.get(RULE_INDICES).should('be.visible'); + goToActionsStepTab(); + + addEmailConnectorAndRuleAction('abc@example.com', 'Test action'); + saveEditedRule(); + + goToRuleEditSettings(); + goToActionsStepTab(); + + cy.get(actionFormSelector(0)).should('be.visible'); + }); + }); + }); + + describe('importing rules', () => { + beforeEach(() => { + cy.intercept('POST', '/api/detection_engine/rules/_import*').as('import'); + }); + + it('ensures imported rules are unsnoozed', () => { + visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL); + + importRules(RULES_TO_IMPORT_FILENAME); + + cy.wait('@import').then(({ response }) => { + cy.wrap(response?.statusCode).should('eql', 200); + + expectRuleUnsnoozedInTable({ + tableSelector: RULES_MANAGEMENT_TABLE, + ruleName: 'Test Custom Rule', + }); + }); + }); + }); + + describe('Handling errors', () => { + it('shows an error if unable to load snooze settings', () => { + createRule(getNewRule({ name: 'Test rule' })).then(({ body: rule }) => { + cy.intercept('GET', `${INTERNAL_ALERTING_API_FIND_RULES_PATH}*`, { + statusCode: 500, + }); + + visitWithoutDateRange(ruleDetailsUrl(rule.id)); + }); + + cy.get(DISABLED_SNOOZE_BADGE).trigger('mouseover'); + + cy.get(TOOLTIP).contains('Unable to fetch snooze settings'); + }); + + it('shows an error if unable to save snooze settings', () => { + createRule(getNewRule({ name: 'Test rule' })).then(({ body: rule }) => { + cy.intercept('POST', internalAlertingSnoozeRule(rule.id), { forceNetworkError: true }); + + visitWithoutDateRange(ruleDetailsUrl(rule.id)); + }); + + snoozeRule('3 days'); + + expectSnoozeErrorToast(); + expectRuleUnsnoozed(); + }); + }); +}); + +function createRuleWithActions( + ruleParams: Parameters[0], + ruleCreator: ( + ruleParams: Parameters[0] + ) => Cypress.Chainable> +): Cypress.Chainable> { + return createSlackConnector().then(({ body }) => + ruleCreator( + getNewRule({ + ...ruleParams, + actions: [ + { + id: body.id, + action_type_id: '.slack', + group: 'default', + params: { + message: 'Some message', + }, + }, + ], + }) + ) + ); +} + +function createSnoozedRule( + ruleParams: Parameters[0] +): Cypress.Chainable> { + return createRule(ruleParams).then((response) => { + const createdRule = response.body; + const oneDayInMs = 24 * 60 * 60 * 1000; + + snoozeRuleViaAPI(createdRule.id, oneDayInMs); + + return cy.wrap(response); + }); +} diff --git a/x-pack/plugins/security_solution/cypress/screens/common.ts b/x-pack/plugins/security_solution/cypress/screens/common.ts new file mode 100644 index 0000000000000..8dc5517aae3c5 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/screens/common.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const TOOLTIP = '[role="tooltip"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/rule_snoozing.ts b/x-pack/plugins/security_solution/cypress/screens/rule_snoozing.ts new file mode 100644 index 0000000000000..675807d81df37 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/screens/rule_snoozing.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const UNSNOOZED_BADGE = '[data-test-subj="rulesListNotifyBadge-unsnoozed"]'; + +export const SNOOZED_BADGE = '[data-test-subj="rulesListNotifyBadge-snoozed"]'; + +export const DISABLED_SNOOZE_BADGE = '[data-test-subj="rulesListNotifyBadge"]'; + +export const SNOOZE_POPOVER_INTERVAL_VALUE_INPUT = '[data-test-subj="ruleSnoozeIntervalValue"]'; + +export const SNOOZE_POPOVER_INTERVAL_UNIT_INPUT = '[data-test-subj="ruleSnoozeIntervalUnit"]'; + +export const SNOOZE_POPOVER_APPLY_BUTTON = '[data-test-subj="ruleSnoozeApply"]'; + +export const SNOOZE_POPOVER_CANCEL_BUTTON = '[data-test-subj="ruleSnoozeCancel"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts b/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts index 83fba358550c4..5d5de9b7f146a 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts @@ -5,12 +5,16 @@ * 2.0. */ +import moment from 'moment'; import { rootRequest } from '../common'; import { DETECTION_ENGINE_RULES_URL } from '../../../common/constants'; -import type { RuleCreateProps } from '../../../common/detection_engine/rule_schema'; +import type { RuleCreateProps, RuleResponse } from '../../../common/detection_engine/rule_schema'; +import { internalAlertingSnoozeRule } from '../../urls/routes'; -export const createRule = (rule: RuleCreateProps) => { - return rootRequest({ +export const createRule = ( + rule: RuleCreateProps +): Cypress.Chainable> => { + return rootRequest({ method: 'POST', url: DETECTION_ENGINE_RULES_URL, body: rule, @@ -19,6 +23,26 @@ export const createRule = (rule: RuleCreateProps) => { }); }; +/** + * Snoozes a rule via API + * + * @param id Rule's SO id + * @param duration Snooze duration in milliseconds, -1 for indefinite + */ +export const snoozeRule = (id: string, duration: number): Cypress.Chainable => + cy.request({ + method: 'POST', + url: internalAlertingSnoozeRule(id), + body: { + snooze_schedule: { + duration, + rRule: { dtstart: new Date().toISOString(), count: 1, tzid: moment().format('zz') }, + }, + }, + headers: { 'kbn-xsrf': 'cypress-creds' }, + failOnStatusCode: false, + }); + export const deleteCustomRule = (ruleId = '1') => { rootRequest({ method: 'DELETE', diff --git a/x-pack/plugins/security_solution/cypress/tasks/rule_snoozing.ts b/x-pack/plugins/security_solution/cypress/tasks/rule_snoozing.ts new file mode 100644 index 0000000000000..35b98d9404591 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/tasks/rule_snoozing.ts @@ -0,0 +1,132 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import moment from 'moment'; +import { RULE_NAME, TOASTER } from '../screens/alerts_detection_rules'; +import { + SNOOZED_BADGE, + SNOOZE_POPOVER_APPLY_BUTTON, + SNOOZE_POPOVER_CANCEL_BUTTON, + SNOOZE_POPOVER_INTERVAL_UNIT_INPUT, + SNOOZE_POPOVER_INTERVAL_VALUE_INPUT, + UNSNOOZED_BADGE, +} from '../screens/rule_snoozing'; + +type SnoozeUnits = 'minutes' | 'hours' | 'days' | 'weeks' | 'months'; +type SnoozeDuration = `${number} ${SnoozeUnits}`; + +interface SnoozeParams { + duration: SnoozeDuration; +} + +interface TableRule { + tableSelector: string; + ruleName: string; +} + +type SnoozeInTableParams = TableRule & SnoozeParams; + +export function snoozeRule(duration: SnoozeDuration): void { + openSnoozePopover(); + snoozeRuleInOpenPopover(duration); +} + +export function expectSnoozeSuccessToast(): void { + cy.get(TOASTER).should('contain', 'Rule successfully snoozed'); +} + +export function expectSnoozeErrorToast(): void { + cy.get(TOASTER).should('contain', 'Unable to change rule snooze settings'); +} + +export function expectRuleSnoozed(duration: SnoozeDuration): void { + cy.get(SNOOZED_BADGE).contains(expectedSnoozeBadgeText(duration)); +} + +export function snoozeRuleInTable({ + tableSelector, + ruleName, + duration, +}: SnoozeInTableParams): void { + openSnoozePopoverInTable(tableSelector, ruleName); + snoozeRuleInOpenPopover(duration); +} + +export function expectRuleSnoozedInTable({ + tableSelector, + ruleName, + duration, +}: SnoozeInTableParams): void { + findRuleRowInTable(tableSelector, ruleName) + .find(SNOOZED_BADGE) + .contains(expectedSnoozeBadgeText(duration)); +} + +export function unsnoozeRule(): void { + cy.get(SNOOZED_BADGE).click(); + cy.get(SNOOZE_POPOVER_CANCEL_BUTTON).click(); +} + +export function expectUnsnoozeSuccessToast(): void { + cy.get(TOASTER).should('contain', 'Rule successfully unsnoozed'); +} + +export function expectRuleUnsnoozed(): void { + cy.get(UNSNOOZED_BADGE); +} + +export function unsnoozeRuleInTable({ tableSelector, ruleName }: TableRule): void { + findRuleRowInTable(tableSelector, ruleName).find(SNOOZED_BADGE).click(); + cy.get(SNOOZE_POPOVER_CANCEL_BUTTON).click(); +} + +export function expectRuleUnsnoozedInTable({ tableSelector, ruleName }: TableRule): void { + findRuleRowInTable(tableSelector, ruleName).find(UNSNOOZED_BADGE).should('exist'); +} + +export function findRuleRowInTable( + tableSelector: string, + ruleName: string +): Cypress.Chainable> { + return cy.get(tableSelector).find(RULE_NAME).contains(ruleName).parents('tr'); +} + +/** + * Opens a snooze popover by clicking the snooze badge. Fits to pages with one snooze icon per page. + */ +function openSnoozePopover(): void { + cy.get(UNSNOOZED_BADGE).click(); +} + +/** + * Opens a snooze popover by clicking the snooze badge in the table's row + */ +function openSnoozePopoverInTable(tableSelector: string, ruleName: string): void { + const parent = findRuleRowInTable(tableSelector, ruleName); + + parent.find(UNSNOOZED_BADGE).click(); +} + +/** + * Snoozes a rule in an open snooze popover + */ +function snoozeRuleInOpenPopover(duration: SnoozeDuration): void { + const [value, units] = duration.split(' '); + + cy.log(`Snooze a rule for ${value} ${units}`); + + cy.get(SNOOZE_POPOVER_INTERVAL_VALUE_INPUT).clear(); + cy.get(SNOOZE_POPOVER_INTERVAL_VALUE_INPUT).type(value.toString()); + cy.get(SNOOZE_POPOVER_INTERVAL_UNIT_INPUT).select(units); + cy.get(SNOOZE_POPOVER_APPLY_BUTTON).click(); +} + +function expectedSnoozeBadgeText(duration: SnoozeDuration): string { + return moment() + .add(...duration.split(' ')) + .format('MMM D'); +} diff --git a/x-pack/plugins/security_solution/cypress/urls/routes.ts b/x-pack/plugins/security_solution/cypress/urls/routes.ts new file mode 100644 index 0000000000000..63d120d3d8bae --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/urls/routes.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { INTERNAL_ALERTING_SNOOZE_RULE } from '@kbn/alerting-plugin/common'; + +export const internalAlertingSnoozeRule = (ruleId: string) => + INTERNAL_ALERTING_SNOOZE_RULE.replace('{id}', ruleId); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_snooze_badge/rule_snooze_badge.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_snooze_badge/rule_snooze_badge.tsx index 8808f6d3033b5..f4aefc5be5a5a 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_snooze_badge/rule_snooze_badge.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_snooze_badge/rule_snooze_badge.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import React from 'react'; import type { RuleObjectId } from '../../../../../common/detection_engine/rule_schema'; import { useUserData } from '../../../../detections/components/user_info'; @@ -32,20 +31,12 @@ export function RuleSnoozeBadge({ const hasCRUDPermissions = hasUserCRUDPermission(canUserCRUD); const invalidateFetchRuleSnoozeSettings = useInvalidateFetchRulesSnoozeSettingsQuery(); - if (error) { - return ( - - - - ); - } - return (