From 79c3fae5d1a586f7d30620d6c5dde0299d736aa9 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Thu, 7 Sep 2023 22:11:53 +0200 Subject: [PATCH] [Security Solution] Get rid of `goToRuleDetails()` in favor of `goToRuleDetailsOf()` (#165011) **Addresses:** https://github.com/elastic/kibana/issues/164513 ## Summary This PR gets rid of Rules Management `goToRuleDetails()` Cypress helper replacing it with `goToRuleDetailsOf()`. ## Details The following has been done - `goToRuleDetails()` replaced with `goToRuleDetailsOf()` where it makes sense (rule creation, scenarios validating something on the rules management table and then on the rule details page and etc). - For quite a number of tests expectations are done on the rule details page but it's opened via rules management table page. In fact this unnecessary step may be flaky as rules table has auto resfresh feature and it should be ideally disabled as well as this requires loading of lazy UI resources and increases test's execution time. It can be avoided by directly opening the details page via ```ts createRule(getNewRule()).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id)) ); ``` `goToRuleDetails()` was removed from such tests in favor of opening the rule details page directly. ## Does opening rule detail page directly make the tests less stable? Yes, it can give such side effect but it will help to either find and fix some bugs in our code or make our tests more robust by adding an universal page ready expectation. While working on this PR I had to fix a few problems on the rule details page caused by getting rid of unnecessary opening rule details page via rules management table but it fact it revealed rule details page's problems - If a test needs first thing to enable a rule like editing test for custom query rule the test may fail as `-1` is sent as rule id. In fact it's a page loading problem. Rule switch become available while the rule isn't loaded yet and it can be easily reproduced in prod if the connection is slow. Disabling rule switch while rule isn't loaded yet solves the problem. - Rule exceptions tests turned to be flaky. Edit exception list item context menu closes on its own sometimes. In fact `useEffect` causing HTTP request fired much more often than it should due to exception list types defined in place and regenerated each render causing the list item to be in loading state while the request is in progress. It was fixed by moving the arrays to stable constants. ## Flaky test runner [Security Solution Cypress tests (150 runs)](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/3017) (there is no indication of negative impact) --- .../pages/rule_details/index.tsx | 15 +- ...ts_detection_callouts_index_outdated.cy.ts | 24 +- .../detection_alerts/cti_enrichments.cy.ts | 16 +- .../missing_privileges_callout.cy.ts | 17 +- .../rule_actions/rule_actions.cy.ts | 7 +- .../rule_creation/custom_query_rule.cy.ts | 200 +++++++------- .../custom_query_rule_data_view.cy.ts | 6 +- .../custom_saved_query_rule.cy.ts | 99 ++++--- .../event_correlation_rule.cy.ts | 10 +- .../rule_creation/indicator_match_rule.cy.ts | 93 ++++--- .../rule_creation/machine_learning_rule.cy.ts | 4 +- .../rule_creation/new_terms_rule.cy.ts | 4 +- .../rule_creation/override.cy.ts | 4 +- .../rule_creation/threshold_rule.cy.ts | 4 +- .../bulk_actions/bulk_duplicate_rules.cy.ts | 6 +- .../bulk_actions/bulk_edit_rules.cy.ts | 18 +- .../bulk_edit_rules_data_view.cy.ts | 152 ++++++----- .../rules_table_persistent_state.cy.ts | 4 +- .../value_lists/value_lists.cy.ts | 71 ++--- .../endpoint_exceptions.cy.ts | 11 +- .../auto_populate_with_alert_data.cy.ts | 10 +- .../closing_all_matching_alerts.cy.ts | 22 +- .../exceptions/entry/flyout_validation.cy.ts | 20 +- .../entry/multiple_conditions.cy.ts | 16 +- .../e2e/exceptions/entry/use_value_list.cy.ts | 62 ++--- .../add_edit_endpoint_exception.cy.ts | 257 ++++++++++-------- .../add_edit_exception.cy.ts | 57 ++-- .../add_edit_exception_data_view.cy.ts | 9 +- .../rule_details_flow/read_only_view.cy.ts | 4 +- .../manage_exceptions.cy.ts | 24 +- .../alerts/alerts_details.cy.ts | 19 +- .../alerts/building_block_alerts.cy.ts | 19 +- .../cypress/objects/rule.ts | 2 - .../cypress/tasks/alerts_detection_rules.ts | 16 +- .../cypress/tasks/api_calls/exceptions.ts | 18 +- .../cypress/tasks/lists.ts | 6 + .../cypress/tasks/rule_details.ts | 4 +- .../cypress/tsconfig.json | 19 +- .../cypress/urls/navigation.ts | 5 +- 39 files changed, 694 insertions(+), 660 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx index 44e41f0f9ebd3..674d29b128413 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx @@ -144,6 +144,13 @@ import { useBoolState } from '../../../../common/hooks/use_bool_state'; import { useLegacyUrlRedirect } from './use_redirect_legacy_url'; import { RuleDetailTabs, useRuleDetailsTabs } from './use_rule_details_tabs'; +const RULE_EXCEPTION_LIST_TYPES = [ + ExceptionListTypeEnum.DETECTION, + ExceptionListTypeEnum.RULE_DEFAULT, +]; + +const RULE_ENDPOINT_EXCEPTION_LIST_TYPE = [ExceptionListTypeEnum.ENDPOINT]; + /** * Need a 100% height here to account for the graph/analyze tool, which sets no explicit height parameters, but fills the available space. */ @@ -603,6 +610,7 @@ const RuleDetailsPageComponent: React.FC = ({ = ({ = ({ > { beforeEach(() => { - createRule(getNewRule({ rule_id: 'rule_testing' })); - loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL); - waitForPageTitleToBeShown(); - goToRuleDetails(); + createRule(getNewRule({ rule_id: 'rule_testing' })).then((rule) => + loadPageAsPlatformEngineerUser(ruleDetailsUrl(rule.body.id)) + ); }); afterEach(() => { @@ -130,10 +128,9 @@ describe( context('On Rule Details page', () => { beforeEach(() => { - createRule(getNewRule({ rule_id: 'rule_testing' })); - loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL); - waitForPageTitleToBeShown(); - goToRuleDetails(); + createRule(getNewRule({ rule_id: 'rule_testing' })).then((rule) => + loadPageAsPlatformEngineerUser(ruleDetailsUrl(rule.body.id)) + ); }); afterEach(() => { @@ -180,10 +177,9 @@ describe( context('On Rule Details page', () => { beforeEach(() => { - createRule(getNewRule({ rule_id: 'rule_testing' })); - loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL); - waitForPageTitleToBeShown(); - goToRuleDetails(); + createRule(getNewRule({ rule_id: 'rule_testing' })).then((rule) => + loadPageAsPlatformEngineerUser(ruleDetailsUrl(rule.body.id)) + ); }); afterEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/cti_enrichments.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/cti_enrichments.cy.ts index 2057a7db3363f..9ab88f2802be8 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/cti_enrichments.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/cti_enrichments.cy.ts @@ -20,12 +20,11 @@ import { THREAT_DETAILS_ACCORDION, } from '../../screens/alerts_details'; import { TIMELINE_FIELD } from '../../screens/rule_details'; -import { goToRuleDetails } from '../../tasks/alerts_detection_rules'; import { expandFirstAlert, setEnrichmentDates, viewThreatIntelTab } from '../../tasks/alerts'; import { createRule } from '../../tasks/api_calls/rules'; import { openJsonView, openThreatIndicatorDetails } from '../../tasks/alerts_details'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +import { ruleDetailsUrl } from '../../urls/navigation'; import { addsFieldsToTimeline } from '../../tasks/rule_details'; describe('CTI Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { @@ -35,7 +34,7 @@ describe('CTI Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless' cy.task('esArchiverLoad', { archiveName: 'threat_indicator' }); cy.task('esArchiverLoad', { archiveName: 'suspicious_source_event' }); login(); - createRule({ ...getNewThreatIndicatorRule(), rule_id: 'rule_testing', enabled: true }); + disableExpandableFlyout(); }); @@ -46,8 +45,9 @@ describe('CTI Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless' beforeEach(() => { login(); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); + createRule({ ...getNewThreatIndicatorRule(), rule_id: 'rule_testing', enabled: true }).then( + (rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id)) + ); }); // Skipped: https://github.com/elastic/kibana/issues/162818 @@ -159,12 +159,6 @@ describe('CTI Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless' cy.task('esArchiverLoad', { archiveName: 'threat_indicator2' }); }); - beforeEach(() => { - login(); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); - }); - after(() => { cy.task('esArchiverUnload', 'threat_indicator2'); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/missing_privileges_callout.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/missing_privileges_callout.cy.ts index 0568037b5c693..30e0383ff3fa0 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/missing_privileges_callout.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_alerts/missing_privileges_callout.cy.ts @@ -7,12 +7,11 @@ import { ROLES } from '@kbn/security-solution-plugin/common/test'; -import { DETECTIONS_RULE_MANAGEMENT_URL, ALERTS_URL } from '../../urls/navigation'; +import { DETECTIONS_RULE_MANAGEMENT_URL, ALERTS_URL, ruleDetailsUrl } from '../../urls/navigation'; import { getNewRule } from '../../objects/rule'; import { PAGE_TITLE } from '../../screens/common/page'; import { login, visitWithoutDateRange, waitForPageWithoutDateRange } from '../../tasks/login'; -import { goToRuleDetails } from '../../tasks/alerts_detection_rules'; import { createRule, deleteCustomRule } from '../../tasks/api_calls/rules'; import { getCallOut, @@ -75,10 +74,9 @@ describe('Detections > Callouts', { tags: '@ess' }, () => { context('On Rule Details page', () => { beforeEach(() => { - createRule(getNewRule()); - loadPageAsReadOnlyUser(DETECTIONS_RULE_MANAGEMENT_URL); - waitForPageTitleToBeShown(); - goToRuleDetails(); + createRule(getNewRule()).then((rule) => + loadPageAsReadOnlyUser(ruleDetailsUrl(rule.body.id)) + ); }); afterEach(() => { @@ -126,10 +124,9 @@ describe('Detections > Callouts', { tags: '@ess' }, () => { context('On Rule Details page', () => { beforeEach(() => { - createRule(getNewRule()); - loadPageAsPlatformEngineer(DETECTIONS_RULE_MANAGEMENT_URL); - waitForPageTitleToBeShown(); - goToRuleDetails(); + createRule(getNewRule()).then((rule) => + loadPageAsPlatformEngineer(ruleDetailsUrl(rule.body.id)) + ); }); afterEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_actions/rule_actions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_actions/rule_actions.cy.ts index a4b15f68cdcb9..fef7df04844e6 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_actions/rule_actions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_actions/rule_actions.cy.ts @@ -8,7 +8,7 @@ import { getIndexConnector } from '../../../objects/connector'; import { getSimpleCustomQueryRule } from '../../../objects/rule'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { goToRuleDetailsOf } from '../../../tasks/alerts_detection_rules'; import { deleteIndex, waitForNewDocumentToBeIndexed } from '../../../tasks/api_calls/elasticsearch'; import { cleanKibana, @@ -51,14 +51,15 @@ describe( const initialNumberOfDocuments = 0; const expectedJson = JSON.parse(actions.connectors[0].document); - it('Indexes a new document after the index action is triggered ', function () { + it('Indexes a new document after the index action is triggered', function () { visit(RULE_CREATION); fillDefineCustomRuleAndContinue(rule); fillAboutRuleAndContinue(rule); fillScheduleRuleAndContinue(rule); fillRuleAction(actions); createAndEnableRule(); - goToRuleDetails(); + + goToRuleDetailsOf(rule.name); /* When the rule is executed, the action is triggered. We wait for the new document to be indexed */ waitForNewDocumentToBeIndexed(index, initialNumberOfDocuments); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_query_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_query_rule.cy.ts index 7bb89b35ca83a..18455fb116734 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_query_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_query_rule.cy.ts @@ -73,11 +73,9 @@ import { import { deleteFirstRule, deleteRuleFromDetailsPage, - editFirstRule, expectManagementTableRules, getRulesManagementTableRows, - goToRuleDetails, - goToTheRuleDetailsOf, + goToRuleDetailsOf, selectRulesByName, } from '../../../tasks/alerts_detection_rules'; import { deleteSelectedRules } from '../../../tasks/rules_bulk_actions'; @@ -108,10 +106,14 @@ import { waitForAlertsToPopulate, } from '../../../tasks/create_new_rule'; import { saveEditedRule } from '../../../tasks/edit_rule'; -import { login, visit, visitSecurityDetectionRulesPage } from '../../../tasks/login'; +import { + login, + visit, + visitSecurityDetectionRulesPage, + visitWithoutDateRange, +} from '../../../tasks/login'; import { enablesRule, getDetails, waitForTheRuleToBeExecuted } from '../../../tasks/rule_details'; - -import { RULE_CREATION } from '../../../urls/navigation'; +import { ruleDetailsUrl, ruleEditUrl, RULE_CREATION } from '../../../urls/navigation'; describe('Custom query rules', { tags: ['@ess', '@brokenInServerless'] }, () => { beforeEach(() => { @@ -180,7 +182,7 @@ describe('Custom query rules', { tags: ['@ess', '@brokenInServerless'] }, () => }); cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); - goToRuleDetails(); + goToRuleDetailsOf(ruleFields.ruleName); cy.log('Asserting rule details'); cy.get(RULE_NAME_HEADER).should('contain', ruleFields.ruleName); @@ -236,10 +238,15 @@ describe('Custom query rules', { tags: ['@ess', '@brokenInServerless'] }, () => describe('Custom detection rules deletion and edition', () => { context('Deletion', () => { + const TESTED_RULE_DATA = getNewRule({ + rule_id: 'rule1', + name: 'New Rule Test', + enabled: false, + max_signals: 500, + }); + beforeEach(() => { - createRule( - getNewRule({ rule_id: 'rule1', name: 'New Rule Test', enabled: false, max_signals: 500 }) - ); + createRule(TESTED_RULE_DATA); createRule( getNewOverrideRule({ rule_id: 'rule2', @@ -279,7 +286,7 @@ describe('Custom query rules', { tags: ['@ess', '@brokenInServerless'] }, () => it('Deletes more than one rule', () => { getRulesManagementTableRows().then((rules) => { - const rulesToDelete = ['New Rule Test', 'Override Rule'] as const; + const rulesToDelete = [TESTED_RULE_DATA.name, 'Override Rule'] as const; const initialNumberOfRules = rules.length; const numberOfRulesToBeDeleted = 2; const expectedNumberOfRulesAfterDeletion = @@ -316,7 +323,7 @@ describe('Custom query rules', { tags: ['@ess', '@brokenInServerless'] }, () => const initialNumberOfRules = rules.length; const expectedNumberOfRulesAfterDeletion = initialNumberOfRules - 1; - goToTheRuleDetailsOf('New Rule Test'); + goToRuleDetailsOf(TESTED_RULE_DATA.name); cy.intercept('POST', '/api/detection_engine/rules/_bulk_delete').as('deleteRule'); deleteRuleFromDetailsPage(); @@ -339,108 +346,119 @@ describe('Custom query rules', { tags: ['@ess', '@brokenInServerless'] }, () => }); context('Edition', () => { - const rule = getEditedRule(); - const expectedEditedtags = rule.tags?.join(''); - const expectedEditedIndexPatterns = rule.index; - - beforeEach(() => { - deleteConnectors(); - createRule(getExistingRule({ rule_id: 'rule1', enabled: true })); - login(); - visitSecurityDetectionRulesPage(); - }); - - it('Only modifies rule active status on enable/disable', () => { - enablesRule(); + const editedRuleData = getEditedRule(); + const expectedEditedTags = editedRuleData.tags?.join(''); + const expectedEditedIndexPatterns = editedRuleData.index; + + describe('on rule details page', () => { + beforeEach(() => { + deleteConnectors(); + login(); + createRule(getExistingRule({ rule_id: 'rule1', enabled: true })).then((rule) => + visitWithoutDateRange(ruleDetailsUrl(rule.body.id)) + ); + }); - cy.intercept('GET', `/api/detection_engine/rules?id=*`).as('fetchRuleDetails'); + it('Only modifies rule active status on enable/disable', () => { + enablesRule(); - goToRuleDetails(); + cy.intercept('GET', `/api/detection_engine/rules?id=*`).as('fetchRuleDetails'); - cy.wait('@fetchRuleDetails').then(({ response }) => { - cy.wrap(response?.statusCode).should('eql', 200); + cy.wait('@fetchRuleDetails').then(({ response }) => { + cy.wrap(response?.statusCode).should('eql', 200); - cy.wrap(response?.body.max_signals).should('eql', getExistingRule().max_signals); - cy.wrap(response?.body.enabled).should('eql', false); + cy.wrap(response?.body.max_signals).should('eql', getExistingRule().max_signals); + cy.wrap(response?.body.enabled).should('eql', false); + }); }); }); - it('Allows a rule to be edited', () => { - const existingRule = getExistingRule(); + describe('on rule editing page', () => { + beforeEach(() => { + deleteConnectors(); + login(); + createRule(getExistingRule({ rule_id: 'rule1', enabled: true })).then((rule) => + visitWithoutDateRange(ruleEditUrl(rule.body.id)) + ); + }); - editFirstRule(); + it('Allows a rule to be edited', () => { + const existingRule = getExistingRule(); - // expect define step to populate - cy.get(CUSTOM_QUERY_INPUT).should('have.value', existingRule.query); + // expect define step to populate + cy.get(CUSTOM_QUERY_INPUT).should('have.value', existingRule.query); - cy.get(DEFINE_INDEX_INPUT).should('have.text', existingRule.index?.join('')); + cy.get(DEFINE_INDEX_INPUT).should('have.text', existingRule.index?.join('')); - goToAboutStepTab(); + goToAboutStepTab(); - // expect about step to populate - cy.get(RULE_NAME_INPUT).invoke('val').should('eql', existingRule.name); - cy.get(RULE_DESCRIPTION_INPUT).should('have.text', existingRule.description); - cy.get(TAGS_FIELD).should('have.text', existingRule.tags?.join('')); - cy.get(SEVERITY_DROPDOWN).should('have.text', 'High'); - cy.get(DEFAULT_RISK_SCORE_INPUT).invoke('val').should('eql', `${existingRule.risk_score}`); + // expect about step to populate + cy.get(RULE_NAME_INPUT).invoke('val').should('eql', existingRule.name); + cy.get(RULE_DESCRIPTION_INPUT).should('have.text', existingRule.description); + cy.get(TAGS_FIELD).should('have.text', existingRule.tags?.join('')); + cy.get(SEVERITY_DROPDOWN).should('have.text', 'High'); + cy.get(DEFAULT_RISK_SCORE_INPUT) + .invoke('val') + .should('eql', `${existingRule.risk_score}`); - goToScheduleStepTab(); + goToScheduleStepTab(); - // expect schedule step to populate - const interval = existingRule.interval; - const intervalParts = interval != null && interval.match(/[0-9]+|[a-zA-Z]+/g); - if (intervalParts) { - const [amount, unit] = intervalParts; - cy.get(SCHEDULE_INTERVAL_AMOUNT_INPUT).invoke('val').should('eql', amount); - cy.get(SCHEDULE_INTERVAL_UNITS_INPUT).invoke('val').should('eql', unit); - } else { - throw new Error('Cannot assert scheduling info on a rule without an interval'); - } + // expect schedule step to populate + const interval = existingRule.interval; + const intervalParts = interval != null && interval.match(/[0-9]+|[a-zA-Z]+/g); + if (intervalParts) { + const [amount, unit] = intervalParts; + cy.get(SCHEDULE_INTERVAL_AMOUNT_INPUT).invoke('val').should('eql', amount); + cy.get(SCHEDULE_INTERVAL_UNITS_INPUT).invoke('val').should('eql', unit); + } else { + throw new Error('Cannot assert scheduling info on a rule without an interval'); + } - goToActionsStepTab(); + goToActionsStepTab(); - addEmailConnectorAndRuleAction('test@example.com', 'Subject'); + addEmailConnectorAndRuleAction('test@example.com', 'Subject'); - cy.get(ACTIONS_SUMMARY_BUTTON).should('have.text', 'Summary of alerts'); - cy.get(ACTIONS_NOTIFY_WHEN_BUTTON).should('have.text', 'Per rule run'); + cy.get(ACTIONS_SUMMARY_BUTTON).should('have.text', 'Summary of alerts'); + cy.get(ACTIONS_NOTIFY_WHEN_BUTTON).should('have.text', 'Per rule run'); - goToAboutStepTab(); - cy.get(TAGS_CLEAR_BUTTON).click(); - fillAboutRule(getEditedRule()); + goToAboutStepTab(); + cy.get(TAGS_CLEAR_BUTTON).click(); + fillAboutRule(getEditedRule()); - cy.intercept('GET', '/api/detection_engine/rules?id*').as('getRule'); + cy.intercept('GET', '/api/detection_engine/rules?id*').as('getRule'); - saveEditedRule(); + saveEditedRule(); - cy.wait('@getRule').then(({ response }) => { - cy.wrap(response?.statusCode).should('eql', 200); - // ensure that editing rule does not modify max_signals - cy.wrap(response?.body.max_signals).should('eql', existingRule.max_signals); - }); + cy.wait('@getRule').then(({ response }) => { + cy.wrap(response?.statusCode).should('eql', 200); + // ensure that editing rule does not modify max_signals + cy.wrap(response?.body.max_signals).should('eql', existingRule.max_signals); + }); - cy.get(RULE_NAME_HEADER).should('contain', `${getEditedRule().name}`); - cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', getEditedRule().description); - cy.get(ABOUT_DETAILS).within(() => { - getDetails(SEVERITY_DETAILS).should('have.text', 'Medium'); - getDetails(RISK_SCORE_DETAILS).should('have.text', `${getEditedRule().risk_score}`); - getDetails(TAGS_DETAILS).should('have.text', expectedEditedtags); - }); - cy.get(INVESTIGATION_NOTES_TOGGLE).click(); - cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', getEditedRule().note); - cy.get(DEFINITION_DETAILS).within(() => { - getDetails(INDEX_PATTERNS_DETAILS).should( - 'have.text', - expectedEditedIndexPatterns?.join('') - ); - getDetails(CUSTOM_QUERY_DETAILS).should('have.text', getEditedRule().query); - getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query'); - getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None'); - }); - if (getEditedRule().interval) { - cy.get(SCHEDULE_DETAILS).within(() => { - getDetails(RUNS_EVERY_DETAILS).should('have.text', getEditedRule().interval); + cy.get(RULE_NAME_HEADER).should('contain', `${getEditedRule().name}`); + cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', getEditedRule().description); + cy.get(ABOUT_DETAILS).within(() => { + getDetails(SEVERITY_DETAILS).should('have.text', 'Medium'); + getDetails(RISK_SCORE_DETAILS).should('have.text', `${getEditedRule().risk_score}`); + getDetails(TAGS_DETAILS).should('have.text', expectedEditedTags); }); - } + cy.get(INVESTIGATION_NOTES_TOGGLE).click(); + cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', getEditedRule().note); + cy.get(DEFINITION_DETAILS).within(() => { + getDetails(INDEX_PATTERNS_DETAILS).should( + 'have.text', + expectedEditedIndexPatterns?.join('') + ); + getDetails(CUSTOM_QUERY_DETAILS).should('have.text', getEditedRule().query); + getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query'); + getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None'); + }); + if (getEditedRule().interval) { + cy.get(SCHEDULE_DETAILS).within(() => { + getDetails(RUNS_EVERY_DETAILS).should('have.text', getEditedRule().interval); + }); + } + }); }); }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_query_rule_data_view.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_query_rule_data_view.cy.ts index 2c2f44024e7a2..da838f54457c3 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_query_rule_data_view.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_query_rule_data_view.cy.ts @@ -50,7 +50,7 @@ import { import { getRulesManagementTableRows, - goToRuleDetails, + goToRuleDetailsOf, } from '../../../tasks/alerts_detection_rules'; import { postDataView } from '../../../tasks/common'; import { @@ -104,7 +104,7 @@ describe('Custom query rules', { tags: ['@ess', '@brokenInServerless'] }, () => cy.get(SEVERITY).should('have.text', 'High'); cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); - goToRuleDetails(); + goToRuleDetailsOf(rule.name); cy.get(RULE_NAME_HEADER).should('contain', `${rule.name}`); cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description); @@ -160,7 +160,7 @@ describe('Custom query rules', { tags: ['@ess', '@brokenInServerless'] }, () => fillScheduleRuleAndContinue(rule); createRuleWithoutEnabling(); - goToRuleDetails(); + goToRuleDetailsOf(rule.name); cy.get(EDIT_RULE_SETTINGS_LINK).click(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_saved_query_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_saved_query_rule.cy.ts index fc9dd511aa21f..747725c88aaa3 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_saved_query_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/custom_saved_query_rule.cy.ts @@ -22,7 +22,7 @@ import { CUSTOM_QUERY_DETAILS, } from '../../../screens/rule_details'; -import { goToRuleDetails, editFirstRule } from '../../../tasks/alerts_detection_rules'; +import { editFirstRule, goToRuleDetailsOf } from '../../../tasks/alerts_detection_rules'; import { createSavedQuery, deleteSavedQueries } from '../../../tasks/api_calls/saved_queries'; import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; import { @@ -35,11 +35,16 @@ import { uncheckLoadQueryDynamically, } from '../../../tasks/create_new_rule'; import { saveEditedRule } from '../../../tasks/edit_rule'; -import { login, visit } from '../../../tasks/login'; +import { login, visit, visitWithoutDateRange } from '../../../tasks/login'; import { assertDetailsNotExist, getDetails } from '../../../tasks/rule_details'; import { createRule } from '../../../tasks/api_calls/rules'; -import { RULE_CREATION, SECURITY_DETECTIONS_RULES_URL } from '../../../urls/navigation'; +import { + ruleDetailsUrl, + ruleEditUrl, + RULE_CREATION, + SECURITY_DETECTIONS_RULES_URL, +} from '../../../urls/navigation'; const savedQueryName = 'custom saved query'; const savedQueryQuery = 'process.name: test'; @@ -86,7 +91,7 @@ describe('Custom saved_query rules', { tags: ['@ess', '@brokenInServerless'] }, cy.wrap(response?.body.type).should('equal', 'saved_query'); }); - goToRuleDetails(); + goToRuleDetailsOf(rule.name); cy.get(RULE_NAME_HEADER).should('contain', `${rule.name}`); @@ -99,50 +104,59 @@ describe('Custom saved_query rules', { tags: ['@ess', '@brokenInServerless'] }, context('Non existent saved query', () => { const FAILED_TO_LOAD_ERROR = 'Failed to load the saved query'; - beforeEach(() => { - createRule(getSavedQueryRule({ saved_id: 'non-existent', query: undefined })); - visit(SECURITY_DETECTIONS_RULES_URL); - }); - it('Shows error toast on details page when saved query can not be loaded', function () { - goToRuleDetails(); - - cy.get(TOASTER).should('contain', FAILED_TO_LOAD_ERROR); - }); - it('Shows validation error on rule edit when saved query can not be loaded', function () { - editFirstRule(); + describe('on rule details page', () => { + beforeEach(() => { + createRule( + getSavedQueryRule({ + saved_id: 'non-existent', + query: undefined, + }) + ).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id))); + }); - cy.get(TOASTER).should('contain', FAILED_TO_LOAD_ERROR); + it('Shows error toast on details page when saved query can not be loaded', function () { + cy.get(TOASTER).should('contain', FAILED_TO_LOAD_ERROR); + }); }); - it('Allows to update saved_query rule with non-existent query', () => { - editFirstRule(); + describe('on rule editing page', () => { + beforeEach(() => { + createRule( + getSavedQueryRule({ + saved_id: 'non-existent', + query: undefined, + }) + ).then((rule) => visitWithoutDateRange(ruleEditUrl(rule.body.id))); + }); - cy.get(LOAD_QUERY_DYNAMICALLY_CHECKBOX).should('exist'); + it('Shows validation error on rule edit when saved query can not be loaded', function () { + cy.get(TOASTER).should('contain', FAILED_TO_LOAD_ERROR); + }); - cy.intercept('PUT', '/api/detection_engine/rules').as('editedRule'); - saveEditedRule(); + it('Allows to update saved_query rule with non-existent query', () => { + cy.get(LOAD_QUERY_DYNAMICALLY_CHECKBOX).should('exist'); - cy.wait('@editedRule').then(({ response }) => { - // updated rule type shouldn't change - cy.wrap(response?.body.type).should('equal', 'saved_query'); - }); + cy.intercept('PUT', '/api/detection_engine/rules').as('editedRule'); + saveEditedRule(); - cy.get(DEFINE_RULE_PANEL_PROGRESS).should('not.exist'); + cy.wait('@editedRule').then(({ response }) => { + // updated rule type shouldn't change + cy.wrap(response?.body.type).should('equal', 'saved_query'); + }); - assertDetailsNotExist(SAVED_QUERY_NAME_DETAILS); - assertDetailsNotExist(SAVED_QUERY_DETAILS); + cy.get(DEFINE_RULE_PANEL_PROGRESS).should('not.exist'); + + assertDetailsNotExist(SAVED_QUERY_NAME_DETAILS); + assertDetailsNotExist(SAVED_QUERY_DETAILS); + }); }); }); context('Editing', () => { it('Allows to update query rule as saved_query rule type', () => { createSavedQuery(savedQueryName, savedQueryQuery); - createRule(getNewRule()); - - visit(SECURITY_DETECTIONS_RULES_URL); - - editFirstRule(); + createRule(getNewRule()).then((rule) => visitWithoutDateRange(ruleEditUrl(rule.body.id))); selectAndLoadSavedQuery(savedQueryName, savedQueryQuery); checkLoadQueryDynamically(); @@ -165,13 +179,11 @@ describe('Custom saved_query rules', { tags: ['@ess', '@brokenInServerless'] }, const expectedCustomTestQuery = 'random test query'; createSavedQuery(savedQueryName, savedQueryQuery).then((response) => { cy.log(JSON.stringify(response.body, null, 2)); - createRule(getSavedQueryRule({ saved_id: response.body.id, query: undefined })); + createRule(getSavedQueryRule({ saved_id: response.body.id, query: undefined })).then( + (rule) => visitWithoutDateRange(ruleEditUrl(rule.body.id)) + ); }); - visit(SECURITY_DETECTIONS_RULES_URL); - - editFirstRule(); - // query input should be disabled and has value of saved query getCustomQueryInput().should('have.value', savedQueryQuery).should('be.disabled'); @@ -192,11 +204,10 @@ describe('Custom saved_query rules', { tags: ['@ess', '@brokenInServerless'] }, it('Allows to update saved_query rule with non-existent query by adding custom query', () => { const expectedCustomTestQuery = 'random test query'; - createRule(getSavedQueryRule({ saved_id: 'non-existent', query: undefined })); + createRule(getSavedQueryRule({ saved_id: 'non-existent', query: undefined })).then((rule) => + visitWithoutDateRange(ruleEditUrl(rule.body.id)) + ); - visit(SECURITY_DETECTIONS_RULES_URL); - - editFirstRule(); uncheckLoadQueryDynamically(); // type custom query, ensure Load dynamically checkbox is absent, as rule can't be saved win non valid saved query @@ -216,7 +227,9 @@ describe('Custom saved_query rules', { tags: ['@ess', '@brokenInServerless'] }, it('Allows to update saved_query rule with non-existent query by selecting another saved query', () => { createSavedQuery(savedQueryName, savedQueryQuery); - createRule(getSavedQueryRule({ saved_id: 'non-existent', query: undefined })); + createRule(getSavedQueryRule({ saved_id: 'non-existent', query: undefined })).then((rule) => + visitWithoutDateRange(ruleEditUrl(rule.body.id)) + ); visit(SECURITY_DETECTIONS_RULES_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts index a558ac6ccedb7..35957cc31938a 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts @@ -42,11 +42,7 @@ import { } from '../../../screens/rule_details'; import { getDetails, waitForTheRuleToBeExecuted } from '../../../tasks/rule_details'; -import { - expectNumberOfRules, - goToRuleDetails, - goToTheRuleDetailsOf, -} from '../../../tasks/alerts_detection_rules'; +import { expectNumberOfRules, goToRuleDetailsOf } from '../../../tasks/alerts_detection_rules'; import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; import { createAndEnableRule, @@ -97,7 +93,7 @@ describe('EQL rules', { tags: ['@ess', '@brokenInServerless'] }, () => { cy.get(SEVERITY).should('have.text', 'High'); cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); - goToRuleDetails(); + goToRuleDetailsOf(rule.name); cy.get(RULE_NAME_HEADER).should('contain', `${rule.name}`); cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description); @@ -164,7 +160,7 @@ describe('EQL rules', { tags: ['@ess', '@brokenInServerless'] }, () => { fillAboutRuleAndContinue(rule); fillScheduleRuleAndContinue(rule); createAndEnableRule(); - goToTheRuleDetailsOf(rule.name); + goToRuleDetailsOf(rule.name); waitForTheRuleToBeExecuted(); waitForAlertsToPopulate(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts index 9e896fa6861fd..42dbf0ac0182e 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts @@ -59,15 +59,16 @@ import { investigateFirstAlertInTimeline } from '../../../tasks/alerts'; import { duplicateFirstRule, duplicateRuleFromMenu, - goToRuleDetails, checkDuplicatedRule, expectNumberOfRules, selectAllRules, + goToRuleDetailsOf, + disableAutoRefresh, } from '../../../tasks/alerts_detection_rules'; import { duplicateSelectedRulesWithExceptions } from '../../../tasks/rules_bulk_actions'; import { createRule } from '../../../tasks/api_calls/rules'; import { loadPrepackagedTimelineTemplates } from '../../../tasks/api_calls/timelines'; -import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; +import { cleanKibana } from '../../../tasks/common'; import { createAndEnableRule, fillAboutRuleAndContinue, @@ -100,14 +101,18 @@ import { SCHEDULE_LOOKBACK_UNITS_INPUT, } from '../../../screens/create_new_rule'; import { goBackToRuleDetails } from '../../../tasks/edit_rule'; -import { login, visit, visitWithoutDateRange } from '../../../tasks/login'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; import { goBackToRulesTable, getDetails, waitForTheRuleToBeExecuted, } from '../../../tasks/rule_details'; -import { DETECTIONS_RULE_MANAGEMENT_URL, RULE_CREATION } from '../../../urls/navigation'; +import { + DETECTIONS_RULE_MANAGEMENT_URL, + ruleDetailsUrl, + RULE_CREATION, +} from '../../../urls/navigation'; const DEFAULT_THREAT_MATCH_QUERY = '@timestamp >= "now-30d/d"'; @@ -121,21 +126,13 @@ describe('indicator match', { tags: ['@ess', '@brokenInServerless'] }, () => { const expectedNumberOfRules = 1; const expectedNumberOfAlerts = '1 alert'; - before(() => { + beforeEach(() => { cleanKibana(); cy.task('esArchiverLoad', { archiveName: 'threat_indicator' }); cy.task('esArchiverLoad', { archiveName: 'suspicious_source_event' }); - }); - - beforeEach(() => { login(); }); - after(() => { - cy.task('esArchiverUnload', 'threat_indicator'); - cy.task('esArchiverUnload', 'suspicious_source_event'); - }); - describe('Creating new indicator match rules', () => { describe('Index patterns', () => { beforeEach(() => { @@ -430,11 +427,6 @@ describe('indicator match', { tags: ['@ess', '@brokenInServerless'] }, () => { }); describe('Generating signals', () => { - beforeEach(() => { - login(); - deleteAlertsAndRules(); - }); - it('Creates and enables a new Indicator Match rule', () => { const rule = getNewThreatIndicatorRule(); visitWithoutDateRange(RULE_CREATION); @@ -453,7 +445,7 @@ describe('indicator match', { tags: ['@ess', '@brokenInServerless'] }, () => { cy.get(SEVERITY).should('have.text', 'Critical'); cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); - goToRuleDetails(); + goToRuleDetailsOf(rule.name); cy.get(RULE_NAME_HEADER).should('contain', `${rule.name}`); cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description); @@ -510,9 +502,10 @@ describe('indicator match', { tags: ['@ess', '@brokenInServerless'] }, () => { const accessibilityText = `Press enter for options, or press space to begin dragging.`; loadPrepackagedTimelineTemplates(); - createRule(getNewThreatIndicatorRule({ rule_id: 'rule_testing', enabled: true })); - visit(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); + createRule(getNewThreatIndicatorRule({ rule_id: 'rule_testing', enabled: true })).then( + (rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id)) + ); + waitForAlertsToPopulate(); investigateFirstAlertInTimeline(); @@ -541,32 +534,46 @@ describe('indicator match', { tags: ['@ess', '@brokenInServerless'] }, () => { }); describe('Duplicates the indicator rule', () => { - beforeEach(() => { - login(); - deleteAlertsAndRules(); - createRule(getNewThreatIndicatorRule({ rule_id: 'rule_testing', enabled: true })); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); + const TESTED_RULE_DATA = getNewThreatIndicatorRule({ + name: 'Indicator rule duplicate test', + rule_id: 'rule_testing', + enabled: false, }); - it('Allows the rule to be duplicated from the table', () => { - duplicateFirstRule(); - goBackToRuleDetails(); - goBackToRulesTable(); - checkDuplicatedRule(); - }); + describe('on rule editing page', () => { + beforeEach(() => { + createRule(TESTED_RULE_DATA); + visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); + disableAutoRefresh(); + }); - it("Allows the rule to be duplicated from the table's bulk actions", () => { - selectAllRules(); - duplicateSelectedRulesWithExceptions(); - checkDuplicatedRule(); + it('Allows the rule to be duplicated from the table', () => { + duplicateFirstRule(); + goBackToRuleDetails(); + goBackToRulesTable(); + checkDuplicatedRule(TESTED_RULE_DATA.name); + }); + + it("Allows the rule to be duplicated from the table's bulk actions", () => { + selectAllRules(); + duplicateSelectedRulesWithExceptions(); + checkDuplicatedRule(`${TESTED_RULE_DATA.name} [Duplicate]`); + }); }); - it('Allows the rule to be duplicated from the edit screen', () => { - goToRuleDetails(); - duplicateRuleFromMenu(); - goBackToRuleDetails(); - goBackToRulesTable(); - checkDuplicatedRule(); + describe('on rule details page', () => { + beforeEach(() => { + createRule(getNewThreatIndicatorRule(TESTED_RULE_DATA)).then((rule) => + visitWithoutDateRange(ruleDetailsUrl(rule.body.id)) + ); + }); + + it('Allows the rule to be duplicated', () => { + duplicateRuleFromMenu(); + goBackToRuleDetails(); + goBackToRulesTable(); + checkDuplicatedRule(`${TESTED_RULE_DATA.name} [Duplicate]`); + }); }); }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/machine_learning_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/machine_learning_rule.cy.ts index e65764dff6203..f258ff6c804b7 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/machine_learning_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/machine_learning_rule.cy.ts @@ -40,7 +40,7 @@ import { } from '../../../screens/rule_details'; import { getDetails } from '../../../tasks/rule_details'; -import { expectNumberOfRules, goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { expectNumberOfRules, goToRuleDetailsOf } from '../../../tasks/alerts_detection_rules'; import { cleanKibana } from '../../../tasks/common'; import { createAndEnableRule, @@ -86,7 +86,7 @@ describe('Detection rules, machine learning', { tags: ['@ess', '@brokenInServerl cy.get(SEVERITY).should('have.text', 'Critical'); cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); - goToRuleDetails(); + goToRuleDetailsOf(mlRule.name); cy.get(RULE_NAME_HEADER).should('contain', `${mlRule.name}`); cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', mlRule.description); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/new_terms_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/new_terms_rule.cy.ts index 2b840111b97bc..ffcda7468bb61 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/new_terms_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/new_terms_rule.cy.ts @@ -44,7 +44,7 @@ import { } from '../../../screens/rule_details'; import { getDetails, waitForTheRuleToBeExecuted } from '../../../tasks/rule_details'; -import { expectNumberOfRules, goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { expectNumberOfRules, goToRuleDetailsOf } from '../../../tasks/alerts_detection_rules'; import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; import { createAndEnableRule, @@ -94,7 +94,7 @@ describe('New Terms rules', { tags: ['@ess', '@brokenInServerless'] }, () => { cy.get(SEVERITY).should('have.text', 'High'); cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); - goToRuleDetails(); + goToRuleDetailsOf(rule.name); cy.get(RULE_NAME_HEADER).should('contain', `${rule.name}`); cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/override.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/override.cy.ts index 4aa1bb9e56724..837d0621cbe6d 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/override.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/override.cy.ts @@ -47,8 +47,8 @@ import { TIMESTAMP_OVERRIDE_DETAILS, } from '../../../screens/rule_details'; -import { expectNumberOfRules, goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { deleteAlertsAndRules } from '../../../tasks/common'; +import { expectNumberOfRules, goToRuleDetailsOf } from '../../../tasks/alerts_detection_rules'; import { createAndEnableRule, fillAboutRuleWithOverrideAndContinue, @@ -90,7 +90,7 @@ describe('Detection rules, override', { tags: ['@ess', '@brokenInServerless'] }, cy.get(SEVERITY).should('have.text', 'High'); cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); - goToRuleDetails(); + goToRuleDetailsOf(rule.name); cy.get(RULE_NAME_HEADER).should('contain', `${rule.name}`); cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts index 078be723c39ac..1f93d745884e0 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts @@ -44,7 +44,7 @@ import { } from '../../../screens/rule_details'; import { getDetails, waitForTheRuleToBeExecuted } from '../../../tasks/rule_details'; -import { expectNumberOfRules, goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { expectNumberOfRules, goToRuleDetailsOf } from '../../../tasks/alerts_detection_rules'; import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; import { createAndEnableRule, @@ -92,7 +92,7 @@ describe('Detection rules, threshold', { tags: ['@ess', '@brokenInServerless'] } cy.get(SEVERITY).should('have.text', 'High'); cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); - goToRuleDetails(); + goToRuleDetailsOf(rule.name); cy.get(RULE_NAME_HEADER).should('contain', `${rule.name}`); cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_duplicate_rules.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_duplicate_rules.cy.ts index b95741083a065..96dd999b6e95a 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_duplicate_rules.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_duplicate_rules.cy.ts @@ -6,7 +6,7 @@ */ import { - goToTheRuleDetailsOf, + goToRuleDetailsOf, expectManagementTableRules, selectAllRules, disableAutoRefresh, @@ -117,7 +117,7 @@ describe( selectAllRules(); duplicateSelectedRulesWithExceptions(); expectManagementTableRules([`${RULE_NAME} [Duplicate]`]); - goToTheRuleDetailsOf(`${RULE_NAME} [Duplicate]`); + goToRuleDetailsOf(`${RULE_NAME} [Duplicate]`); goToExceptionsTab(); assertExceptionItemsExists(EXCEPTION_CARD_ITEM_NAME, [NON_EXPIRED_EXCEPTION_ITEM_NAME]); viewExpiredExceptionItems(); @@ -128,7 +128,7 @@ describe( selectAllRules(); duplicateSelectedRulesWithNonExpiredExceptions(); expectManagementTableRules([`${RULE_NAME} [Duplicate]`]); - goToTheRuleDetailsOf(`${RULE_NAME} [Duplicate]`); + goToRuleDetailsOf(`${RULE_NAME} [Duplicate]`); goToExceptionsTab(); assertExceptionItemsExists(EXCEPTION_CARD_ITEM_NAME, [NON_EXPIRED_EXCEPTION_ITEM_NAME]); viewExpiredExceptionItems(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts index 4b86a8344836c..6b2d3a530cca5 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts @@ -27,7 +27,7 @@ import { EUI_CHECKBOX, EUI_FILTER_SELECT_ITEM } from '../../../../../screens/com import { selectAllRules, - goToTheRuleDetailsOf, + goToRuleDetailsOf, testAllTagsBadges, testTagsBadge, testMultipleSelectedRulesLabel, @@ -401,7 +401,7 @@ describe('Detection rules, bulk edit', { tags: ['@ess', '@brokenInServerless'] } }); // check if rule has been updated - goToTheRuleDetailsOf(RULE_NAME); + goToRuleDetailsOf(RULE_NAME); hasIndexPatterns(resultingIndexPatterns.join('')); }); }); @@ -440,7 +440,7 @@ describe('Detection rules, bulk edit', { tags: ['@ess', '@brokenInServerless'] } }); // check if rule has been updated - goToTheRuleDetailsOf(RULE_NAME); + goToRuleDetailsOf(RULE_NAME); hasIndexPatterns(resultingIndexPatterns.join('')); }); }); @@ -496,7 +496,7 @@ describe('Detection rules, bulk edit', { tags: ['@ess', '@brokenInServerless'] } waitForBulkEditActionToFinish({ updatedCount: rulesToSelect.length }); // check if rule has been updated - goToTheRuleDetailsOf(RULE_NAME); + goToRuleDetailsOf(RULE_NAME); hasIndexPatterns(indexPattersToWrite.join('')); }); @@ -521,7 +521,7 @@ describe('Detection rules, bulk edit', { tags: ['@ess', '@brokenInServerless'] } waitForBulkEditActionToFinish({ updatedCount: rulesToSelect.length }); // check if rule has been updated - goToTheRuleDetailsOf(RULE_NAME); + goToRuleDetailsOf(RULE_NAME); hasIndexPatterns(resultingIndexPatterns.join('')); }); @@ -572,7 +572,7 @@ describe('Detection rules, bulk edit', { tags: ['@ess', '@brokenInServerless'] } waitForBulkEditActionToFinish({ updatedCount: rows.length }); // check if timeline template has been updated to selected one - goToTheRuleDetailsOf(RULE_NAME); + goToRuleDetailsOf(RULE_NAME); getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', timelineTemplateName); }); }); @@ -590,7 +590,7 @@ describe('Detection rules, bulk edit', { tags: ['@ess', '@brokenInServerless'] } waitForBulkEditActionToFinish({ updatedCount: rows.length }); // check if timeline template has been updated to selected one, by opening rule that have had timeline prior to editing - goToTheRuleDetailsOf(RULE_NAME); + goToRuleDetailsOf(RULE_NAME); getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', noneTimelineTemplate); }); }); @@ -627,7 +627,7 @@ describe('Detection rules, bulk edit', { tags: ['@ess', '@brokenInServerless'] } submitBulkEditForm(); waitForBulkEditActionToFinish({ updatedCount: rows.length }); - goToTheRuleDetailsOf(RULE_NAME); + goToRuleDetailsOf(RULE_NAME); assertRuleScheduleValues({ interval: '20h', @@ -651,7 +651,7 @@ describe('Detection rules, bulk edit', { tags: ['@ess', '@brokenInServerless'] } submitBulkEditForm(); waitForBulkEditActionToFinish({ updatedCount: rows.length }); - goToTheRuleDetailsOf(RULE_NAME); + goToRuleDetailsOf(RULE_NAME); assertRuleScheduleValues({ interval: '1h', diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_data_view.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_data_view.cy.ts index 32e96dd8f3cfb..b8b26df371ed0 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_data_view.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_data_view.cy.ts @@ -13,8 +13,7 @@ import { import { DATA_VIEW_DETAILS, INDEX_PATTERNS_DETAILS } from '../../../../../screens/rule_details'; import { - goToRuleDetails, - goToTheRuleDetailsOf, + goToRuleDetailsOf, expectManagementTableRules, selectAllRules, getRulesManagementTableRows, @@ -57,6 +56,50 @@ describe( 'Bulk editing index patterns of rules with a data view only', { tags: ['@ess', '@brokenInServerless'] }, () => { + const TESTED_CUSTOM_QUERY_RULE_DATA = getNewRule({ + index: undefined, + data_view_id: DATA_VIEW_ID, + rule_id: '1', + name: 'New Rule Test 1', + enabled: false, + }); + const TESTED_CUSTOM_QUERY_RULE_DATA_2 = getNewRule({ + index: undefined, + data_view_id: DATA_VIEW_ID, + saved_id: 'mocked', + rule_id: '6', + name: 'New Rule Test 2', + enabled: false, + }); + const TESTED_EQL_RULE_DATA = getEqlRule({ + index: undefined, + data_view_id: DATA_VIEW_ID, + rule_id: '2', + name: 'New EQL Rule', + enabled: false, + }); + const TESTED_THREAT_INDICATOR_RULE_DATA = getNewThreatIndicatorRule({ + index: undefined, + data_view_id: DATA_VIEW_ID, + rule_id: '3', + name: 'Threat Indicator Rule Test', + enabled: false, + }); + const TESTED_THRESHOLD_RULE_DATA = getNewThresholdRule({ + index: undefined, + data_view_id: DATA_VIEW_ID, + rule_id: '4', + name: 'Threshold Rule', + enabled: false, + }); + const TESTED_TERMS_RULE_DATA = getNewTermsRule({ + index: undefined, + data_view_id: DATA_VIEW_ID, + rule_id: '5', + name: 'New Terms Rule', + enabled: false, + }); + before(() => { cleanKibana(); }); @@ -68,72 +111,23 @@ describe( postDataView(DATA_VIEW_ID); - createRule( - getNewRule({ - index: undefined, - data_view_id: DATA_VIEW_ID, - rule_id: '1', - name: 'New Rule Test 1', - enabled: false, - }) - ); - createRule( - getEqlRule({ - index: undefined, - data_view_id: DATA_VIEW_ID, - rule_id: '2', - name: 'New EQL Rule', - enabled: false, - }) - ); - createRule( - getNewThreatIndicatorRule({ - index: undefined, - data_view_id: DATA_VIEW_ID, - rule_id: '3', - name: 'Threat Indicator Rule Test', - enabled: false, - }) - ); - createRule( - getNewThresholdRule({ - index: undefined, - data_view_id: DATA_VIEW_ID, - rule_id: '4', - name: 'Threshold Rule', - enabled: false, - }) - ); - createRule( - getNewTermsRule({ - index: undefined, - data_view_id: DATA_VIEW_ID, - rule_id: '5', - name: 'New Terms Rule', - enabled: false, - }) - ); - createRule( - getNewRule({ - index: undefined, - data_view_id: DATA_VIEW_ID, - saved_id: 'mocked', - rule_id: '6', - name: 'New Rule Test 2', - enabled: false, - }) - ); + createRule(TESTED_CUSTOM_QUERY_RULE_DATA); + createRule(TESTED_EQL_RULE_DATA); + createRule(TESTED_THREAT_INDICATOR_RULE_DATA); + createRule(TESTED_THRESHOLD_RULE_DATA); + createRule(TESTED_TERMS_RULE_DATA); + createRule(TESTED_CUSTOM_QUERY_RULE_DATA_2); visitSecurityDetectionRulesPage(); disableAutoRefresh(); expectManagementTableRules([ - 'New Rule Test 1', - 'New EQL Rule', - 'Threat Indicator Rule Test', - 'Threshold Rule', - 'New Terms Rule', - 'New Rule Test 2', + TESTED_CUSTOM_QUERY_RULE_DATA.name, + TESTED_EQL_RULE_DATA.name, + TESTED_THREAT_INDICATOR_RULE_DATA.name, + TESTED_THRESHOLD_RULE_DATA.name, + TESTED_TERMS_RULE_DATA.name, + TESTED_CUSTOM_QUERY_RULE_DATA_2.name, ]); }); @@ -151,7 +145,7 @@ describe( }); // check if rule still has data view and index patterns field does not exist - goToRuleDetails(); + goToRuleDetailsOf(TESTED_CUSTOM_QUERY_RULE_DATA.name); getDetails(DATA_VIEW_DETAILS).contains(DATA_VIEW_ID); assertDetailsNotExist(INDEX_PATTERNS_DETAILS); }); @@ -174,7 +168,7 @@ describe( waitForBulkEditActionToFinish({ updatedCount: rows.length }); // check if rule has been updated with index patterns and data view does not exist - goToRuleDetails(); + goToRuleDetailsOf(TESTED_CUSTOM_QUERY_RULE_DATA.name); hasIndexPatterns(expectedIndexPatterns.join('')); assertDetailsNotExist(DATA_VIEW_DETAILS); }); @@ -195,7 +189,7 @@ describe( }); // check if rule still has data view and index patterns field does not exist - goToRuleDetails(); + goToRuleDetailsOf(TESTED_CUSTOM_QUERY_RULE_DATA.name); getDetails(DATA_VIEW_DETAILS).contains(DATA_VIEW_ID); assertDetailsNotExist(INDEX_PATTERNS_DETAILS); }); @@ -215,7 +209,7 @@ describe( waitForBulkEditActionToFinish({ updatedCount: rows.length }); // check if rule has been overwritten with index patterns and data view does not exist - goToRuleDetails(); + goToRuleDetailsOf(TESTED_CUSTOM_QUERY_RULE_DATA.name); hasIndexPatterns(expectedIndexPatterns.join('')); assertDetailsNotExist(DATA_VIEW_DETAILS); }); @@ -239,7 +233,7 @@ describe( }); // check if rule still has data view and index patterns field does not exist - goToRuleDetails(); + goToRuleDetailsOf(TESTED_CUSTOM_QUERY_RULE_DATA.name); getDetails(DATA_VIEW_DETAILS).contains(DATA_VIEW_ID); }); }); @@ -250,6 +244,18 @@ describe( 'Bulk editing index patterns of rules with index patterns and rules with a data view', { tags: ['@ess', '@brokenInServerless'] }, () => { + const TESTED_CUSTOM_QUERY_RULE_DATA_WITH_DATAVIEW = getNewRule({ + name: 'with dataview', + index: [], + data_view_id: DATA_VIEW_ID, + rule_id: '1', + }); + const TESTED_CUSTOM_QUERY_RULE_DATA_WITHOUT_DATAVIEW = getNewRule({ + name: 'no data view', + index: ['test-index-1-*'], + rule_id: '2', + }); + before(() => { cleanKibana(); }); @@ -261,10 +267,8 @@ describe( postDataView(DATA_VIEW_ID); - createRule( - getNewRule({ name: 'with dataview', index: [], data_view_id: DATA_VIEW_ID, rule_id: '1' }) - ); - createRule(getNewRule({ name: 'no data view', index: ['test-index-1-*'], rule_id: '2' })); + createRule(TESTED_CUSTOM_QUERY_RULE_DATA_WITH_DATAVIEW); + createRule(TESTED_CUSTOM_QUERY_RULE_DATA_WITHOUT_DATAVIEW); visitSecurityDetectionRulesPage(); disableAutoRefresh(); @@ -286,7 +290,7 @@ describe( }); // check if rule still has data view and index patterns field does not exist - goToTheRuleDetailsOf('with dataview'); + goToRuleDetailsOf(TESTED_CUSTOM_QUERY_RULE_DATA_WITH_DATAVIEW.name); getDetails(DATA_VIEW_DETAILS).contains(DATA_VIEW_ID); assertDetailsNotExist(INDEX_PATTERNS_DETAILS); }); @@ -304,7 +308,7 @@ describe( }); // check if rule still has data view and index patterns field does not exist - goToRuleDetails(); + goToRuleDetailsOf(TESTED_CUSTOM_QUERY_RULE_DATA_WITH_DATAVIEW.name); assertDetailsNotExist(DATA_VIEW_DETAILS); }); } diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_persistent_state.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_persistent_state.cy.ts index 30c35ba44288a..d2b2f93200e26 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_persistent_state.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_persistent_state.cy.ts @@ -21,7 +21,6 @@ import { filterByCustomRules, filterBySearchTerm, filterByTags, - goToRuleDetails, expectFilterSearchTerm, expectFilterByTags, expectFilterByCustomRules, @@ -35,6 +34,7 @@ import { expectFilterByPrebuiltRules, expectFilterByEnabledRules, expectManagementTableRules, + goToRuleDetailsOf, } from '../../../../tasks/alerts_detection_rules'; import { createRule } from '../../../../tasks/api_calls/rules'; import { @@ -228,7 +228,7 @@ describe('Rules table: persistent state', { tags: ['@ess', '@serverless'] }, () changeRulesTableState(); goToTablePage(2); - goToRuleDetails(); + goToRuleDetailsOf('rule 6'); cy.go('back'); expectRulesManagementTab(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/value_lists/value_lists.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/value_lists/value_lists.cy.ts index 4cacc2ddeb24b..552f1c4f109e9 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/value_lists/value_lists.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/value_lists/value_lists.cy.ts @@ -22,6 +22,7 @@ import { exportValueList, waitForListsIndex, deleteValueLists, + KNOWN_VALUE_LIST_FILES, } from '../../../tasks/lists'; import { VALUE_LISTS_TABLE, @@ -39,7 +40,11 @@ describe('value lists', () => { describe('management modal', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { beforeEach(() => { login(); - deleteValueLists([TEXT_LIST_FILE_NAME, IPS_LIST_FILE_NAME, CIDRS_LIST_FILE_NAME]); + deleteValueLists([ + KNOWN_VALUE_LIST_FILES.TEXT, + KNOWN_VALUE_LIST_FILES.IPs, + KNOWN_VALUE_LIST_FILES.CIDRs, + ]); createListsIndex(); visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); waitForListsIndex(); @@ -59,52 +64,52 @@ describe('value lists', () => { it('creates a "keyword" list from an uploaded file', () => { selectValueListType('keyword'); - selectValueListsFile(TEXT_LIST_FILE_NAME); + selectValueListsFile(KNOWN_VALUE_LIST_FILES.TEXT); uploadValueList(); cy.get(VALUE_LISTS_TABLE) .find(VALUE_LISTS_ROW) .should(($row) => { - expect($row.text()).to.contain(TEXT_LIST_FILE_NAME); + expect($row.text()).to.contain(KNOWN_VALUE_LIST_FILES.TEXT); expect($row.text()).to.contain('Keywords'); }); }); it('creates a "text" list from an uploaded file', () => { selectValueListType('text'); - selectValueListsFile(TEXT_LIST_FILE_NAME); + selectValueListsFile(KNOWN_VALUE_LIST_FILES.TEXT); uploadValueList(); cy.get(VALUE_LISTS_TABLE) .find(VALUE_LISTS_ROW) .should(($row) => { - expect($row.text()).to.contain(TEXT_LIST_FILE_NAME); + expect($row.text()).to.contain(KNOWN_VALUE_LIST_FILES.TEXT); expect($row.text()).to.contain('Text'); }); }); it('creates a "ip" list from an uploaded file', () => { selectValueListType('ip'); - selectValueListsFile(IPS_LIST_FILE_NAME); + selectValueListsFile(KNOWN_VALUE_LIST_FILES.IPs); uploadValueList(); cy.get(VALUE_LISTS_TABLE) .find(VALUE_LISTS_ROW) .should(($row) => { - expect($row.text()).to.contain(IPS_LIST_FILE_NAME); + expect($row.text()).to.contain(KNOWN_VALUE_LIST_FILES.IPs); expect($row.text()).to.contain('IP addresses'); }); }); it('creates a "ip_range" list from an uploaded file', () => { selectValueListType('ip_range'); - selectValueListsFile(CIDRS_LIST_FILE_NAME); + selectValueListsFile(KNOWN_VALUE_LIST_FILES.CIDRs); uploadValueList(); cy.get(VALUE_LISTS_TABLE) .find(VALUE_LISTS_ROW) .should(($row) => { - expect($row.text()).to.contain(CIDRS_LIST_FILE_NAME); + expect($row.text()).to.contain(KNOWN_VALUE_LIST_FILES.CIDRs); expect($row.text()).to.contain('IP ranges'); }); }); @@ -113,46 +118,46 @@ describe('value lists', () => { // Flaky in serverless tests describe('delete list types', { tags: ['@brokenInServerless'] }, () => { it('deletes a "keyword" list from an uploaded file', () => { - importValueList(TEXT_LIST_FILE_NAME, 'keyword'); + importValueList(KNOWN_VALUE_LIST_FILES.TEXT, 'keyword'); openValueListsModal(); - deleteValueListsFile(TEXT_LIST_FILE_NAME); + deleteValueListsFile(KNOWN_VALUE_LIST_FILES.TEXT); cy.get(VALUE_LISTS_TABLE) .find(VALUE_LISTS_ROW) .should(($row) => { - expect($row.text()).not.to.contain(TEXT_LIST_FILE_NAME); + expect($row.text()).not.to.contain(KNOWN_VALUE_LIST_FILES.TEXT); }); }); it('deletes a "text" list from an uploaded file', () => { - importValueList(TEXT_LIST_FILE_NAME, 'text'); + importValueList(KNOWN_VALUE_LIST_FILES.TEXT, 'text'); openValueListsModal(); - deleteValueListsFile(TEXT_LIST_FILE_NAME); + deleteValueListsFile(KNOWN_VALUE_LIST_FILES.TEXT); cy.get(VALUE_LISTS_TABLE) .find(VALUE_LISTS_ROW) .should(($row) => { - expect($row.text()).not.to.contain(TEXT_LIST_FILE_NAME); + expect($row.text()).not.to.contain(KNOWN_VALUE_LIST_FILES.TEXT); }); }); it('deletes a "ip" from an uploaded file', () => { - importValueList(IPS_LIST_FILE_NAME, 'ip'); + importValueList(KNOWN_VALUE_LIST_FILES.IPs, 'ip'); openValueListsModal(); - deleteValueListsFile(IPS_LIST_FILE_NAME); + deleteValueListsFile(KNOWN_VALUE_LIST_FILES.IPs); cy.get(VALUE_LISTS_TABLE) .find(VALUE_LISTS_ROW) .should(($row) => { - expect($row.text()).not.to.contain(IPS_LIST_FILE_NAME); + expect($row.text()).not.to.contain(KNOWN_VALUE_LIST_FILES.IPs); }); }); it('deletes a "ip_range" from an uploaded file', () => { - importValueList(CIDRS_LIST_FILE_NAME, 'ip_range', ['192.168.100.0']); + importValueList(KNOWN_VALUE_LIST_FILES.CIDRs, 'ip_range', ['192.168.100.0']); openValueListsModal(); - deleteValueListsFile(CIDRS_LIST_FILE_NAME); + deleteValueListsFile(KNOWN_VALUE_LIST_FILES.CIDRs); cy.get(VALUE_LISTS_TABLE) .find(VALUE_LISTS_ROW) .should(($row) => { - expect($row.text()).not.to.contain(CIDRS_LIST_FILE_NAME); + expect($row.text()).not.to.contain(KNOWN_VALUE_LIST_FILES.CIDRs); }); }); }); @@ -160,10 +165,10 @@ describe('value lists', () => { // Flaky in serverless tests describe('export list types', { tags: ['@brokenInServerless'] }, () => { it('exports a "keyword" list from an uploaded file', () => { - cy.intercept('POST', `/api/lists/items/_export?list_id=${TEXT_LIST_FILE_NAME}`).as( + cy.intercept('POST', `/api/lists/items/_export?list_id=${KNOWN_VALUE_LIST_FILES.TEXT}`).as( 'exportList' ); - importValueList(TEXT_LIST_FILE_NAME, 'keyword'); + importValueList(KNOWN_VALUE_LIST_FILES.TEXT, 'keyword'); // Importing value lists includes bulk creation of list items with refresh=wait_for // While it should wait for data update and return after that it's not always a case with bulk operations. @@ -175,7 +180,7 @@ describe('value lists', () => { exportValueList(); cy.wait('@exportList').then(({ response }) => { - cy.fixture(TEXT_LIST_FILE_NAME).then((list: string) => { + cy.fixture(KNOWN_VALUE_LIST_FILES.TEXT).then((list: string) => { const [lineOne, lineTwo] = list.split('\n'); expect(response?.body).to.contain(lineOne); expect(response?.body).to.contain(lineTwo); @@ -184,10 +189,10 @@ describe('value lists', () => { }); it('exports a "text" list from an uploaded file', () => { - cy.intercept('POST', `/api/lists/items/_export?list_id=${TEXT_LIST_FILE_NAME}`).as( + cy.intercept('POST', `/api/lists/items/_export?list_id=${KNOWN_VALUE_LIST_FILES.TEXT}`).as( 'exportList' ); - importValueList(TEXT_LIST_FILE_NAME, 'text'); + importValueList(KNOWN_VALUE_LIST_FILES.TEXT, 'text'); // Importing value lists includes bulk creation of list items with refresh=wait_for // While it should wait for data update and return after that it's not always a case with bulk operations. @@ -199,7 +204,7 @@ describe('value lists', () => { exportValueList(); cy.wait('@exportList').then(({ response }) => { - cy.fixture(TEXT_LIST_FILE_NAME).then((list: string) => { + cy.fixture(KNOWN_VALUE_LIST_FILES.TEXT).then((list: string) => { const [lineOne, lineTwo] = list.split('\n'); expect(response?.body).to.contain(lineOne); expect(response?.body).to.contain(lineTwo); @@ -208,10 +213,10 @@ describe('value lists', () => { }); it('exports a "ip" list from an uploaded file', () => { - cy.intercept('POST', `/api/lists/items/_export?list_id=${IPS_LIST_FILE_NAME}`).as( + cy.intercept('POST', `/api/lists/items/_export?list_id=${KNOWN_VALUE_LIST_FILES.IPs}`).as( 'exportList' ); - importValueList(IPS_LIST_FILE_NAME, 'ip'); + importValueList(KNOWN_VALUE_LIST_FILES.IPs, 'ip'); // Importing value lists includes bulk creation of list items with refresh=wait_for // While it should wait for data update and return after that it's not always a case with bulk operations. @@ -222,7 +227,7 @@ describe('value lists', () => { openValueListsModal(); exportValueList(); cy.wait('@exportList').then(({ response }) => { - cy.fixture(IPS_LIST_FILE_NAME).then((list: string) => { + cy.fixture(KNOWN_VALUE_LIST_FILES.IPs).then((list: string) => { const [lineOne, lineTwo] = list.split('\n'); expect(response?.body).to.contain(lineOne); expect(response?.body).to.contain(lineTwo); @@ -231,10 +236,10 @@ describe('value lists', () => { }); it('exports a "ip_range" list from an uploaded file', () => { - cy.intercept('POST', `/api/lists/items/_export?list_id=${CIDRS_LIST_FILE_NAME}`).as( + cy.intercept('POST', `/api/lists/items/_export?list_id=${KNOWN_VALUE_LIST_FILES.CIDRs}`).as( 'exportList' ); - importValueList(CIDRS_LIST_FILE_NAME, 'ip_range', ['192.168.100.0']); + importValueList(KNOWN_VALUE_LIST_FILES.CIDRs, 'ip_range', ['192.168.100.0']); // Importing value lists includes bulk creation of list items with refresh=wait_for // While it should wait for data update and return after that it's not always a case with bulk operations. @@ -245,7 +250,7 @@ describe('value lists', () => { openValueListsModal(); exportValueList(); cy.wait('@exportList').then(({ response }) => { - cy.fixture(CIDRS_LIST_FILE_NAME).then((list: string) => { + cy.fixture(KNOWN_VALUE_LIST_FILES.CIDRs).then((list: string) => { const [lineOne] = list.split('\n'); expect(response?.body).to.contain(lineOne); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts index e9c07294e62d3..3ca8b633e6564 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/endpoint_exceptions.cy.ts @@ -15,10 +15,9 @@ import { } from '../../../tasks/alerts'; import { login, visitWithoutDateRange } from '../../../tasks/login'; import { getEndpointRule } from '../../../objects/rule'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { createRule } from '../../../tasks/api_calls/rules'; import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { ruleDetailsUrl } from '../../../urls/navigation'; import { addExceptionEntryFieldValueAndSelectSuggestion, addExceptionEntryFieldValueValue, @@ -51,10 +50,12 @@ describe.skip( cy.task('esArchiverResetKibana'); login(); deleteAlertsAndRules(); + cy.task('esArchiverLoad', { archiveName: 'endpoint' }); - createRule(getEndpointRule()); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); + createRule(getEndpointRule()).then((rule) => + visitWithoutDateRange(ruleDetailsUrl(rule.body.id)) + ); + waitForTheRuleToBeExecuted(); waitForAlertsToPopulate(); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/auto_populate_with_alert_data.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/auto_populate_with_alert_data.cy.ts index 14d002b96b7b4..afd1f6c36e29b 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/auto_populate_with_alert_data.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/auto_populate_with_alert_data.cy.ts @@ -7,7 +7,6 @@ import { LOADING_INDICATOR } from '../../../../screens/security_header'; import { getEndpointRule } from '../../../../objects/rule'; import { createRule } from '../../../../tasks/api_calls/rules'; -import { goToRuleDetails } from '../../../../tasks/alerts_detection_rules'; import { addExceptionFromFirstAlert, expandFirstAlert, @@ -27,7 +26,7 @@ import { import { login, visitWithoutDateRange } from '../../../../tasks/login'; import { goToExceptionsTab } from '../../../../tasks/rule_details'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation'; +import { ruleDetailsUrl } from '../../../../urls/navigation'; import { deleteAlertsAndRules } from '../../../../tasks/common'; import { ADD_AND_BTN, @@ -52,9 +51,10 @@ describe.skip( cy.task('esArchiverResetKibana'); cy.task('esArchiverLoad', { archiveName: 'endpoint' }); login(); - createRule(getEndpointRule()); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); + createRule(getEndpointRule()).then((rule) => + visitWithoutDateRange(ruleDetailsUrl(rule.body.id)) + ); + waitForAlertsToPopulate(); }); after(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/closing_all_matching_alerts.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/closing_all_matching_alerts.cy.ts index 9c4a575dccb4e..f85e572160796 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/closing_all_matching_alerts.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/alerts_table_flow/rule_exceptions/closing_all_matching_alerts.cy.ts @@ -12,8 +12,7 @@ import { } from '../../../../tasks/alerts'; import { deleteAlertsAndRules, postDataView } from '../../../../tasks/common'; import { login, visitWithoutDateRange } from '../../../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation'; -import { goToRuleDetails } from '../../../../tasks/alerts_detection_rules'; +import { ruleDetailsUrl } from '../../../../urls/navigation'; import { createRule } from '../../../../tasks/api_calls/rules'; import { getNewRule } from '../../../../objects/rule'; import { LOADING_INDICATOR } from '../../../../screens/security_header'; @@ -29,7 +28,6 @@ import { // See https://github.com/elastic/kibana/issues/163967 describe('Close matching Alerts ', () => { - const newRule = getNewRule(); const ITEM_NAME = 'Sample Exception Item'; beforeEach(() => { @@ -40,15 +38,15 @@ describe('Close matching Alerts ', () => { login(); postDataView('exceptions-*'); - createRule({ - ...newRule, - query: 'agent.name:*', - data_view_id: 'exceptions-*', - interval: '10s', - rule_id: 'rule_testing', - }); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); + createRule( + getNewRule({ + query: 'agent.name:*', + data_view_id: 'exceptions-*', + interval: '10s', + rule_id: 'rule_testing', + }) + ).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id))); + waitForAlertsToPopulate(); }); after(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/flyout_validation.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/flyout_validation.cy.ts index e11cace87d8e8..04ef2368a7e1c 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/flyout_validation.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/flyout_validation.cy.ts @@ -10,7 +10,6 @@ import { getNewRule } from '../../../objects/rule'; import { RULE_STATUS } from '../../../screens/create_new_rule'; import { createRule } from '../../../tasks/api_calls/rules'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { login, visitWithoutDateRange } from '../../../tasks/login'; import { openExceptionFlyoutFromEmptyViewerPrompt, @@ -47,8 +46,8 @@ import { FIELD_INPUT_PARENT, } from '../../../screens/exceptions'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; -import { reload } from '../../../tasks/common'; +import { ruleDetailsUrl } from '../../../urls/navigation'; +import { deleteAlertsAndRules, reload } from '../../../tasks/common'; import { createExceptionList, createExceptionListItem, @@ -75,7 +74,11 @@ describe.skip('Exceptions flyout', { tags: ['@ess', '@serverless'] }, () => { // Comment the Conflicts here as they are skipped // cy.task('esArchiverLoad',{ archiveName: 'conflicts_1' }); // cy.task('esArchiverLoad',{ archiveName: 'conflicts_2' }); + }); + + beforeEach(() => { login(); + deleteAlertsAndRules(); createExceptionList(getExceptionList(), getExceptionList().list_id).then((response) => createRule( getNewRule({ @@ -90,18 +93,9 @@ describe.skip('Exceptions flyout', { tags: ['@ess', '@serverless'] }, () => { }, ], }) - ) + ).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'rule_exceptions'))) ); - login(); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - }); - - beforeEach(() => { - login(); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); cy.get(RULE_STATUS).should('have.text', '—'); - goToExceptionsTab(); }); after(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/multiple_conditions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/multiple_conditions.cy.ts index e1e396af156b5..2cf577d41e167 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/multiple_conditions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/multiple_conditions.cy.ts @@ -8,12 +8,8 @@ import { getNewRule } from '../../../objects/rule'; import { createRule } from '../../../tasks/api_calls/rules'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { login, visitWithoutDateRange } from '../../../tasks/login'; -import { - openExceptionFlyoutFromEmptyViewerPrompt, - goToExceptionsTab, -} from '../../../tasks/rule_details'; +import { openExceptionFlyoutFromEmptyViewerPrompt } from '../../../tasks/rule_details'; import { addExceptionFlyoutItemName, addTwoAndedConditions, @@ -26,7 +22,8 @@ import { EXCEPTION_ITEM_VIEWER_CONTAINER, } from '../../../screens/exceptions'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { ruleDetailsUrl } from '../../../urls/navigation'; +import { deleteAlertsAndRules } from '../../../tasks/common'; // FLAKY: https://github.com/elastic/kibana/issues/165651 // FLAKY: https://github.com/elastic/kibana/issues/165734 @@ -38,6 +35,7 @@ describe( beforeEach(() => { cy.task('esArchiverResetKibana'); login(); + deleteAlertsAndRules(); // At least create Rule with exceptions_list to be able to view created exceptions createRule({ ...getNewRule(), @@ -45,15 +43,13 @@ describe( index: ['exceptions*'], exceptions_list: [], rule_id: '2', - }); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); - goToExceptionsTab(); + }).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'rule_exceptions'))); }); after(() => { cy.task('esArchiverUnload', 'exceptions'); }); + const exceptionName = 'My item name'; it('Use multipe AND conditions and validate it generates one exception', () => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts index b1e2c81b4c420..0969b53d8cee6 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts @@ -12,26 +12,19 @@ import { addExceptionFlyoutItemName, submitNewExceptionItem, } from '../../../tasks/exceptions'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; -import { - goToExceptionsTab, - openExceptionFlyoutFromEmptyViewerPrompt, -} from '../../../tasks/rule_details'; -import { VALUE_LISTS_TABLE, VALUE_LISTS_ROW } from '../../../screens/lists'; +import { openExceptionFlyoutFromEmptyViewerPrompt } from '../../../tasks/rule_details'; import { getNewRule } from '../../../objects/rule'; import { cleanKibana } from '../../../tasks/common'; import { login, visitWithoutDateRange } from '../../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { DETECTIONS_RULE_MANAGEMENT_URL, ruleDetailsUrl } from '../../../urls/navigation'; import { createListsIndex, waitForListsIndex, waitForValueListsModalToBeLoaded, - selectValueListType, - selectValueListsFile, - uploadValueList, openValueListsModal, deleteValueListsFile, - closeValueListsModal, + importValueList, + KNOWN_VALUE_LIST_FILES, } from '../../../tasks/lists'; import { createRule } from '../../../tasks/api_calls/rules'; import { @@ -55,21 +48,22 @@ describe( 'Use Value list in exception entry', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { - before(() => { + beforeEach(() => { cleanKibana(); login(); - cy.task('esArchiverLoad', { archiveName: 'exceptions' }); - createRule({ - ...getNewRule(), - query: 'user.name:*', - index: ['exceptions*'], - exceptions_list: [], - rule_id: '2', - }); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - }); - beforeEach(() => { createListsIndex(); + cy.task('esArchiverLoad', { archiveName: 'exceptions' }); + importValueList(KNOWN_VALUE_LIST_FILES.TEXT, 'keyword'); + + createRule( + getNewRule({ + query: 'user.name:*', + index: ['exceptions*'], + exceptions_list: [], + rule_id: '2', + enabled: false, + }) + ).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'rule_exceptions'))); }); afterEach(() => { @@ -80,24 +74,6 @@ describe( const ITEM_NAME = 'Exception item with value list'; const ITEM_FIELD = 'agent.name'; - goToRulesAndOpenValueListModal(); - - // Add new value list of type keyword - const listName = 'value_list.txt'; - selectValueListType('keyword'); - selectValueListsFile(listName); - uploadValueList(); - - cy.get(VALUE_LISTS_TABLE) - .find(VALUE_LISTS_ROW) - .should(($row) => { - expect($row.text()).to.contain(listName); - expect($row.text()).to.contain('Keywords'); - }); - closeValueListsModal(); - goToRuleDetails(); - goToExceptionsTab(); - // open add exception modal openExceptionFlyoutFromEmptyViewerPrompt(); @@ -107,7 +83,7 @@ describe( addExceptionEntryFieldValue(ITEM_FIELD, 0); addExceptionEntryOperatorValue('is in list', 0); - addExceptionEntryFieldMatchIncludedValue('value_list.txt', 0); + addExceptionEntryFieldMatchIncludedValue(KNOWN_VALUE_LIST_FILES.TEXT, 0); // The Close all alerts that match attributes in this exception option is disabled cy.get(CLOSE_ALERTS_CHECKBOX).should('exist'); @@ -128,7 +104,7 @@ describe( // Go back to value list to delete the existing one goToRulesAndOpenValueListModal(); - deleteValueListsFile(listName); + deleteValueListsFile(KNOWN_VALUE_LIST_FILES.TEXT); // Toast should be shown because of exception reference cy.get(EXCEPTIONS_TABLE_MODAL).should('exist'); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts index f3b84ebb98f7a..170530f8c8045 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts @@ -8,13 +8,12 @@ import { getNewRule } from '../../../objects/rule'; import { createRule } from '../../../tasks/api_calls/rules'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { login, visitWithoutDateRange } from '../../../tasks/login'; import { - goToEndpointExceptionsTab, openEditException, openExceptionFlyoutFromEmptyViewerPrompt, searchForExceptionItem, + waitForPageToBeLoaded as waitForRuleDetailsPageToBeLoaded, } from '../../../tasks/rule_details'; import { addExceptionConditions, @@ -26,7 +25,7 @@ import { submitNewExceptionItem, } from '../../../tasks/exceptions'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { ruleDetailsUrl } from '../../../urls/navigation'; import { deleteAlertsAndRules } from '../../../tasks/common'; import { NO_EXCEPTIONS_EXIST_PROMPT, @@ -42,156 +41,190 @@ import { EXCEPTION_CARD_ITEM_CONDITIONS, FIELD_INPUT_PARENT, } from '../../../screens/exceptions'; -import { createEndpointExceptionList } from '../../../tasks/api_calls/exceptions'; +import { + createEndpointExceptionList, + createEndpointExceptionListItem, +} from '../../../tasks/api_calls/exceptions'; // FLAKY: https://github.com/elastic/kibana/issues/165736 describe( 'Add endpoint exception from rule details', - { tags: ['@ess', '@serverless', '@brokenInServerless'] }, + { tags: ['@ess', '@brokenInServerless'] }, () => { const ITEM_NAME = 'Sample Exception List Item'; + const NEW_ITEM_NAME = 'Exception item-EDITED'; + const ITEM_FIELD = 'event.code'; + const FIELD_DIFFERENT_FROM_EXISTING_ITEM_FIELD = 'agent.type'; - before(() => { + beforeEach(() => { cy.task('esArchiverResetKibana'); cy.task('esArchiverLoad', { archiveName: 'auditbeat' }); login(); deleteAlertsAndRules(); - // create rule with exception - createEndpointExceptionList<{ - id: string; - list_id: string; - type: - | 'detection' - | 'rule_default' - | 'endpoint' - | 'endpoint_trusted_apps' - | 'endpoint_events' - | 'endpoint_host_isolation_exceptions' - | 'endpoint_blocklists'; - namespace_type: 'agnostic' | 'single'; - }>().then((response) => { - createRule( - getNewRule({ - query: 'event.code:*', - index: ['auditbeat*'], - exceptions_list: [ - { - id: response.body.id, - list_id: response.body.list_id, - type: response.body.type, - namespace_type: response.body.namespace_type, - }, - ], - rule_id: '2', - }) - ); - }); }); - beforeEach(() => { - login(); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); - goToEndpointExceptionsTab(); - }); - - after(() => { + afterEach(() => { cy.task('esArchiverUnload', 'auditbeat'); }); - it('creates an exception item', () => { - // when no exceptions exist, empty component shows with action to add exception - cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist'); + describe('without exception items', () => { + beforeEach(() => { + createEndpointExceptionList().then((response) => { + createRule( + getNewRule({ + query: 'event.code:*', + index: ['auditbeat*'], + exceptions_list: [ + { + id: response.body.id, + list_id: response.body.list_id, + type: response.body.type, + namespace_type: response.body.namespace_type, + }, + ], + rule_id: '2', + enabled: false, + }) + ).then((rule) => + visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'endpoint_exceptions')) + ); + }); + }); - // open add exception modal - openExceptionFlyoutFromEmptyViewerPrompt(); + it('creates an exception item', () => { + // when no exceptions exist, empty component shows with action to add exception + cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist'); - // submit button is disabled if no paramerters were added - cy.get(CONFIRM_BTN).should('have.attr', 'disabled'); + // open add exception modal + openExceptionFlyoutFromEmptyViewerPrompt(); - // for endpoint exceptions, must specify OS - selectOs('windows'); + // submit button is disabled if no paramerters were added + cy.get(CONFIRM_BTN).should('have.attr', 'disabled'); - // add exception item conditions - addExceptionConditions({ - field: 'event.code', - operator: 'is', - values: ['foo'], - }); + // for endpoint exceptions, must specify OS + selectOs('windows'); + + // add exception item conditions + addExceptionConditions({ + field: 'event.code', + operator: 'is', + values: ['foo'], + }); - // Name is required so want to check that submit is still disabled - cy.get(CONFIRM_BTN).should('have.attr', 'disabled'); + // Name is required so want to check that submit is still disabled + cy.get(CONFIRM_BTN).should('have.attr', 'disabled'); - // add exception item name - addExceptionFlyoutItemName(ITEM_NAME); + // add exception item name + addExceptionFlyoutItemName(ITEM_NAME); - // Option to add to rule or add to list should NOT appear - cy.get(ADD_TO_RULE_OR_LIST_SECTION).should('not.exist'); + // Option to add to rule or add to list should NOT appear + cy.get(ADD_TO_RULE_OR_LIST_SECTION).should('not.exist'); - // not testing close alert functionality here, just ensuring that the options appear as expected - cy.get(CLOSE_SINGLE_ALERT_CHECKBOX).should('not.exist'); - cy.get(CLOSE_ALERTS_CHECKBOX).should('exist'); + // not testing close alert functionality here, just ensuring that the options appear as expected + cy.get(CLOSE_SINGLE_ALERT_CHECKBOX).should('not.exist'); + cy.get(CLOSE_ALERTS_CHECKBOX).should('exist'); - // submit - submitNewExceptionItem(); + // submit + submitNewExceptionItem(); - // new exception item displays - cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + // new exception item displays + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + }); }); - it('edits an endpoint exception item', () => { - const NEW_ITEM_NAME = 'Exception item-EDITED'; - const ITEM_FIELD = 'event.code'; - const FIELD_DIFFERENT_FROM_EXISTING_ITEM_FIELD = 'agent.type'; + describe('with exception items', () => { + beforeEach(() => { + createEndpointExceptionList().then((response) => { + createEndpointExceptionListItem({ + comments: [], + description: 'Exception list item', + entries: [ + { + field: ITEM_FIELD, + operator: 'included', + type: 'match', + value: 'foo', + }, + ], + name: ITEM_NAME, + tags: [], + type: 'simple', + os_types: ['windows'], + }); + + createRule( + getNewRule({ + name: 'Rule with exceptions', + query: 'event.code:*', + index: ['auditbeat*'], + exceptions_list: [ + { + id: response.body.id, + list_id: response.body.list_id, + type: response.body.type, + namespace_type: response.body.namespace_type, + }, + ], + rule_id: '2', + enabled: false, + }) + ).then((rule) => { + visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'endpoint_exceptions')); + waitForRuleDetailsPageToBeLoaded('Rule with exceptions'); + }); + }); + }); - // displays existing exception items - cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); - cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist'); - cy.get(EXCEPTION_CARD_ITEM_NAME).should('have.text', ITEM_NAME); - cy.get(EXCEPTION_CARD_ITEM_CONDITIONS).should('have.text', ` ${ITEM_FIELD}IS foo`); + it('edits an endpoint exception item', () => { + // displays existing exception items + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist'); + cy.get(EXCEPTION_CARD_ITEM_NAME).should('have.text', ITEM_NAME); + cy.get(EXCEPTION_CARD_ITEM_CONDITIONS).should('have.text', ` ${ITEM_FIELD}IS foo`); - // open edit exception modal - openEditException(); + // open edit exception modal + openEditException(); - // edit exception item name - editExceptionFlyoutItemName(NEW_ITEM_NAME); + // edit exception item name + editExceptionFlyoutItemName(NEW_ITEM_NAME); - // check that the existing item's field is being populated - cy.get(EXCEPTION_ITEM_CONTAINER) - .eq(0) - .find(FIELD_INPUT_PARENT) - .eq(0) - .should('have.text', ITEM_FIELD); - cy.get(VALUES_INPUT).should('have.text', 'foo'); + // check that the existing item's field is being populated + cy.get(EXCEPTION_ITEM_CONTAINER) + .eq(0) + .find(FIELD_INPUT_PARENT) + .eq(0) + .should('have.text', ITEM_FIELD); + cy.get(VALUES_INPUT).should('have.text', 'foo'); - // edit conditions - editException(FIELD_DIFFERENT_FROM_EXISTING_ITEM_FIELD, 0, 0); + // edit conditions + editException(FIELD_DIFFERENT_FROM_EXISTING_ITEM_FIELD, 0, 0); - // submit - submitEditedExceptionItem(); + // submit + submitEditedExceptionItem(); - // new exception item displays - cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + // new exception item displays + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); - // check that updates stuck - cy.get(EXCEPTION_CARD_ITEM_NAME).should('have.text', NEW_ITEM_NAME); - cy.get(EXCEPTION_CARD_ITEM_CONDITIONS).should('have.text', ' agent.typeIS foo'); - }); + // check that updates stuck + cy.get(EXCEPTION_CARD_ITEM_NAME).should('have.text', NEW_ITEM_NAME); + cy.get(EXCEPTION_CARD_ITEM_CONDITIONS).should('have.text', ' agent.typeIS foo'); + }); - it('allows user to search for items', () => { - cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + it('allows user to search for items', () => { + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); - // can search for an exception value - searchForExceptionItem('foo'); + // can search for an exception value + searchForExceptionItem('foo'); - // new exception item displays - cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + // new exception item displays + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); - // displays empty search result view if no matches found - searchForExceptionItem('abc'); + // displays empty search result view if no matches found + searchForExceptionItem('abc'); - // new exception item displays - cy.get(NO_EXCEPTIONS_SEARCH_RESULTS_PROMPT).should('exist'); + // new exception item displays + cy.get(NO_EXCEPTIONS_SEARCH_RESULTS_PROMPT).should('exist'); + }); }); } ); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception.cy.ts index 18537145ec582..11f5a58679404 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception.cy.ts @@ -10,7 +10,6 @@ import { getNewRule } from '../../../objects/rule'; import { ALERTS_COUNT, EMPTY_ALERT_TABLE } from '../../../screens/alerts'; import { createRule } from '../../../tasks/api_calls/rules'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { goToClosedAlertsOnRuleDetailsPage, goToOpenedAlertsOnRuleDetailsPage, @@ -37,7 +36,7 @@ import { submitEditedExceptionItem, submitNewExceptionItem, } from '../../../tasks/exceptions'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { ruleDetailsUrl } from '../../../urls/navigation'; import { deleteAlertsAndRules } from '../../../tasks/common'; import { NO_EXCEPTIONS_EXIST_PROMPT, @@ -67,35 +66,25 @@ describe('Add/edit exception from rule details', { tags: ['@ess', '@brokenInServ before(() => { cy.task('esArchiverResetKibana'); cy.task('esArchiverLoad', { archiveName: 'exceptions' }); - login(); }); after(() => { cy.task('esArchiverUnload', 'exceptions'); }); + beforeEach(() => { + login(); + deleteAlertsAndRules(); + + const exceptionList = getExceptionList(); + deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type); + }); + describe('existing list and items', () => { const exceptionList = getExceptionList(); beforeEach(() => { - deleteAlertsAndRules(); - deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type); // create rule with exceptions createExceptionList(exceptionList, exceptionList.list_id).then((response) => { - createRule( - getNewRule({ - query: 'agent.name:*', - index: ['exceptions*'], - exceptions_list: [ - { - id: response.body.id, - list_id: exceptionList.list_id, - type: exceptionList.type, - namespace_type: exceptionList.namespace_type, - }, - ], - rule_id: '2', - }) - ); createExceptionListItem(exceptionList.list_id, { list_id: exceptionList.list_id, item_id: 'simple_list_item', @@ -113,12 +102,23 @@ describe('Add/edit exception from rule details', { tags: ['@ess', '@brokenInServ }, ], }); - }); - login(); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); - goToExceptionsTab(); + createRule( + getNewRule({ + query: 'agent.name:*', + index: ['exceptions*'], + exceptions_list: [ + { + id: response.body.id, + list_id: exceptionList.list_id, + type: exceptionList.type, + namespace_type: exceptionList.namespace_type, + }, + ], + rule_id: '2', + }) + ).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'rule_exceptions'))); + }); }); it('Edits an exception item', () => { @@ -245,7 +245,6 @@ describe('Add/edit exception from rule details', { tags: ['@ess', '@brokenInServ describe('rule without existing exceptions', () => { beforeEach(() => { - deleteAlertsAndRules(); createRule( getNewRule({ query: 'agent.name:*', @@ -253,11 +252,7 @@ describe('Add/edit exception from rule details', { tags: ['@ess', '@brokenInServ interval: '10s', rule_id: 'rule_testing', }) - ); - login(); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); - goToExceptionsTab(); + ).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'rule_exceptions'))); }); afterEach(() => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception_data_view.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception_data_view.cy.ts index 229cfce25b9fa..a1e3e17db597f 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception_data_view.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/add_edit_exception_data_view.cy.ts @@ -8,7 +8,6 @@ import { getNewRule } from '../../../objects/rule'; import { ALERTS_COUNT, EMPTY_ALERT_TABLE } from '../../../screens/alerts'; import { createRule } from '../../../tasks/api_calls/rules'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { goToClosedAlertsOnRuleDetailsPage, goToOpenedAlertsOnRuleDetailsPage, @@ -28,7 +27,7 @@ import { waitForTheRuleToBeExecuted, } from '../../../tasks/rule_details'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { ruleDetailsUrl } from '../../../urls/navigation'; import { postDataView, deleteAlertsAndRules } from '../../../tasks/common'; import { NO_EXCEPTIONS_EXIST_PROMPT, @@ -60,6 +59,7 @@ describe( }); beforeEach(() => { + login(); deleteAlertsAndRules(); createRule( getNewRule({ @@ -68,10 +68,7 @@ describe( interval: '10s', rule_id: 'rule_testing', }) - ); - login(); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); + ).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id))); waitForAlertsToPopulate(); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/read_only_view.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/read_only_view.cy.ts index 6ecb3c1e40602..d6e5637e17379 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/read_only_view.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/rule_details_flow/read_only_view.cy.ts @@ -11,7 +11,7 @@ import { getNewRule } from '../../../objects/rule'; import { createRule } from '../../../tasks/api_calls/rules'; import { login, visitSecurityDetectionRulesPage } from '../../../tasks/login'; import { goToExceptionsTab, goToAlertsTab } from '../../../tasks/rule_details'; -import { goToTheRuleDetailsOf } from '../../../tasks/alerts_detection_rules'; +import { goToRuleDetailsOf } from '../../../tasks/alerts_detection_rules'; import { deleteAlertsAndRules } from '../../../tasks/common'; import { NO_EXCEPTIONS_EXIST_PROMPT, @@ -55,7 +55,7 @@ describe('Exceptions viewer read only', { tags: '@ess' }, () => { login(ROLES.reader); visitSecurityDetectionRulesPage(ROLES.reader); - goToTheRuleDetailsOf('Test exceptions rule'); + goToRuleDetailsOf('Test exceptions rule'); goToExceptionsTab(); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts index e0f932d81ac88..c5cf8a5de9421 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import type { RuleResponse } from '@kbn/security-solution-plugin/common/api/detection_engine'; import { getNewRule } from '../../../objects/rule'; import { login, visitWithoutDateRange } from '../../../tasks/login'; import { createRule } from '../../../tasks/api_calls/rules'; @@ -19,7 +20,7 @@ import { submitNewExceptionItem, deleteFirstExceptionItemInListDetailPage, } from '../../../tasks/exceptions'; -import { DETECTIONS_RULE_MANAGEMENT_URL, EXCEPTIONS_URL } from '../../../urls/navigation'; +import { EXCEPTIONS_URL, ruleDetailsUrl } from '../../../urls/navigation'; import { CONFIRM_BTN, @@ -29,8 +30,6 @@ import { EXECPTION_ITEM_CARD_HEADER_TITLE, EMPTY_EXCEPTIONS_VIEWER, } from '../../../screens/exceptions'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; -import { goToExceptionsTab } from '../../../tasks/rule_details'; import { addExceptionListFromSharedExceptionListHeaderMenu, createSharedExceptionList, @@ -43,19 +42,17 @@ describe( 'Add, edit and delete exception', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { - before(() => { + beforeEach(() => { cy.task('esArchiverResetKibana'); cy.task('esArchiverLoad', { archiveName: 'exceptions' }); + createRule(getNewRule()).as('createdRule'); - createRule(getNewRule()); - }); - - beforeEach(() => { login(); visitWithoutDateRange(EXCEPTIONS_URL); waitForExceptionsTableToBeLoaded(); }); - after(() => { + + afterEach(() => { cy.task('esArchiverUnload', 'exceptions'); }); @@ -87,11 +84,10 @@ describe( submitNewExceptionItem(); - // Navigate to Rule page - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); - - goToExceptionsTab(); + // Navigate to Rule details page + cy.get>('@createdRule').then((rule) => + visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'rule_exceptions')) + ); // Only one Exception should generated cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts index 1604d1fdbe692..de204fd08f62e 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts @@ -29,12 +29,12 @@ import { cleanKibana } from '../../../tasks/common'; import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; import { login, visit, visitWithoutDateRange } from '../../../tasks/login'; import { getNewRule, getUnmappedRule } from '../../../objects/rule'; -import { ALERTS_URL } from '../../../urls/navigation'; +import { ALERTS_URL, ruleDetailsUrl } from '../../../urls/navigation'; import { tablePageSelector } from '../../../screens/table_pagination'; import { ALERTS_TABLE_COUNT } from '../../../screens/timeline'; import { ALERT_SUMMARY_SEVERITY_DONUT_CHART } from '../../../screens/alerts'; import { getLocalstorageEntryAsObject } from '../../../helpers/common'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { waitForPageToBeLoaded as waitForRuleDetailsPageToBeLoaded } from '../../../tasks/rule_details'; describe('Alert details flyout', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { describe('Basic functions', () => { @@ -179,8 +179,13 @@ describe('Alert details flyout', { tags: ['@ess', '@serverless', '@brokenInServe }); describe('Localstorage management', () => { + const ARCHIVED_RULE_ID = '7015a3e2-e4ea-11ed-8c11-49608884878f'; + const ARCHIVED_RULE_NAME = 'Endpoint Security'; + before(() => { cleanKibana(); + + // It just imports an alert without a rule but rule details page should work anyway cy.task('esArchiverLoad', { archiveName: 'query_alert', useCreate: true, docsOnly: true }); }); @@ -230,7 +235,10 @@ describe('Alert details flyout', { tags: ['@ess', '@serverless', '@brokenInServe it('should remove the flyout state from localstorage when navigating away without closing the flyout', () => { cy.get(OVERVIEW_RULE).should('be.visible'); - goToRuleDetails(); + + visitWithoutDateRange(ruleDetailsUrl(ARCHIVED_RULE_ID)); + waitForRuleDetailsPageToBeLoaded(ARCHIVED_RULE_NAME); + const localStorageCheck = () => cy.getAllLocalStorage().then((storage) => { const securityDataTable = getLocalstorageEntryAsObject(storage, 'securityDataTable'); @@ -242,7 +250,10 @@ describe('Alert details flyout', { tags: ['@ess', '@serverless', '@brokenInServe it('should not reopen the flyout when navigating away from the alerts page and returning to it', () => { cy.get(OVERVIEW_RULE).should('be.visible'); - goToRuleDetails(); + + visitWithoutDateRange(ruleDetailsUrl(ARCHIVED_RULE_ID)); + waitForRuleDetailsPageToBeLoaded(ARCHIVED_RULE_NAME); + visit(ALERTS_URL); cy.get(OVERVIEW_RULE).should('not.exist'); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts index d57ab19a0f4fe..6b869268fa15b 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/building_block_alerts.cy.ts @@ -9,14 +9,13 @@ import { getBuildingBlockRule } from '../../../objects/rule'; import { OVERVIEW_ALERTS_HISTOGRAM_EMPTY } from '../../../screens/overview'; import { HIGHLIGHTED_ROWS_IN_TABLE } from '../../../screens/rule_details'; import { OVERVIEW } from '../../../screens/security_header'; -import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { createRule } from '../../../tasks/api_calls/rules'; import { cleanKibana } from '../../../tasks/common'; import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; import { login, visitWithoutDateRange } from '../../../tasks/login'; import { waitForTheRuleToBeExecuted } from '../../../tasks/rule_details'; import { navigateFromHeaderTo } from '../../../tasks/security_header'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { ruleDetailsUrl } from '../../../urls/navigation'; const EXPECTED_NUMBER_OF_ALERTS = 5; @@ -26,19 +25,21 @@ describe( () => { before(() => { cy.task('esArchiverLoad', { archiveName: 'auditbeat_big' }); - cleanKibana(); - login(); - }); - beforeEach(() => { - createRule(getBuildingBlockRule()); }); + after(() => { cy.task('esArchiverUnload', 'auditbeat_big'); }); + beforeEach(() => { + cleanKibana(); + login(); + createRule(getBuildingBlockRule()).then((rule) => + visitWithoutDateRange(ruleDetailsUrl(rule.body.id)) + ); + }); + it('Alerts should be visible on the Rule Detail page and not visible on the Overview page', () => { - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); waitForTheRuleToBeExecuted(); // Check that generated events are visible on the Details page diff --git a/x-pack/test/security_solution_cypress/cypress/objects/rule.ts b/x-pack/test/security_solution_cypress/cypress/objects/rule.ts index 586a4188b84b1..13ff441e64ee5 100644 --- a/x-pack/test/security_solution_cypress/cypress/objects/rule.ts +++ b/x-pack/test/security_solution_cypress/cypress/objects/rule.ts @@ -491,8 +491,6 @@ export const indicatorRuleMatchingDoc = { matchedIndex: 'logs-ti_abusech.malware', }; -export const duplicatedRuleName = `${getNewThreatIndicatorRule().name} [Duplicate]`; - export const getSeveritiesOverride = (): string[] => ['Low', 'Medium', 'High', 'Critical']; export const getEditedRule = (): QueryRuleCreateProps => diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts b/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts index 5f66f5513ed17..cb920e8093be1 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { duplicatedRuleName } from '../objects/rule'; import { COLLAPSED_ACTION_BTN, CUSTOM_RULES_BTN, @@ -107,8 +106,8 @@ export const duplicateRuleFromMenu = () => { * Check that the duplicated rule is on the table * and it is disabled (default) */ -export const checkDuplicatedRule = () => { - cy.contains(RULE_NAME, duplicatedRuleName) +export const checkDuplicatedRule = (ruleName: string): void => { + cy.contains(RULE_NAME, ruleName) .parents(RULES_ROW) .find(RULE_SWITCH) .should('have.attr', 'aria-checked', 'false'); @@ -193,14 +192,7 @@ export const filterByDisabledRules = () => { cy.get(DISABLED_RULES_BTN).click(); }; -/** - * @deprecated use goToTheRuleDetailsOf - */ -export const goToRuleDetails = () => { - cy.get(RULE_NAME).first().click(); -}; - -export const goToTheRuleDetailsOf = (ruleName: string) => { +export const goToRuleDetailsOf = (ruleName: string) => { cy.contains(RULE_NAME, ruleName).click(); cy.get(PAGE_CONTENT_SPINNER).should('be.visible'); @@ -502,7 +494,7 @@ export const closeErrorToast = () => { }; export const goToEditRuleActionsSettingsOf = (name: string) => { - goToTheRuleDetailsOf(name); + goToRuleDetailsOf(name); goToRuleEditSettings(); // wait until first step loads completely. Otherwise cypress stuck at the first edit page cy.get(EDIT_SUBMIT_BUTTON).should('be.enabled'); diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/exceptions.ts b/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/exceptions.ts index 622e311fa0fd1..2d5bf00b3c381 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/exceptions.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/exceptions.ts @@ -5,19 +5,29 @@ * 2.0. */ +import { CreateEndpointListItemResponse } from '@kbn/lists-plugin/common/api'; import type { ExceptionListSchema, ExceptionListItemSchema, + CreateEndpointListItemSchema, } from '@kbn/securitysolution-io-ts-list-types'; +import { ENDPOINT_LIST_ITEM_URL, ENDPOINT_LIST_URL } from '@kbn/securitysolution-list-constants'; import type { ExceptionList, ExceptionListItem, RuleExceptionItem } from '../../objects/exception'; import { rootRequest } from '../common'; -export const createEndpointExceptionList = () => - rootRequest({ +export const createEndpointExceptionList = () => + rootRequest({ method: 'POST', - url: '/api/endpoint_list', + url: ENDPOINT_LIST_URL, + headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' }, + }); + +export const createEndpointExceptionListItem = (item: CreateEndpointListItemSchema) => + rootRequest({ + method: 'POST', + url: ENDPOINT_LIST_ITEM_URL, + body: item, headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' }, - failOnStatusCode: false, }); export const createExceptionList = ( diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/lists.ts b/x-pack/test/security_solution_cypress/cypress/tasks/lists.ts index e9dd3d882b429..fcae40e1e8549 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/lists.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/lists.ts @@ -15,6 +15,12 @@ import { VALUE_LIST_TYPE_SELECTOR, } from '../screens/lists'; +export const KNOWN_VALUE_LIST_FILES = { + TEXT: 'value_list.txt', + IPs: 'ip_list.txt', + CIDRs: 'cidr_list.txt', +}; + export const createListsIndex = () => { cy.request({ method: 'POST', diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/rule_details.ts b/x-pack/test/security_solution_cypress/cypress/tasks/rule_details.ts index 871cbcb82ab7a..b18905b443679 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/rule_details.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/rule_details.ts @@ -106,8 +106,8 @@ export const goToEndpointExceptionsTab = () => { }; export const openEditException = (index = 0) => { - cy.get(EXCEPTION_ITEM_ACTIONS_BUTTON).eq(index).click({ force: true }); - cy.get(EDIT_EXCEPTION_BTN).eq(index).click({ force: true }); + cy.get(EXCEPTION_ITEM_ACTIONS_BUTTON).eq(index).click(); + cy.get(EDIT_EXCEPTION_BTN).eq(index).click(); }; export const removeException = () => { diff --git a/x-pack/test/security_solution_cypress/cypress/tsconfig.json b/x-pack/test/security_solution_cypress/cypress/tsconfig.json index ff1d9c7551f75..e24946f40a3ff 100644 --- a/x-pack/test/security_solution_cypress/cypress/tsconfig.json +++ b/x-pack/test/security_solution_cypress/cypress/tsconfig.json @@ -1,21 +1,10 @@ { "extends": "../../../../tsconfig.base.json", - "include": [ - "**/*", - "fixtures/**/*.json" - ], - "exclude": [ - "target/**/*" - ], + "include": ["**/*", "fixtures/**/*.json"], + "exclude": ["target/**/*"], "compilerOptions": { "outDir": "target/types", - "types": [ - "cypress", - "cypress-file-upload", - "cypress-real-events", - "cypress-recurse", - "node", - ], + "types": ["cypress", "cypress-file-upload", "cypress-real-events", "cypress-recurse", "node"] }, "kbn_references": [ "@kbn/securitysolution-io-ts-alerting-types", @@ -46,5 +35,7 @@ "@kbn/dev-utils", "@kbn/expandable-flyout", "@kbn/config-schema", + "@kbn/lists-plugin", + "@kbn/securitysolution-list-constants" ] } diff --git a/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts b/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts index aa13d43a23ab6..eca48ae6fafff 100644 --- a/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts +++ b/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts @@ -57,7 +57,10 @@ export const DISCOVER_WITH_FILTER_URL = export const DISCOVER_WITH_PINNED_FILTER_URL = "/app/discover#/?_g=(filters:!(('$state':(store:globalState),meta:(alias:!n,disabled:!f,index:security-solution-default,key:host.name,negate:!f,params:(query:test-host),type:phrase),query:(match_phrase:(host.name:test-host)))),refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(columns:!(),filters:!(),index:security-solution-default,interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))"; -export const ruleDetailsUrl = (ruleId: string) => `app/security/rules/id/${ruleId}`; +export const ruleDetailsUrl = ( + ruleId: string, + section?: 'alerts' | 'rule_exceptions' | 'endpoint_exceptions' | 'execution_results' +) => `app/security/rules/id/${ruleId}${section ? `/${section}` : ''}`; export const detectionsRuleDetailsUrl = (ruleId: string) => `app/security/detections/rules/id/${ruleId}`;