Skip to content

Commit

Permalink
[8.9] [Security Solution] [Detection Engine] Fix rule_exception cyp…
Browse files Browse the repository at this point in the history
…ress test flakiness (#161751) (#163688)

# Backport

This will backport the following commits from `main` to `8.9`:
- [[Security Solution] [Detection Engine] Fix `rule_exception` cypress
test flakiness (#161751)](#161751)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Wafaa
Nasr","email":"[email protected]"},"sourceCommit":{"committedDate":"2023-08-01T11:28:46Z","message":"[Security
Solution] [Detection Engine] Fix `rule_exception` cypress test flakiness
(#161751)\n\n## Summary\r\n\r\n- Fixes
#159341 \r\n\r\n**Steps to
insure the flakiness** \r\n\r\n- Run the test through Flaky test runner
by modifying the\r\n`x-pack/plugins/security_solution/package.json` to
only run the\r\n`Rule_exceptions` as the following
=>\r\n`./cypress/e2e/exceptions/**/rule_exception.cy.ts`\r\n- Run the
test locally multiple times by wrapping the test suite by \r\n
`Cypress._.times(50, () => {});`\r\n\r\n**Failing steps**\r\n\r\n- The
test only failed in the step mentioned when executed through
the\r\nFlaky test runner.\r\n\r\n```\r\n 1) Rule Exceptions workflows
from Alert\r\n --\r\n | Should create a Rule exception item from the
alert actions overflow menu and close all matching alerts:\r\n |
AssertionError: Timed out retrying after 150000ms: Expected to find
element: `[data-test-subj=\"alertsStateTableEmptyState\"]`, but never
found it.\r\n```\r\n\r\n- By executing it locally multiple times, the
test failed at different\r\nsteps on each occasion.\r\n \r\n-
Immediately after creating an Exception with the Closing all
matching\r\nalerts option, the Alert table was not found empty,
indicating
a\r\nfailure.\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/492aa552-f721-493b-b0b7-fa3e91dc4e63)\r\n\r\n-
After removing the exception, the expected number of alerts was
not\r\nfound in the Alerts table, resulting in a
failure.\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/c291d630-8775-4a5b-9a6b-feb30a169757)\r\n\r\n-
Unrelated to this test, but concerning exceptions, the
failure\r\noccurred when attempting to click on \"Submit exception\" due
to an error\r\ntoast obstructing the button, similar to the 2nd
screenshot
provided\r\nbelow.\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/d117df13-d521-4ead-8a71-e7a6bd1585d8)\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/758cbb3e-9b95-439a-a5d1-49de8d84518e)\r\n\r\n**Steps
to mitigate test flakiness:**\r\n\r\n- **Splitting Test Cases:** The
rule_exceptions test currently covers\r\nmultiple areas using different
Rule types. To improve stability, we\r\nshould divide it into separate
test files. For example,\r\n`closing_all_matching_alerts.cy.ts`
and\r\n`auto_populate_with_alert_data.cy.ts`. Additionally, we should
ensure\r\nthat each test file cleans up any previous data to maintain
test\r\nisolation.\r\n\r\n- **Handling Async Calls:** Test flakiness can
occur when Cypress\r\nexecutes faster than async calls, leading to
errors when alerts don't\r\nmove to the closed tab in time. To address
this, we should avoid\r\nimmediate validation after creating an
exception. Instead, refresh the\r\n`Alerts table` to allow time for the
alerts to be moved to the\r\nappropriate tab before asserting the
conditions.\r\n\r\n For example ` waitForAlerts();` method\r\n\r\n-
**Avoiding Specific Alert Counts:** Relying on a specific number
of\r\ngenerated or closed alerts for validation is not a robust
approach.\r\nDuring test execution, the Rule might generate more alerts
than\r\nexpected, leading to test failures. To overcome this, we should
focus on\r\nvalidating the expected behavior rather than a fixed alert
count.\r\n \r\n For example\r\n ```\r\n
goToClosedAlertsOnRuleDetailsPage(); \r\n
cy.get(ALERTS_COUNT).should('exist');\r\n ```\r\n\r\n- In the test, when
utilizing `cy.task('esArchiverLoad',\r\n'exceptions');`, it can be
beneficial to check if the exception list is\r\nnot present in the
environment by calling `cy.task('esArchiverUnload',\r\n'exceptions');`
beforehand. This cleanup step ensures that any existing\r\nexception
list is removed, mitigating the occurrence of the following\r\nerror:
`resource_already_exists_exception:
index\r\n[.lists-default-000001/U_3_TShzRY-WZD_XqhSBnw] already exists
(400).`\r\n\r\n- It does not provide a value at the end of
the\r\n`closing_all_matching_alerts.cy.ts` test to verify if alerts
are\r\ngenerated again after the `Exception` that closes all matching
alerts is\r\ndeleted because the test already begins with the rule
generating alerts\r\nuntil the exception is created. Therefore, this
part has been excluded.\r\n\r\nBy following these steps for the test,
running the new files multiple\r\ntimes locally proved to be
beneficial:\r\n\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/8a0250a0-274f-442b-b94c-86e4c815afd1)\r\n
successfully
\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/4e9562f3-506e-4f13-ab1f-c084d2613eb8)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"8f8c51a2d6c960007a9dc5f8fb4abd9fad7ec5aa","branchLabelMapping":{"^v8.10.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","test-failure-flaky","backport:prev-minor","Team:Detection
Engine","v8.10.0"],"number":161751,"url":"https://github.com/elastic/kibana/pull/161751","mergeCommit":{"message":"[Security
Solution] [Detection Engine] Fix `rule_exception` cypress test flakiness
(#161751)\n\n## Summary\r\n\r\n- Fixes
#159341 \r\n\r\n**Steps to
insure the flakiness** \r\n\r\n- Run the test through Flaky test runner
by modifying the\r\n`x-pack/plugins/security_solution/package.json` to
only run the\r\n`Rule_exceptions` as the following
=>\r\n`./cypress/e2e/exceptions/**/rule_exception.cy.ts`\r\n- Run the
test locally multiple times by wrapping the test suite by \r\n
`Cypress._.times(50, () => {});`\r\n\r\n**Failing steps**\r\n\r\n- The
test only failed in the step mentioned when executed through
the\r\nFlaky test runner.\r\n\r\n```\r\n 1) Rule Exceptions workflows
from Alert\r\n --\r\n | Should create a Rule exception item from the
alert actions overflow menu and close all matching alerts:\r\n |
AssertionError: Timed out retrying after 150000ms: Expected to find
element: `[data-test-subj=\"alertsStateTableEmptyState\"]`, but never
found it.\r\n```\r\n\r\n- By executing it locally multiple times, the
test failed at different\r\nsteps on each occasion.\r\n \r\n-
Immediately after creating an Exception with the Closing all
matching\r\nalerts option, the Alert table was not found empty,
indicating
a\r\nfailure.\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/492aa552-f721-493b-b0b7-fa3e91dc4e63)\r\n\r\n-
After removing the exception, the expected number of alerts was
not\r\nfound in the Alerts table, resulting in a
failure.\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/c291d630-8775-4a5b-9a6b-feb30a169757)\r\n\r\n-
Unrelated to this test, but concerning exceptions, the
failure\r\noccurred when attempting to click on \"Submit exception\" due
to an error\r\ntoast obstructing the button, similar to the 2nd
screenshot
provided\r\nbelow.\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/d117df13-d521-4ead-8a71-e7a6bd1585d8)\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/758cbb3e-9b95-439a-a5d1-49de8d84518e)\r\n\r\n**Steps
to mitigate test flakiness:**\r\n\r\n- **Splitting Test Cases:** The
rule_exceptions test currently covers\r\nmultiple areas using different
Rule types. To improve stability, we\r\nshould divide it into separate
test files. For example,\r\n`closing_all_matching_alerts.cy.ts`
and\r\n`auto_populate_with_alert_data.cy.ts`. Additionally, we should
ensure\r\nthat each test file cleans up any previous data to maintain
test\r\nisolation.\r\n\r\n- **Handling Async Calls:** Test flakiness can
occur when Cypress\r\nexecutes faster than async calls, leading to
errors when alerts don't\r\nmove to the closed tab in time. To address
this, we should avoid\r\nimmediate validation after creating an
exception. Instead, refresh the\r\n`Alerts table` to allow time for the
alerts to be moved to the\r\nappropriate tab before asserting the
conditions.\r\n\r\n For example ` waitForAlerts();` method\r\n\r\n-
**Avoiding Specific Alert Counts:** Relying on a specific number
of\r\ngenerated or closed alerts for validation is not a robust
approach.\r\nDuring test execution, the Rule might generate more alerts
than\r\nexpected, leading to test failures. To overcome this, we should
focus on\r\nvalidating the expected behavior rather than a fixed alert
count.\r\n \r\n For example\r\n ```\r\n
goToClosedAlertsOnRuleDetailsPage(); \r\n
cy.get(ALERTS_COUNT).should('exist');\r\n ```\r\n\r\n- In the test, when
utilizing `cy.task('esArchiverLoad',\r\n'exceptions');`, it can be
beneficial to check if the exception list is\r\nnot present in the
environment by calling `cy.task('esArchiverUnload',\r\n'exceptions');`
beforehand. This cleanup step ensures that any existing\r\nexception
list is removed, mitigating the occurrence of the following\r\nerror:
`resource_already_exists_exception:
index\r\n[.lists-default-000001/U_3_TShzRY-WZD_XqhSBnw] already exists
(400).`\r\n\r\n- It does not provide a value at the end of
the\r\n`closing_all_matching_alerts.cy.ts` test to verify if alerts
are\r\ngenerated again after the `Exception` that closes all matching
alerts is\r\ndeleted because the test already begins with the rule
generating alerts\r\nuntil the exception is created. Therefore, this
part has been excluded.\r\n\r\nBy following these steps for the test,
running the new files multiple\r\ntimes locally proved to be
beneficial:\r\n\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/8a0250a0-274f-442b-b94c-86e4c815afd1)\r\n
successfully
\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/4e9562f3-506e-4f13-ab1f-c084d2613eb8)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"8f8c51a2d6c960007a9dc5f8fb4abd9fad7ec5aa"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.10.0","labelRegex":"^v8.10.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/161751","number":161751,"mergeCommit":{"message":"[Security
Solution] [Detection Engine] Fix `rule_exception` cypress test flakiness
(#161751)\n\n## Summary\r\n\r\n- Fixes
#159341 \r\n\r\n**Steps to
insure the flakiness** \r\n\r\n- Run the test through Flaky test runner
by modifying the\r\n`x-pack/plugins/security_solution/package.json` to
only run the\r\n`Rule_exceptions` as the following
=>\r\n`./cypress/e2e/exceptions/**/rule_exception.cy.ts`\r\n- Run the
test locally multiple times by wrapping the test suite by \r\n
`Cypress._.times(50, () => {});`\r\n\r\n**Failing steps**\r\n\r\n- The
test only failed in the step mentioned when executed through
the\r\nFlaky test runner.\r\n\r\n```\r\n 1) Rule Exceptions workflows
from Alert\r\n --\r\n | Should create a Rule exception item from the
alert actions overflow menu and close all matching alerts:\r\n |
AssertionError: Timed out retrying after 150000ms: Expected to find
element: `[data-test-subj=\"alertsStateTableEmptyState\"]`, but never
found it.\r\n```\r\n\r\n- By executing it locally multiple times, the
test failed at different\r\nsteps on each occasion.\r\n \r\n-
Immediately after creating an Exception with the Closing all
matching\r\nalerts option, the Alert table was not found empty,
indicating
a\r\nfailure.\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/492aa552-f721-493b-b0b7-fa3e91dc4e63)\r\n\r\n-
After removing the exception, the expected number of alerts was
not\r\nfound in the Alerts table, resulting in a
failure.\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/c291d630-8775-4a5b-9a6b-feb30a169757)\r\n\r\n-
Unrelated to this test, but concerning exceptions, the
failure\r\noccurred when attempting to click on \"Submit exception\" due
to an error\r\ntoast obstructing the button, similar to the 2nd
screenshot
provided\r\nbelow.\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/d117df13-d521-4ead-8a71-e7a6bd1585d8)\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/758cbb3e-9b95-439a-a5d1-49de8d84518e)\r\n\r\n**Steps
to mitigate test flakiness:**\r\n\r\n- **Splitting Test Cases:** The
rule_exceptions test currently covers\r\nmultiple areas using different
Rule types. To improve stability, we\r\nshould divide it into separate
test files. For example,\r\n`closing_all_matching_alerts.cy.ts`
and\r\n`auto_populate_with_alert_data.cy.ts`. Additionally, we should
ensure\r\nthat each test file cleans up any previous data to maintain
test\r\nisolation.\r\n\r\n- **Handling Async Calls:** Test flakiness can
occur when Cypress\r\nexecutes faster than async calls, leading to
errors when alerts don't\r\nmove to the closed tab in time. To address
this, we should avoid\r\nimmediate validation after creating an
exception. Instead, refresh the\r\n`Alerts table` to allow time for the
alerts to be moved to the\r\nappropriate tab before asserting the
conditions.\r\n\r\n For example ` waitForAlerts();` method\r\n\r\n-
**Avoiding Specific Alert Counts:** Relying on a specific number
of\r\ngenerated or closed alerts for validation is not a robust
approach.\r\nDuring test execution, the Rule might generate more alerts
than\r\nexpected, leading to test failures. To overcome this, we should
focus on\r\nvalidating the expected behavior rather than a fixed alert
count.\r\n \r\n For example\r\n ```\r\n
goToClosedAlertsOnRuleDetailsPage(); \r\n
cy.get(ALERTS_COUNT).should('exist');\r\n ```\r\n\r\n- In the test, when
utilizing `cy.task('esArchiverLoad',\r\n'exceptions');`, it can be
beneficial to check if the exception list is\r\nnot present in the
environment by calling `cy.task('esArchiverUnload',\r\n'exceptions');`
beforehand. This cleanup step ensures that any existing\r\nexception
list is removed, mitigating the occurrence of the following\r\nerror:
`resource_already_exists_exception:
index\r\n[.lists-default-000001/U_3_TShzRY-WZD_XqhSBnw] already exists
(400).`\r\n\r\n- It does not provide a value at the end of
the\r\n`closing_all_matching_alerts.cy.ts` test to verify if alerts
are\r\ngenerated again after the `Exception` that closes all matching
alerts is\r\ndeleted because the test already begins with the rule
generating alerts\r\nuntil the exception is created. Therefore, this
part has been excluded.\r\n\r\nBy following these steps for the test,
running the new files multiple\r\ntimes locally proved to be
beneficial:\r\n\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/8a0250a0-274f-442b-b94c-86e4c815afd1)\r\n
successfully
\r\n\r\n![image](https://github.com/elastic/kibana/assets/12671903/4e9562f3-506e-4f13-ab1f-c084d2613eb8)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"8f8c51a2d6c960007a9dc5f8fb4abd9fad7ec5aa"}}]}]
BACKPORT-->

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
WafaaNasr and kibanamachine authored Aug 22, 2023
1 parent 072be8c commit fd35b9a
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import {
esArchiverLoad,
esArchiverResetKibana,
esArchiverUnload,
} from '../../../tasks/es_archiver';
import { deleteAlertsAndRules } from '../../../tasks/common';
import {
expandFirstAlert,
goToClosedAlertsOnRuleDetailsPage,
goToOpenedAlertsOnRuleDetailsPage,
openAddEndpointExceptionFromAlertActionButton,
openAddEndpointExceptionFromFirstAlert,
waitForAlerts,
} from '../../../tasks/alerts';
import { login, visitWithoutDateRange } from '../../../tasks/login';
import { getEndpointRule } from '../../../objects/rule';
Expand All @@ -21,11 +25,6 @@ import {
waitForAlertsToPopulate,
waitForTheRuleToBeExecuted,
} from '../../../tasks/create_new_rule';
import {
esArchiverLoad,
esArchiverResetKibana,
esArchiverUnload,
} from '../../../tasks/es_archiver';
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation';
import {
addExceptionEntryFieldValue,
Expand All @@ -36,26 +35,21 @@ import {
submitNewExceptionItem,
validateExceptionConditionField,
} from '../../../tasks/exceptions';
import { ALERTS_COUNT, EMPTY_ALERT_TABLE } from '../../../screens/alerts';
import { ALERTS_COUNT } from '../../../screens/alerts';
import {
ADD_AND_BTN,
EXCEPTION_CARD_ITEM_CONDITIONS,
EXCEPTION_CARD_ITEM_NAME,
EXCEPTION_ITEM_VIEWER_CONTAINER,
NO_EXCEPTIONS_EXIST_PROMPT,
} from '../../../screens/exceptions';
import {
removeException,
goToAlertsTab,
goToEndpointExceptionsTab,
} from '../../../tasks/rule_details';
import { goToEndpointExceptionsTab } from '../../../tasks/rule_details';

describe('Endpoint Exceptions workflows from Alert', () => {
const expectedNumberOfAlerts = 1;
const ITEM_NAME = 'Sample Exception List Item';
const ITEM_NAME_EDIT = 'Sample Exception List Item';
const ADDITIONAL_ENTRY = 'host.hostname';
beforeEach(() => {
esArchiverUnload('endpoint');
esArchiverResetKibana();
login();
deleteAlertsAndRules();
Expand All @@ -69,7 +63,6 @@ describe('Endpoint Exceptions workflows from Alert', () => {

after(() => {
esArchiverUnload('endpoint');
esArchiverUnload('endpoint_2');
});

it('Should be able to create and close single Endpoint exception from overflow menu', () => {
Expand All @@ -84,33 +77,14 @@ describe('Endpoint Exceptions workflows from Alert', () => {
addExceptionFlyoutItemName(ITEM_NAME);
submitNewExceptionItem();

// Alerts table should now be empty from having added exception and closed
// matching alert
cy.get(EMPTY_ALERT_TABLE).should('exist');
// Instead of immediately checking if the Opened Alert has moved to the closed tab,
// use the waitForAlerts method to create a buffer, allowing the alerts some time to
// be moved to the Closed Alert tab.
waitForAlerts();

// Closed alert should appear in table
goToClosedAlertsOnRuleDetailsPage();
cy.get(ALERTS_COUNT).should('exist');
cy.get(ALERTS_COUNT).should('have.text', `${expectedNumberOfAlerts} alert`);

// Endpoint Exception will move to Endpoint List under Exception tab of rule
goToEndpointExceptionsTab();

// Remove the exception and load an event that would have matched that exception
// to show that said exception now starts to show up again
removeException();
// when removing exception and again, no more exist, empty screen shows again
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist');

// load more docs
esArchiverLoad('endpoint_2');

goToAlertsTab();
goToOpenedAlertsOnRuleDetailsPage();
waitForTheRuleToBeExecuted();
waitForAlertsToPopulate();

cy.get(ALERTS_COUNT).should('have.text', `${expectedNumberOfAlerts} alert`);
});

it('Should be able to create Endpoint exception from Alerts take action button, and change multiple exception items without resetting to initial auto-prefilled entries', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,147 +4,69 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { LOADING_INDICATOR } from '../../../screens/security_header';
import { getNewRule, getEndpointRule } 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 {
esArchiverLoad,
esArchiverResetKibana,
esArchiverUnload,
} from '../../../../tasks/es_archiver';
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,
goToClosedAlertsOnRuleDetailsPage,
goToOpenedAlertsOnRuleDetailsPage,
openAddRuleExceptionFromAlertActionButton,
} from '../../../tasks/alerts';
} from '../../../../tasks/alerts';
import {
addExceptionEntryFieldValue,
addExceptionEntryFieldValueValue,
addExceptionEntryOperatorValue,
addExceptionFlyoutItemName,
selectBulkCloseAlerts,
submitNewExceptionItem,
validateExceptionItemFirstAffectedRuleNameInRulePage,
validateExceptionItemAffectsTheCorrectRulesInRulePage,
validateExceptionConditionField,
validateExceptionCommentCountAndText,
editExceptionFlyoutItemName,
validateHighlightedFieldsPopulatedAsExceptionConditions,
validateEmptyExceptionConditionField,
} from '../../../tasks/exceptions';
import {
esArchiverLoad,
esArchiverResetKibana,
esArchiverUnload,
} from '../../../tasks/es_archiver';
import { login, visitWithoutDateRange } from '../../../tasks/login';
import {
goToAlertsTab,
goToExceptionsTab,
removeException,
waitForTheRuleToBeExecuted,
} from '../../../tasks/rule_details';
} from '../../../../tasks/exceptions';
import { login, visitWithoutDateRange } from '../../../../tasks/login';
import { goToExceptionsTab } from '../../../../tasks/rule_details';

import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation';
import { postDataView, deleteAlertsAndRules } from '../../../tasks/common';
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation';
import { deleteAlertsAndRules } from '../../../../tasks/common';
import {
ADD_AND_BTN,
ENTRY_DELETE_BTN,
EXCEPTION_CARD_ITEM_CONDITIONS,
EXCEPTION_CARD_ITEM_NAME,
EXCEPTION_ITEM_VIEWER_CONTAINER,
NO_EXCEPTIONS_EXIST_PROMPT,
} from '../../../screens/exceptions';
import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule';
} from '../../../../screens/exceptions';
import { waitForAlertsToPopulate } from '../../../../tasks/create_new_rule';

const loadEndpointRuleAndAlerts = () => {
esArchiverLoad('endpoint');
login();
createRule(getEndpointRule());
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
goToRuleDetails();
waitForAlertsToPopulate();
};

describe('Rule Exceptions workflows from Alert', () => {
const EXPECTED_NUMBER_OF_ALERTS = '1 alert';
describe('Auto populate exception with Alert data', () => {
const ITEM_NAME = 'Sample Exception Item';
const ITEM_NAME_EDIT = 'Sample Exception Item Edit';
const ADDITIONAL_ENTRY = 'host.hostname';
const newRule = getNewRule();

beforeEach(() => {
esArchiverUnload('endpoint');
esArchiverResetKibana();
esArchiverLoad('endpoint');
login();
createRule(getEndpointRule());
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
goToRuleDetails();
waitForAlertsToPopulate();
});
after(() => {
esArchiverUnload('exceptions');
esArchiverUnload('endpoint');
deleteAlertsAndRules();
});
afterEach(() => {
esArchiverUnload('exceptions_2');
esArchiverUnload('endpoint');
});

it('Should create a Rule exception item from alert actions overflow menu and close all matching alerts', () => {
esArchiverLoad('exceptions');
login();
postDataView('exceptions-*');
createRule({
...newRule,
query: 'agent.name:*',
data_view_id: 'exceptions-*',
interval: '10s',
rule_id: 'rule_testing',
});
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
goToRuleDetails();
waitForAlertsToPopulate();

cy.get(LOADING_INDICATOR).should('not.exist');
addExceptionFromFirstAlert();

addExceptionEntryFieldValue('agent.name', 0);
addExceptionEntryOperatorValue('is', 0);
addExceptionEntryFieldValueValue('foo', 0);

addExceptionFlyoutItemName(ITEM_NAME);
selectBulkCloseAlerts();
submitNewExceptionItem();

// Alerts table should now be empty from having added exception and closed
// matching alert
cy.get(EMPTY_ALERT_TABLE).should('exist');

// Closed alert should appear in table
goToClosedAlertsOnRuleDetailsPage();
cy.get(ALERTS_COUNT).should('exist');
cy.get(ALERTS_COUNT).should('have.text', `${EXPECTED_NUMBER_OF_ALERTS}`);

// Remove the exception and load an event that would have matched that exception
// to show that said exception now starts to show up again
goToExceptionsTab();

// Validate the exception is affecting the correct rule count and name
validateExceptionItemAffectsTheCorrectRulesInRulePage(1);
validateExceptionItemFirstAffectedRuleNameInRulePage(newRule.name);

// when removing exception and again, no more exist, empty screen shows again
removeException();
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist');

// load more docs
esArchiverLoad('exceptions_2');

// now that there are no more exceptions, the docs should match and populate alerts
goToAlertsTab();
goToOpenedAlertsOnRuleDetailsPage();
waitForTheRuleToBeExecuted();
waitForAlertsToPopulate();

cy.get(ALERTS_COUNT).should('have.text', '2 alerts');
});
it('Should create a Rule exception item from alert actions overflow menu and auto populate the conditions using alert Highlighted fields', () => {
loadEndpointRuleAndAlerts();

cy.get(LOADING_INDICATOR).should('not.exist');
addExceptionFromFirstAlert();

Expand Down Expand Up @@ -176,8 +98,6 @@ describe('Rule Exceptions workflows from Alert', () => {
submitNewExceptionItem();
});
it('Should create a Rule exception from Alerts take action button and change multiple exception items without resetting to initial auto-prefilled entries', () => {
loadEndpointRuleAndAlerts();

cy.get(LOADING_INDICATOR).should('not.exist');

// Open first Alert Summary
Expand Down Expand Up @@ -234,8 +154,6 @@ describe('Rule Exceptions workflows from Alert', () => {
cy.get(EXCEPTION_CARD_ITEM_CONDITIONS).contains('span', 'host.hostname');
});
it('Should delete all prefilled exception entries when creating a Rule exception from Alerts take action button without resetting to initial auto-prefilled entries', () => {
loadEndpointRuleAndAlerts();

cy.get(LOADING_INDICATOR).should('not.exist');

// Open first Alert Summary
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import {
esArchiverLoad,
esArchiverResetKibana,
esArchiverUnload,
} from '../../../../tasks/es_archiver';
import {
addExceptionFromFirstAlert,
goToClosedAlertsOnRuleDetailsPage,
waitForAlerts,
} from '../../../../tasks/alerts';
import { deleteAlertsAndRules, postDataView } from '../../../../tasks/common';
import { waitForAlertsToPopulate } from '../../../../tasks/create_new_rule';
import { login, visitWithoutDateRange } from '../../../../tasks/login';
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation';
import { goToRuleDetails } from '../../../../tasks/alerts_detection_rules';
import { createRule } from '../../../../tasks/api_calls/rules';
import { getNewRule } from '../../../../objects/rule';
import { LOADING_INDICATOR } from '../../../../screens/security_header';
import { ALERTS_COUNT } from '../../../../screens/alerts';
import {
addExceptionEntryFieldValue,
addExceptionEntryOperatorValue,
addExceptionEntryFieldValueValue,
addExceptionFlyoutItemName,
selectBulkCloseAlerts,
submitNewExceptionItem,
} from '../../../../tasks/exceptions';

describe('Close matching Alerts ', () => {
const newRule = getNewRule();
const ITEM_NAME = 'Sample Exception Item';

beforeEach(() => {
esArchiverUnload('exceptions');
esArchiverResetKibana();
deleteAlertsAndRules();
esArchiverLoad('exceptions');

login();
postDataView('exceptions-*');
createRule({
...newRule,
query: 'agent.name:*',
data_view_id: 'exceptions-*',
interval: '10s',
rule_id: 'rule_testing',
});
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
goToRuleDetails();
waitForAlertsToPopulate();
});
after(() => {
esArchiverUnload('exceptions');
});

it('Should create a Rule exception item from alert actions overflow menu and close all matching alerts', () => {
cy.get(LOADING_INDICATOR).should('not.exist');
addExceptionFromFirstAlert();

addExceptionEntryFieldValue('agent.name', 0);
addExceptionEntryOperatorValue('is', 0);
addExceptionEntryFieldValueValue('foo', 0);

addExceptionFlyoutItemName(ITEM_NAME);
selectBulkCloseAlerts();
submitNewExceptionItem();

// Instead of immediately checking if the Opened Alert has moved to the closed tab,
// use the waitForAlerts method to create a buffer, allowing the alerts some time to
// be moved to the Closed Alert tab.
waitForAlerts();

// Closed alert should appear in table
goToClosedAlertsOnRuleDetailsPage();
// We should not expect a specific number using should "have.text" because as the Rule is executing it is highly likely to create other
// alerts and when the exception conditions start to close matching alerts there might be more than what was
// before creating an exception
cy.get(ALERTS_COUNT).should('exist');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ export const validateEmptyExceptionConditionField = () => {
cy.get(FIELD_INPUT).should('be.empty');
};
export const submitNewExceptionItem = () => {
cy.get(CONFIRM_BTN).should('exist');
cy.get(CONFIRM_BTN).click();
cy.get(CONFIRM_BTN).should('not.exist');
};
Expand Down

0 comments on commit fd35b9a

Please sign in to comment.