mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[8.9] [Security Solution] Reduce Rules Management e2e flakiness (#165468)
**NOTE: This is a manual backport of #164099** **Original PR description:** --- **Relates to: https://github.com/elastic/kibana/issues/161507** **Fixes: https://github.com/elastic/kibana/issues/163704** **Fixes: https://github.com/elastic/kibana/issues/163182** **Fixes: https://github.com/elastic/kibana/issues/163558** **Fixes: https://github.com/elastic/kibana/issues/163974** **Fixes: https://github.com/elastic/kibana/issues/153914** **Fixes: https://github.com/elastic/kibana/issues/164079** **Fixes: https://github.com/elastic/kibana/issues/164279** ## Summary While working on fixing Rules Management flaky tests I've noticed similar fails in different tests. This PR addresses common pitfalls to reduce a number of reasons causing e2e tests flakiness and as a result reduce a number of flaky tests. ## Details The common reasons causing e2e tests flakiness for the rules tables are - Auto-refresh Auto-refresh functionality is enabled by default and the table gets auto-refreshed every 60 seconds. If a test takes more than 60 seconds the table fetches updated rules. Having rules enabled by default and sorted by `Enabled` column makes the sorting order undetermined and as rules get updated due to execution ES return them in undetermined order. This update can happen between commands working on the same element and indexed access like `eq()` would access different elements. - Missing selectors Some tests or helper functions have expectations for an element absence like `should('not.exist')` without checking an element is visible before like `should('be.visible')`. This way a referenced element may disappear from the codebase after refactoring and the expectation still fulfils. - Checking for `should('not.visible')` while an element is removed from the DOM It most applicable to popovers as it first animates to be hidden and then removed from the DOM. Cypress first need to find an element to check its visibility. Replacing `should('not.visible')` with `should('not.exist')` and taking into concern from the account previous bullet fixes the problem. - Modifying ES data without refreshing (`_delete_by_query` in particular) Due to high performance ES architecture data isn't updated instantly. Having such behavior in tests leads to undetermined state depending on a number of environmental factors. As UI doesn't always auto-refreshes to fetch the recent updates in short period of time test fail. `_delete_by_query` may take some time to update the data but it doesn't support `refresh=wait_for` as it stated in [docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html#_refreshing_shards). Adding `?refresh=true` or just `?refresh` to `_delete_by_query` ES request urls fixes the problem. ### What was done to address mentioned reasons above? - Auto-refresh functionality disabled in tests where it's not necessary. - `enabled: false` field was added to rule creators to have disabled rules as the majority of tests don't need enabled rules. - `waitForRulesTableToBeLoaded` was removed and replaced with `expectManagementTableRules` at some tests. - `should('not.visible')` replaced with `should('not.exist')` in `deleteRuleFromDetailsPage()` - `?refresh` added to `_delete_by_query` ES data update requests The other changes get rid of global constants and improve readability. ## Flaky test runs [All Cypress tests under `detection_response` folder (100 runs)](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2920) (value lists export is flaky but it's out of scope of this PR) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
cb8b5a9b59
commit
2c0c69a418
31 changed files with 1194 additions and 1061 deletions
|
@ -13,7 +13,6 @@ import {
|
|||
RULE_NAME,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
import { VALUE_LISTS_MODAL_ACTIVATOR } from '../../screens/lists';
|
||||
import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { cleanKibana } from '../../tasks/common';
|
||||
import {
|
||||
|
@ -22,19 +21,17 @@ import {
|
|||
waitForCallOutToBeShown,
|
||||
MISSING_PRIVILEGES_CALLOUT,
|
||||
} from '../../tasks/common/callouts';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../tasks/login';
|
||||
|
||||
describe('All rules - read only', () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
createRule(getNewRule({ rule_id: '1' }));
|
||||
createRule(getNewRule({ rule_id: '1', enabled: false }));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLES.reader);
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL, ROLES.reader);
|
||||
waitForRulesTableToBeLoaded();
|
||||
visitSecurityDetectionRulesPage(ROLES.reader);
|
||||
cy.get(RULE_NAME).should('have.text', getNewRule().name);
|
||||
});
|
||||
|
||||
|
|
|
@ -5,33 +5,29 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getNewRule } from '../../objects/rule';
|
||||
import { EXCEPTION_CARD_ITEM_NAME } from '../../screens/exceptions';
|
||||
import {
|
||||
waitForRulesTableToBeLoaded,
|
||||
goToTheRuleDetailsOf,
|
||||
selectNumberOfRules,
|
||||
duplicateSelectedRulesWithoutExceptions,
|
||||
disableAutoRefresh,
|
||||
selectAllRules,
|
||||
expectManagementTableRules,
|
||||
duplicateSelectedRulesWithExceptions,
|
||||
duplicateSelectedRulesWithNonExpiredExceptions,
|
||||
goToTheRuleDetailsOf,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
|
||||
import { goToExceptionsTab, viewExpiredExceptionItems } from '../../tasks/rule_details';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
import { createRuleExceptionItem } from '../../tasks/api_calls/exceptions';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { cleanKibana, resetRulesTableState, deleteAlertsAndRules } from '../../tasks/common';
|
||||
|
||||
import { getNewRule } from '../../objects/rule';
|
||||
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
|
||||
import { createRuleExceptionItem } from '../../tasks/api_calls/exceptions';
|
||||
import { EXCEPTION_CARD_ITEM_NAME } from '../../screens/exceptions';
|
||||
import {
|
||||
assertExceptionItemsExists,
|
||||
assertNumberOfExceptionItemsExists,
|
||||
} from '../../tasks/exceptions';
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../tasks/login';
|
||||
import { goToExceptionsTab, viewExpiredExceptionItems } from '../../tasks/rule_details';
|
||||
import {
|
||||
duplicateSelectedRulesWithExceptions,
|
||||
duplicateSelectedRulesWithNonExpiredExceptions,
|
||||
duplicateSelectedRulesWithoutExceptions,
|
||||
} from '../../tasks/rules_bulk_edit';
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
|
||||
const RULE_NAME = 'Custom rule for bulk actions';
|
||||
|
||||
|
@ -61,55 +57,54 @@ describe('Detection rules, bulk duplicate', () => {
|
|||
resetRulesTableState();
|
||||
deleteAlertsAndRules();
|
||||
esArchiverResetKibana();
|
||||
createRule(getNewRule({ name: RULE_NAME, ...defaultRuleData, rule_id: '1' })).then(
|
||||
(response) => {
|
||||
createRuleExceptionItem(response.body.id, [
|
||||
{
|
||||
description: 'Exception item for rule default exception list',
|
||||
entries: [
|
||||
{
|
||||
field: 'user.name',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
name: EXPIRED_EXCEPTION_ITEM_NAME,
|
||||
type: 'simple',
|
||||
expire_time: expiredDate,
|
||||
},
|
||||
{
|
||||
description: 'Exception item for rule default exception list',
|
||||
entries: [
|
||||
{
|
||||
field: 'user.name',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
name: NON_EXPIRED_EXCEPTION_ITEM_NAME,
|
||||
type: 'simple',
|
||||
expire_time: futureDate,
|
||||
},
|
||||
]);
|
||||
}
|
||||
);
|
||||
createRule(
|
||||
getNewRule({ name: RULE_NAME, ...defaultRuleData, rule_id: '1', enabled: false })
|
||||
).then((response) => {
|
||||
createRuleExceptionItem(response.body.id, [
|
||||
{
|
||||
description: 'Exception item for rule default exception list',
|
||||
entries: [
|
||||
{
|
||||
field: 'user.name',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
name: EXPIRED_EXCEPTION_ITEM_NAME,
|
||||
type: 'simple',
|
||||
expire_time: expiredDate,
|
||||
},
|
||||
{
|
||||
description: 'Exception item for rule default exception list',
|
||||
entries: [
|
||||
{
|
||||
field: 'user.name',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
name: NON_EXPIRED_EXCEPTION_ITEM_NAME,
|
||||
type: 'simple',
|
||||
expire_time: futureDate,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
|
||||
waitForRulesTableToBeLoaded();
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
});
|
||||
|
||||
it('Duplicates rules', () => {
|
||||
selectNumberOfRules(1);
|
||||
selectAllRules();
|
||||
duplicateSelectedRulesWithoutExceptions();
|
||||
expectManagementTableRules([`${RULE_NAME} [Duplicate]`]);
|
||||
});
|
||||
|
||||
describe('With exceptions', () => {
|
||||
it('Duplicates rules with expired exceptions', () => {
|
||||
selectNumberOfRules(1);
|
||||
selectAllRules();
|
||||
duplicateSelectedRulesWithExceptions();
|
||||
expectManagementTableRules([`${RULE_NAME} [Duplicate]`]);
|
||||
goToTheRuleDetailsOf(`${RULE_NAME} [Duplicate]`);
|
||||
|
@ -120,7 +115,7 @@ describe('Detection rules, bulk duplicate', () => {
|
|||
});
|
||||
|
||||
it('Duplicates rules with exceptions, excluding expired exceptions', () => {
|
||||
selectNumberOfRules(1);
|
||||
selectAllRules();
|
||||
duplicateSelectedRulesWithNonExpiredExceptions();
|
||||
expectManagementTableRules([`${RULE_NAME} [Duplicate]`]);
|
||||
goToTheRuleDetailsOf(`${RULE_NAME} [Duplicate]`);
|
||||
|
|
|
@ -5,95 +5,87 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { createRuleAssetSavedObject } from '../../helpers/rules';
|
||||
import {
|
||||
getNewRule,
|
||||
getEqlRule,
|
||||
getMachineLearningRule,
|
||||
getNewThreatIndicatorRule,
|
||||
getNewThresholdRule,
|
||||
getNewTermsRule,
|
||||
} from '../../objects/rule';
|
||||
import {
|
||||
MODAL_CONFIRMATION_BTN,
|
||||
MODAL_CONFIRMATION_BODY,
|
||||
RULE_CHECKBOX,
|
||||
RULES_TAGS_POPOVER_BTN,
|
||||
MODAL_ERROR_BODY,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
|
||||
import { EUI_CHECKBOX, EUI_FILTER_SELECT_ITEM } from '../../screens/common/controls';
|
||||
import {
|
||||
RULES_BULK_EDIT_INDEX_PATTERNS_WARNING,
|
||||
RULES_BULK_EDIT_TAGS_WARNING,
|
||||
RULES_BULK_EDIT_TIMELINE_TEMPLATES_WARNING,
|
||||
TAGS_RULE_BULK_MENU_ITEM,
|
||||
INDEX_PATTERNS_RULE_BULK_MENU_ITEM,
|
||||
APPLY_TIMELINE_RULE_BULK_MENU_ITEM,
|
||||
RULES_BULK_EDIT_TAGS_WARNING,
|
||||
RULES_BULK_EDIT_INDEX_PATTERNS_WARNING,
|
||||
RULES_BULK_EDIT_TIMELINE_TEMPLATES_WARNING,
|
||||
} from '../../screens/rules_bulk_edit';
|
||||
|
||||
import { TIMELINE_TEMPLATE_DETAILS } from '../../screens/rule_details';
|
||||
|
||||
import { EUI_FILTER_SELECT_ITEM } from '../../screens/common/controls';
|
||||
|
||||
import {
|
||||
waitForRulesTableToBeLoaded,
|
||||
selectAllRules,
|
||||
goToTheRuleDetailsOf,
|
||||
selectNumberOfRules,
|
||||
testAllTagsBadges,
|
||||
testTagsBadge,
|
||||
testMultipleSelectedRulesLabel,
|
||||
disableAutoRefresh,
|
||||
filterByElasticRules,
|
||||
clickErrorToastBtn,
|
||||
unselectRuleByName,
|
||||
selectAllRulesOnPage,
|
||||
getRulesManagementTableRows,
|
||||
selectAllRules,
|
||||
cancelConfirmationModal,
|
||||
selectRulesByName,
|
||||
testMultipleSelectedRulesLabel,
|
||||
getRuleRow,
|
||||
testTagsBadge,
|
||||
testAllTagsBadges,
|
||||
goToTheRuleDetailsOf,
|
||||
clickErrorToastBtn,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
|
||||
import {
|
||||
typeIndexPatterns,
|
||||
waitForBulkEditActionToFinish,
|
||||
submitBulkEditForm,
|
||||
clickAddIndexPatternsMenuItem,
|
||||
checkPrebuiltRulesCannotBeModified,
|
||||
checkMachineLearningRulesCannotBeModified,
|
||||
waitForMixedRulesBulkEditModal,
|
||||
openBulkEditAddTagsForm,
|
||||
openBulkEditDeleteTagsForm,
|
||||
typeTags,
|
||||
openTagsSelect,
|
||||
openBulkActionsMenu,
|
||||
clickApplyTimelineTemplatesMenuItem,
|
||||
clickAddTagsMenuItem,
|
||||
checkOverwriteTagsCheckbox,
|
||||
checkOverwriteIndexPatternsCheckbox,
|
||||
openBulkEditAddIndexPatternsForm,
|
||||
openBulkEditDeleteIndexPatternsForm,
|
||||
selectTimelineTemplate,
|
||||
checkTagsInTagsFilter,
|
||||
clickUpdateScheduleMenuItem,
|
||||
typeScheduleInterval,
|
||||
typeScheduleLookback,
|
||||
setScheduleLookbackTimeUnit,
|
||||
setScheduleIntervalTimeUnit,
|
||||
assertRuleScheduleValues,
|
||||
assertUpdateScheduleWarningExists,
|
||||
assertDefaultValuesAreAppliedToScheduleFields,
|
||||
} from '../../tasks/rules_bulk_edit';
|
||||
|
||||
import { hasIndexPatterns, getDetails } from '../../tasks/rule_details';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
createAndInstallMockedPrebuiltRules,
|
||||
getAvailablePrebuiltRulesCount,
|
||||
} from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { loadPrepackagedTimelineTemplates } from '../../tasks/api_calls/timelines';
|
||||
import { cleanKibana, resetRulesTableState, deleteAlertsAndRules } from '../../tasks/common';
|
||||
|
||||
import {
|
||||
getEqlRule,
|
||||
getNewThreatIndicatorRule,
|
||||
getNewRule,
|
||||
getNewThresholdRule,
|
||||
getMachineLearningRule,
|
||||
getNewTermsRule,
|
||||
} from '../../objects/rule';
|
||||
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../tasks/login';
|
||||
import {
|
||||
getAvailablePrebuiltRulesCount,
|
||||
excessivelyInstallAllPrebuiltRules,
|
||||
} from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { setRowsPerPageTo } from '../../tasks/table_pagination';
|
||||
openBulkActionsMenu,
|
||||
clickApplyTimelineTemplatesMenuItem,
|
||||
checkPrebuiltRulesCannotBeModified,
|
||||
clickAddTagsMenuItem,
|
||||
waitForMixedRulesBulkEditModal,
|
||||
typeTags,
|
||||
submitBulkEditForm,
|
||||
waitForBulkEditActionToFinish,
|
||||
openBulkEditAddTagsForm,
|
||||
openTagsSelect,
|
||||
checkTagsInTagsFilter,
|
||||
checkOverwriteTagsCheckbox,
|
||||
openBulkEditDeleteTagsForm,
|
||||
clickAddIndexPatternsMenuItem,
|
||||
checkMachineLearningRulesCannotBeModified,
|
||||
typeIndexPatterns,
|
||||
openBulkEditAddIndexPatternsForm,
|
||||
checkOverwriteIndexPatternsCheckbox,
|
||||
openBulkEditDeleteIndexPatternsForm,
|
||||
selectTimelineTemplate,
|
||||
clickUpdateScheduleMenuItem,
|
||||
assertUpdateScheduleWarningExists,
|
||||
assertDefaultValuesAreAppliedToScheduleFields,
|
||||
typeScheduleInterval,
|
||||
setScheduleIntervalTimeUnit,
|
||||
typeScheduleLookback,
|
||||
setScheduleLookbackTimeUnit,
|
||||
assertRuleScheduleValues,
|
||||
} from '../../tasks/rules_bulk_edit';
|
||||
import { hasIndexPatterns, getDetails } from '../../tasks/rule_details';
|
||||
import { setRowsPerPageTo, sortByTableColumn } from '../../tasks/table_pagination';
|
||||
|
||||
const RULE_NAME = 'Custom rule for bulk actions';
|
||||
const EUI_SELECTABLE_LIST_ITEM_SR_TEXT = '. To check this option, press Enter.';
|
||||
|
@ -101,16 +93,8 @@ const EUI_SELECTABLE_LIST_ITEM_SR_TEXT = '. To check this option, press Enter.';
|
|||
const prePopulatedIndexPatterns = ['index-1-*', 'index-2-*'];
|
||||
const prePopulatedTags = ['test-default-tag-1', 'test-default-tag-2'];
|
||||
|
||||
const expectedNumberOfCustomRulesToBeEdited = 6;
|
||||
const expectedNumberOfMachineLearningRulesToBeEdited = 1;
|
||||
|
||||
/**
|
||||
* total number of custom rules that are not Machine learning
|
||||
*/
|
||||
const expectedNumberOfNotMLRules =
|
||||
expectedNumberOfCustomRulesToBeEdited - expectedNumberOfMachineLearningRulesToBeEdited;
|
||||
const numberOfRulesPerPage = 5;
|
||||
|
||||
const defaultRuleData = {
|
||||
index: prePopulatedIndexPatterns,
|
||||
tags: prePopulatedTags,
|
||||
|
@ -128,19 +112,53 @@ describe('Detection rules, bulk edit', () => {
|
|||
resetRulesTableState();
|
||||
deleteAlertsAndRules();
|
||||
esArchiverResetKibana();
|
||||
createRule(getNewRule({ name: RULE_NAME, ...defaultRuleData, rule_id: '1' }));
|
||||
createRule(getEqlRule({ ...defaultRuleData, rule_id: '2' }));
|
||||
createRule(getMachineLearningRule({ tags: ['test-default-tag-1', 'test-default-tag-2'] }));
|
||||
createRule(getNewThreatIndicatorRule({ ...defaultRuleData, rule_id: '4' }));
|
||||
createRule(getNewThresholdRule({ ...defaultRuleData, rule_id: '5' }));
|
||||
createRule(getNewTermsRule({ ...defaultRuleData, rule_id: '6' }));
|
||||
createRule(getNewRule({ name: RULE_NAME, ...defaultRuleData, rule_id: '1', enabled: false }));
|
||||
createRule(
|
||||
getEqlRule({ ...defaultRuleData, rule_id: '2', name: 'New EQL Rule', enabled: false })
|
||||
);
|
||||
createRule(
|
||||
getMachineLearningRule({
|
||||
name: 'New ML Rule Test',
|
||||
tags: ['test-default-tag-1', 'test-default-tag-2'],
|
||||
enabled: false,
|
||||
})
|
||||
);
|
||||
createRule(
|
||||
getNewThreatIndicatorRule({
|
||||
...defaultRuleData,
|
||||
rule_id: '4',
|
||||
name: 'Threat Indicator Rule Test',
|
||||
enabled: false,
|
||||
})
|
||||
);
|
||||
createRule(
|
||||
getNewThresholdRule({
|
||||
...defaultRuleData,
|
||||
rule_id: '5',
|
||||
name: 'Threshold Rule',
|
||||
enabled: false,
|
||||
})
|
||||
);
|
||||
createRule(
|
||||
getNewTermsRule({ ...defaultRuleData, rule_id: '6', name: 'New Terms Rule', enabled: false })
|
||||
);
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
|
||||
waitForRulesTableToBeLoaded();
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
});
|
||||
|
||||
describe('Prerequisites', () => {
|
||||
const PREBUILT_RULES = [
|
||||
createRuleAssetSavedObject({
|
||||
name: 'Prebuilt rule 1',
|
||||
rule_id: 'rule_1',
|
||||
}),
|
||||
createRuleAssetSavedObject({
|
||||
name: 'Prebuilt rule 2',
|
||||
rule_id: 'rule_2',
|
||||
}),
|
||||
];
|
||||
|
||||
it('No rules selected', () => {
|
||||
openBulkActionsMenu();
|
||||
|
||||
|
@ -151,80 +169,87 @@ describe('Detection rules, bulk edit', () => {
|
|||
});
|
||||
|
||||
it('Only prebuilt rules selected', () => {
|
||||
const expectedNumberOfSelectedRules = 10;
|
||||
|
||||
excessivelyInstallAllPrebuiltRules();
|
||||
createAndInstallMockedPrebuiltRules({ rules: PREBUILT_RULES });
|
||||
|
||||
// select Elastic(prebuilt) rules, check if we can't proceed further, as Elastic rules are not editable
|
||||
filterByElasticRules();
|
||||
selectNumberOfRules(expectedNumberOfSelectedRules);
|
||||
selectAllRulesOnPage();
|
||||
clickApplyTimelineTemplatesMenuItem();
|
||||
|
||||
// check modal window for Elastic rule that can't be edited
|
||||
checkPrebuiltRulesCannotBeModified(expectedNumberOfSelectedRules);
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
// check modal window for Elastic rule that can't be edited
|
||||
checkPrebuiltRulesCannotBeModified(rows.length);
|
||||
|
||||
// the confirm button closes modal
|
||||
cy.get(MODAL_CONFIRMATION_BTN).should('have.text', 'Close').click();
|
||||
cy.get(MODAL_CONFIRMATION_BODY).should('not.exist');
|
||||
// the confirm button closes modal
|
||||
cy.get(MODAL_CONFIRMATION_BTN).should('have.text', 'Close').click();
|
||||
cy.get(MODAL_CONFIRMATION_BODY).should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('Prebuilt and custom rules selected: user proceeds with custom rules editing', () => {
|
||||
excessivelyInstallAllPrebuiltRules();
|
||||
getRulesManagementTableRows().then((existedRulesRows) => {
|
||||
createAndInstallMockedPrebuiltRules({ rules: PREBUILT_RULES });
|
||||
|
||||
// modal window should show how many rules can be edit, how many not
|
||||
selectAllRules();
|
||||
clickAddTagsMenuItem();
|
||||
waitForMixedRulesBulkEditModal(expectedNumberOfCustomRulesToBeEdited);
|
||||
// modal window should show how many rules can be edit, how many not
|
||||
selectAllRules();
|
||||
clickAddTagsMenuItem();
|
||||
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
checkPrebuiltRulesCannotBeModified(availablePrebuiltRulesCount);
|
||||
waitForMixedRulesBulkEditModal(existedRulesRows.length);
|
||||
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
checkPrebuiltRulesCannotBeModified(availablePrebuiltRulesCount);
|
||||
});
|
||||
|
||||
// user can proceed with custom rule editing
|
||||
cy.get(MODAL_CONFIRMATION_BTN)
|
||||
.should('have.text', `Edit ${existedRulesRows.length} custom rules`)
|
||||
.click();
|
||||
|
||||
// action should finish
|
||||
typeTags(['test-tag']);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: existedRulesRows.length });
|
||||
});
|
||||
|
||||
// user can proceed with custom rule editing
|
||||
cy.get(MODAL_CONFIRMATION_BTN)
|
||||
.should('have.text', `Edit ${expectedNumberOfCustomRulesToBeEdited} custom rules`)
|
||||
.click();
|
||||
|
||||
// action should finish
|
||||
typeTags(['test-tag']);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
});
|
||||
|
||||
it('Prebuilt and custom rules selected: user cancels action', () => {
|
||||
excessivelyInstallAllPrebuiltRules();
|
||||
createAndInstallMockedPrebuiltRules({ rules: PREBUILT_RULES });
|
||||
|
||||
// modal window should show how many rules can be edit, how many not
|
||||
selectAllRules();
|
||||
clickAddTagsMenuItem();
|
||||
waitForMixedRulesBulkEditModal(expectedNumberOfCustomRulesToBeEdited);
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
// modal window should show how many rules can be edit, how many not
|
||||
selectAllRules();
|
||||
clickAddTagsMenuItem();
|
||||
waitForMixedRulesBulkEditModal(rows.length);
|
||||
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
checkPrebuiltRulesCannotBeModified(availablePrebuiltRulesCount);
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
checkPrebuiltRulesCannotBeModified(availablePrebuiltRulesCount);
|
||||
});
|
||||
|
||||
// user cancels action and modal disappears
|
||||
cancelConfirmationModal();
|
||||
});
|
||||
|
||||
// user cancels action and modal disappears
|
||||
cancelConfirmationModal();
|
||||
});
|
||||
|
||||
it('should not lose rules selection after edit action', () => {
|
||||
const rulesCount = 4;
|
||||
const rulesToUpdate = [RULE_NAME, 'New EQL Rule', 'New Terms Rule'] as const;
|
||||
// Switch to 5 rules per page, to have few pages in pagination(ideal way to test auto refresh and selection of few items)
|
||||
setRowsPerPageTo(numberOfRulesPerPage);
|
||||
selectNumberOfRules(rulesCount);
|
||||
setRowsPerPageTo(5);
|
||||
// and make the rules order isn't changing (set sorting by rule name) over time if rules are run
|
||||
sortByTableColumn('Rule');
|
||||
selectRulesByName(rulesToUpdate);
|
||||
|
||||
// open add tags form and add 2 new tags
|
||||
openBulkEditAddTagsForm();
|
||||
typeTags(['new-tag-1']);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: rulesCount });
|
||||
waitForBulkEditActionToFinish({ updatedCount: rulesToUpdate.length });
|
||||
|
||||
testMultipleSelectedRulesLabel(rulesCount);
|
||||
testMultipleSelectedRulesLabel(rulesToUpdate.length);
|
||||
// check if first four(rulesCount) rules still selected and tags are updated
|
||||
for (let i = 0; i < rulesCount; i += 1) {
|
||||
cy.get(RULE_CHECKBOX).eq(i).should('be.checked');
|
||||
cy.get(RULES_TAGS_POPOVER_BTN)
|
||||
.eq(i)
|
||||
for (const ruleName of rulesToUpdate) {
|
||||
getRuleRow(ruleName).find(EUI_CHECKBOX).should('be.checked');
|
||||
getRuleRow(ruleName)
|
||||
.find(RULES_TAGS_POPOVER_BTN)
|
||||
.each(($el) => {
|
||||
testTagsBadge($el, prePopulatedTags.concat(['new-tag-1']));
|
||||
});
|
||||
|
@ -234,7 +259,7 @@ describe('Detection rules, bulk edit', () => {
|
|||
|
||||
describe('Tags actions', () => {
|
||||
it('Display list of tags in tags select', () => {
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
selectAllRules();
|
||||
|
||||
openBulkEditAddTagsForm();
|
||||
openTagsSelect();
|
||||
|
@ -247,119 +272,131 @@ describe('Detection rules, bulk edit', () => {
|
|||
});
|
||||
|
||||
it('Add tags to custom rules', () => {
|
||||
const tagsToBeAdded = ['tag-to-add-1', 'tag-to-add-2'];
|
||||
const resultingTags = [...prePopulatedTags, ...tagsToBeAdded];
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
const tagsToBeAdded = ['tag-to-add-1', 'tag-to-add-2'];
|
||||
const resultingTags = [...prePopulatedTags, ...tagsToBeAdded];
|
||||
|
||||
// check if only pre-populated tags exist in the tags filter
|
||||
checkTagsInTagsFilter(prePopulatedTags, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
// check if only pre-populated tags exist in the tags filter
|
||||
checkTagsInTagsFilter(prePopulatedTags, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
selectAllRules();
|
||||
|
||||
// open add tags form and add 2 new tags
|
||||
openBulkEditAddTagsForm();
|
||||
typeTags(tagsToBeAdded);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
// open add tags form and add 2 new tags
|
||||
openBulkEditAddTagsForm();
|
||||
typeTags(tagsToBeAdded);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
|
||||
// check if all rules have been updated with new tags
|
||||
testAllTagsBadges(resultingTags);
|
||||
// check if all rules have been updated with new tags
|
||||
testAllTagsBadges(resultingTags);
|
||||
|
||||
// check that new tags were added to tags filter
|
||||
// tags in tags filter sorted alphabetically
|
||||
const resultingTagsInFilter = [...resultingTags].sort();
|
||||
checkTagsInTagsFilter(resultingTagsInFilter, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
// check that new tags were added to tags filter
|
||||
// tags in tags filter sorted alphabetically
|
||||
const resultingTagsInFilter = [...resultingTags].sort();
|
||||
checkTagsInTagsFilter(resultingTagsInFilter, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
});
|
||||
});
|
||||
|
||||
it('Display success toast after adding tags', () => {
|
||||
const tagsToBeAdded = ['tag-to-add-1', 'tag-to-add-2'];
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
const tagsToBeAdded = ['tag-to-add-1', 'tag-to-add-2'];
|
||||
|
||||
// check if only pre-populated tags exist in the tags filter
|
||||
checkTagsInTagsFilter(prePopulatedTags, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
// check if only pre-populated tags exist in the tags filter
|
||||
checkTagsInTagsFilter(prePopulatedTags, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
selectAllRules();
|
||||
|
||||
// open add tags form and add 2 new tags
|
||||
openBulkEditAddTagsForm();
|
||||
typeTags(tagsToBeAdded);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
// open add tags form and add 2 new tags
|
||||
openBulkEditAddTagsForm();
|
||||
typeTags(tagsToBeAdded);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
});
|
||||
});
|
||||
|
||||
it('Overwrite tags in custom rules', () => {
|
||||
const tagsToOverwrite = ['overwrite-tag-1'];
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
const tagsToOverwrite = ['overwrite-tag-1'];
|
||||
|
||||
// check if only pre-populated tags exist in the tags filter
|
||||
checkTagsInTagsFilter(prePopulatedTags, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
// check if only pre-populated tags exist in the tags filter
|
||||
checkTagsInTagsFilter(prePopulatedTags, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
selectAllRules();
|
||||
|
||||
// open add tags form, check overwrite tags and warning message, type tags
|
||||
openBulkEditAddTagsForm();
|
||||
checkOverwriteTagsCheckbox();
|
||||
// open add tags form, check overwrite tags and warning message, type tags
|
||||
openBulkEditAddTagsForm();
|
||||
checkOverwriteTagsCheckbox();
|
||||
|
||||
cy.get(RULES_BULK_EDIT_TAGS_WARNING).should(
|
||||
'have.text',
|
||||
`You’re about to overwrite tags for ${expectedNumberOfCustomRulesToBeEdited} selected rules, press Save to apply changes.`
|
||||
);
|
||||
cy.get(RULES_BULK_EDIT_TAGS_WARNING).should(
|
||||
'have.text',
|
||||
`You’re about to overwrite tags for ${rows.length} selected rules, press Save to apply changes.`
|
||||
);
|
||||
|
||||
typeTags(tagsToOverwrite);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
typeTags(tagsToOverwrite);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
|
||||
// check if all rules have been updated with new tags
|
||||
testAllTagsBadges(tagsToOverwrite);
|
||||
// check if all rules have been updated with new tags
|
||||
testAllTagsBadges(tagsToOverwrite);
|
||||
|
||||
// check that only new tags are in the tag filter
|
||||
checkTagsInTagsFilter(tagsToOverwrite, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
// check that only new tags are in the tag filter
|
||||
checkTagsInTagsFilter(tagsToOverwrite, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
});
|
||||
});
|
||||
|
||||
it('Delete tags from custom rules', () => {
|
||||
const tagsToDelete = prePopulatedTags.slice(0, 1);
|
||||
const resultingTags = prePopulatedTags.slice(1);
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
const tagsToDelete = prePopulatedTags.slice(0, 1);
|
||||
const resultingTags = prePopulatedTags.slice(1);
|
||||
|
||||
// check if only pre-populated tags exist in the tags filter
|
||||
checkTagsInTagsFilter(prePopulatedTags, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
// check if only pre-populated tags exist in the tags filter
|
||||
checkTagsInTagsFilter(prePopulatedTags, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
selectAllRules();
|
||||
|
||||
// open add tags form, check overwrite tags, type tags
|
||||
openBulkEditDeleteTagsForm();
|
||||
typeTags(tagsToDelete);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
// open add tags form, check overwrite tags, type tags
|
||||
openBulkEditDeleteTagsForm();
|
||||
typeTags(tagsToDelete);
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
|
||||
// check tags has been removed from all rules
|
||||
testAllTagsBadges(resultingTags);
|
||||
// check tags has been removed from all rules
|
||||
testAllTagsBadges(resultingTags);
|
||||
|
||||
// check that tags were removed from the tag filter
|
||||
checkTagsInTagsFilter(resultingTags, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
// check that tags were removed from the tag filter
|
||||
checkTagsInTagsFilter(resultingTags, EUI_SELECTABLE_LIST_ITEM_SR_TEXT);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Index patterns', () => {
|
||||
it('Index pattern action applied to custom rules, including machine learning: user proceeds with edit of custom non machine learning rule', () => {
|
||||
const indexPattersToBeAdded = ['index-to-add-1-*', 'index-to-add-2-*'];
|
||||
const resultingIndexPatterns = [...prePopulatedIndexPatterns, ...indexPattersToBeAdded];
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
const indexPattersToBeAdded = ['index-to-add-1-*', 'index-to-add-2-*'];
|
||||
const resultingIndexPatterns = [...prePopulatedIndexPatterns, ...indexPattersToBeAdded];
|
||||
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
clickAddIndexPatternsMenuItem();
|
||||
selectAllRules();
|
||||
clickAddIndexPatternsMenuItem();
|
||||
|
||||
// confirm editing custom rules, that are not Machine Learning
|
||||
checkMachineLearningRulesCannotBeModified(expectedNumberOfMachineLearningRulesToBeEdited);
|
||||
cy.get(MODAL_CONFIRMATION_BTN).click();
|
||||
// confirm editing custom rules, that are not Machine Learning
|
||||
checkMachineLearningRulesCannotBeModified(expectedNumberOfMachineLearningRulesToBeEdited);
|
||||
cy.get(MODAL_CONFIRMATION_BTN).click();
|
||||
|
||||
typeIndexPatterns(indexPattersToBeAdded);
|
||||
submitBulkEditForm();
|
||||
typeIndexPatterns(indexPattersToBeAdded);
|
||||
submitBulkEditForm();
|
||||
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfNotMLRules });
|
||||
waitForBulkEditActionToFinish({
|
||||
updatedCount: rows.length - expectedNumberOfMachineLearningRulesToBeEdited,
|
||||
});
|
||||
|
||||
// check if rule has been updated
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
hasIndexPatterns(resultingIndexPatterns.join(''));
|
||||
// check if rule has been updated
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
hasIndexPatterns(resultingIndexPatterns.join(''));
|
||||
});
|
||||
});
|
||||
|
||||
it('Index pattern action applied to custom rules, including machine learning: user cancels action', () => {
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
selectAllRules();
|
||||
clickAddIndexPatternsMenuItem();
|
||||
|
||||
// confirm editing custom rules, that are not Machine Learning
|
||||
|
@ -370,46 +407,68 @@ describe('Detection rules, bulk edit', () => {
|
|||
});
|
||||
|
||||
it('Add index patterns to custom rules', () => {
|
||||
const indexPattersToBeAdded = ['index-to-add-1-*', 'index-to-add-2-*'];
|
||||
const resultingIndexPatterns = [...prePopulatedIndexPatterns, ...indexPattersToBeAdded];
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
const indexPattersToBeAdded = ['index-to-add-1-*', 'index-to-add-2-*'];
|
||||
const resultingIndexPatterns = [...prePopulatedIndexPatterns, ...indexPattersToBeAdded];
|
||||
|
||||
// select only rules that are not ML
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
unselectRuleByName(getMachineLearningRule().name);
|
||||
// select only rules that are not ML
|
||||
selectRulesByName([
|
||||
RULE_NAME,
|
||||
'New EQL Rule',
|
||||
'Threat Indicator Rule Test',
|
||||
'Threshold Rule',
|
||||
'New Terms Rule',
|
||||
]);
|
||||
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(indexPattersToBeAdded);
|
||||
submitBulkEditForm();
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(indexPattersToBeAdded);
|
||||
submitBulkEditForm();
|
||||
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfNotMLRules });
|
||||
waitForBulkEditActionToFinish({
|
||||
updatedCount: rows.length - expectedNumberOfMachineLearningRulesToBeEdited,
|
||||
});
|
||||
|
||||
// check if rule has been updated
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
hasIndexPatterns(resultingIndexPatterns.join(''));
|
||||
// check if rule has been updated
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
hasIndexPatterns(resultingIndexPatterns.join(''));
|
||||
});
|
||||
});
|
||||
|
||||
it('Display success toast after editing the index pattern', () => {
|
||||
const indexPattersToBeAdded = ['index-to-add-1-*', 'index-to-add-2-*'];
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
const indexPattersToBeAdded = ['index-to-add-1-*', 'index-to-add-2-*'];
|
||||
|
||||
// select only rules that are not ML
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
unselectRuleByName(getMachineLearningRule().name);
|
||||
// select only rules that are not ML
|
||||
selectRulesByName([
|
||||
RULE_NAME,
|
||||
'New EQL Rule',
|
||||
'Threat Indicator Rule Test',
|
||||
'Threshold Rule',
|
||||
'New Terms Rule',
|
||||
]);
|
||||
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(indexPattersToBeAdded);
|
||||
submitBulkEditForm();
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(indexPattersToBeAdded);
|
||||
submitBulkEditForm();
|
||||
|
||||
waitForBulkEditActionToFinish({
|
||||
updatedCount: expectedNumberOfNotMLRules,
|
||||
waitForBulkEditActionToFinish({
|
||||
updatedCount: rows.length - expectedNumberOfMachineLearningRulesToBeEdited,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Overwrite index patterns in custom rules', () => {
|
||||
const rulesToSelect = [
|
||||
RULE_NAME,
|
||||
'New EQL Rule',
|
||||
'Threat Indicator Rule Test',
|
||||
'Threshold Rule',
|
||||
'New Terms Rule',
|
||||
] as const;
|
||||
const indexPattersToWrite = ['index-to-write-1-*', 'index-to-write-2-*'];
|
||||
|
||||
// select only rules that are not ML
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
unselectRuleByName(getMachineLearningRule().name);
|
||||
selectRulesByName(rulesToSelect);
|
||||
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
|
||||
|
@ -417,13 +476,13 @@ describe('Detection rules, bulk edit', () => {
|
|||
checkOverwriteIndexPatternsCheckbox();
|
||||
cy.get(RULES_BULK_EDIT_INDEX_PATTERNS_WARNING).should(
|
||||
'have.text',
|
||||
`You’re about to overwrite index patterns for ${expectedNumberOfNotMLRules} selected rules, press Save to apply changes.`
|
||||
`You’re about to overwrite index patterns for ${rulesToSelect.length} selected rules, press Save to apply changes.`
|
||||
);
|
||||
|
||||
typeIndexPatterns(indexPattersToWrite);
|
||||
submitBulkEditForm();
|
||||
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfNotMLRules });
|
||||
waitForBulkEditActionToFinish({ updatedCount: rulesToSelect.length });
|
||||
|
||||
// check if rule has been updated
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
|
@ -431,18 +490,24 @@ describe('Detection rules, bulk edit', () => {
|
|||
});
|
||||
|
||||
it('Delete index patterns from custom rules', () => {
|
||||
const rulesToSelect = [
|
||||
RULE_NAME,
|
||||
'New EQL Rule',
|
||||
'Threat Indicator Rule Test',
|
||||
'Threshold Rule',
|
||||
'New Terms Rule',
|
||||
] as const;
|
||||
const indexPatternsToDelete = prePopulatedIndexPatterns.slice(0, 1);
|
||||
const resultingIndexPatterns = prePopulatedIndexPatterns.slice(1);
|
||||
|
||||
// select only not ML rules
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
unselectRuleByName(getMachineLearningRule().name);
|
||||
selectRulesByName(rulesToSelect);
|
||||
|
||||
openBulkEditDeleteIndexPatternsForm();
|
||||
typeIndexPatterns(indexPatternsToDelete);
|
||||
submitBulkEditForm();
|
||||
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfNotMLRules });
|
||||
waitForBulkEditActionToFinish({ updatedCount: rulesToSelect.length });
|
||||
|
||||
// check if rule has been updated
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
|
@ -450,16 +515,23 @@ describe('Detection rules, bulk edit', () => {
|
|||
});
|
||||
|
||||
it('Delete all index patterns from custom rules', () => {
|
||||
const rulesToSelect = [
|
||||
RULE_NAME,
|
||||
'New EQL Rule',
|
||||
'Threat Indicator Rule Test',
|
||||
'Threshold Rule',
|
||||
'New Terms Rule',
|
||||
] as const;
|
||||
|
||||
// select only rules that are not ML
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
unselectRuleByName(getMachineLearningRule().name);
|
||||
selectRulesByName(rulesToSelect);
|
||||
|
||||
openBulkEditDeleteIndexPatternsForm();
|
||||
typeIndexPatterns(prePopulatedIndexPatterns);
|
||||
submitBulkEditForm();
|
||||
|
||||
// error toast should be displayed that that rules edit failed
|
||||
waitForBulkEditActionToFinish({ failedCount: expectedNumberOfNotMLRules });
|
||||
waitForBulkEditActionToFinish({ failedCount: rulesToSelect.length });
|
||||
|
||||
// on error toast button click display error that index patterns can't be empty
|
||||
clickErrorToastBtn();
|
||||
|
@ -473,97 +545,107 @@ describe('Detection rules, bulk edit', () => {
|
|||
});
|
||||
|
||||
it('Apply timeline template to custom rules', () => {
|
||||
const timelineTemplateName = 'Generic Endpoint Timeline';
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
const timelineTemplateName = 'Generic Endpoint Timeline';
|
||||
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
selectAllRules();
|
||||
|
||||
// open Timeline template form, check warning, select timeline template
|
||||
clickApplyTimelineTemplatesMenuItem();
|
||||
cy.get(RULES_BULK_EDIT_TIMELINE_TEMPLATES_WARNING).contains(
|
||||
`You're about to apply changes to ${expectedNumberOfCustomRulesToBeEdited} selected rules. If you previously applied Timeline templates to these rules, they will be overwritten or (if you select 'None') reset to none.`
|
||||
);
|
||||
selectTimelineTemplate(timelineTemplateName);
|
||||
// open Timeline template form, check warning, select timeline template
|
||||
clickApplyTimelineTemplatesMenuItem();
|
||||
cy.get(RULES_BULK_EDIT_TIMELINE_TEMPLATES_WARNING).contains(
|
||||
`You're about to apply changes to ${rows.length} selected rules. If you previously applied Timeline templates to these rules, they will be overwritten or (if you select 'None') reset to none.`
|
||||
);
|
||||
selectTimelineTemplate(timelineTemplateName);
|
||||
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
|
||||
// check if timeline template has been updated to selected one
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', timelineTemplateName);
|
||||
// check if timeline template has been updated to selected one
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', timelineTemplateName);
|
||||
});
|
||||
});
|
||||
|
||||
it('Reset timeline template to None for custom rules', () => {
|
||||
const noneTimelineTemplate = 'None';
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
const noneTimelineTemplate = 'None';
|
||||
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
selectAllRules();
|
||||
|
||||
// open Timeline template form, submit form without picking timeline template as None is selected by default
|
||||
clickApplyTimelineTemplatesMenuItem();
|
||||
// open Timeline template form, submit form without picking timeline template as None is selected by default
|
||||
clickApplyTimelineTemplatesMenuItem();
|
||||
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
submitBulkEditForm();
|
||||
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);
|
||||
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', noneTimelineTemplate);
|
||||
// check if timeline template has been updated to selected one, by opening rule that have had timeline prior to editing
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', noneTimelineTemplate);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Schedule', () => {
|
||||
it('Default values are applied to bulk edit schedule fields', () => {
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
clickUpdateScheduleMenuItem();
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
selectAllRules();
|
||||
clickUpdateScheduleMenuItem();
|
||||
|
||||
assertUpdateScheduleWarningExists(expectedNumberOfCustomRulesToBeEdited);
|
||||
assertUpdateScheduleWarningExists(rows.length);
|
||||
|
||||
assertDefaultValuesAreAppliedToScheduleFields({
|
||||
interval: 5,
|
||||
lookback: 1,
|
||||
assertDefaultValuesAreAppliedToScheduleFields({
|
||||
interval: 5,
|
||||
lookback: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Updates schedule for custom rules', () => {
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
clickUpdateScheduleMenuItem();
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
selectAllRules();
|
||||
clickUpdateScheduleMenuItem();
|
||||
|
||||
assertUpdateScheduleWarningExists(expectedNumberOfCustomRulesToBeEdited);
|
||||
assertUpdateScheduleWarningExists(rows.length);
|
||||
|
||||
typeScheduleInterval('20');
|
||||
setScheduleIntervalTimeUnit('Hours');
|
||||
typeScheduleInterval('20');
|
||||
setScheduleIntervalTimeUnit('Hours');
|
||||
|
||||
typeScheduleLookback('10');
|
||||
setScheduleLookbackTimeUnit('Minutes');
|
||||
typeScheduleLookback('10');
|
||||
setScheduleLookbackTimeUnit('Minutes');
|
||||
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
|
||||
assertRuleScheduleValues({
|
||||
interval: '20h',
|
||||
lookback: '10m',
|
||||
assertRuleScheduleValues({
|
||||
interval: '20h',
|
||||
lookback: '10m',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Validates invalid inputs when scheduling for custom rules', () => {
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
clickUpdateScheduleMenuItem();
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
selectAllRules();
|
||||
clickUpdateScheduleMenuItem();
|
||||
|
||||
// Validate invalid values are corrected to minimumValue - for 0 and negative values
|
||||
typeScheduleInterval('0');
|
||||
setScheduleIntervalTimeUnit('Hours');
|
||||
// Validate invalid values are corrected to minimumValue - for 0 and negative values
|
||||
typeScheduleInterval('0');
|
||||
setScheduleIntervalTimeUnit('Hours');
|
||||
|
||||
typeScheduleLookback('-5');
|
||||
setScheduleLookbackTimeUnit('Seconds');
|
||||
typeScheduleLookback('-5');
|
||||
setScheduleLookbackTimeUnit('Seconds');
|
||||
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
goToTheRuleDetailsOf(RULE_NAME);
|
||||
|
||||
assertRuleScheduleValues({
|
||||
interval: '1h',
|
||||
lookback: '1s',
|
||||
assertRuleScheduleValues({
|
||||
interval: '1h',
|
||||
lookback: '1s',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,82 +7,70 @@
|
|||
|
||||
import type { RuleActionArray } from '@kbn/securitysolution-io-ts-alerting-types';
|
||||
import { ROLES } from '../../../common/test';
|
||||
|
||||
import { createRuleAssetSavedObject } from '../../helpers/rules';
|
||||
import {
|
||||
getNewRule,
|
||||
getEqlRule,
|
||||
getMachineLearningRule,
|
||||
getNewThreatIndicatorRule,
|
||||
getNewThresholdRule,
|
||||
getNewTermsRule,
|
||||
} from '../../objects/rule';
|
||||
import { actionFormSelector } from '../../screens/common/rule_actions';
|
||||
import {
|
||||
ADD_RULE_ACTIONS_MENU_ITEM,
|
||||
RULES_BULK_EDIT_ACTIONS_INFO,
|
||||
RULES_BULK_EDIT_ACTIONS_WARNING,
|
||||
ADD_RULE_ACTIONS_MENU_ITEM,
|
||||
} from '../../screens/rules_bulk_edit';
|
||||
import { actionFormSelector } from '../../screens/common/rule_actions';
|
||||
|
||||
import {
|
||||
expectManagementTableRules,
|
||||
selectAllRules,
|
||||
disableAutoRefresh,
|
||||
getRulesManagementTableRows,
|
||||
goToEditRuleActionsSettingsOf,
|
||||
selectRulesByName,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import { createSlackConnector } from '../../tasks/api_calls/connectors';
|
||||
import {
|
||||
preventPrebuiltRulesPackageInstallation,
|
||||
createAndInstallMockedPrebuiltRules,
|
||||
excessivelyInstallAllPrebuiltRules,
|
||||
} from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { cleanKibana, deleteAlertsAndRules, deleteConnectors } from '../../tasks/common';
|
||||
import { waitForCallOutToBeShown, MISSING_PRIVILEGES_CALLOUT } from '../../tasks/common/callouts';
|
||||
import type { RuleActionCustomFrequency } from '../../tasks/common/rule_actions';
|
||||
import {
|
||||
addSlackRuleAction,
|
||||
pickSummaryOfAlertsOption,
|
||||
pickCustomFrequencyOption,
|
||||
assertSelectedSummaryOfAlertsOption,
|
||||
assertSelectedCustomFrequencyOption,
|
||||
assertSlackRuleAction,
|
||||
pickPerRuleRunFrequencyOption,
|
||||
assertSelectedPerRuleRunFrequencyOption,
|
||||
addEmailConnectorAndRuleAction,
|
||||
assertEmailRuleAction,
|
||||
assertSelectedCustomFrequencyOption,
|
||||
assertSelectedPerRuleRunFrequencyOption,
|
||||
assertSelectedSummaryOfAlertsOption,
|
||||
pickCustomFrequencyOption,
|
||||
pickPerRuleRunFrequencyOption,
|
||||
pickSummaryOfAlertsOption,
|
||||
} from '../../tasks/common/rule_actions';
|
||||
import {
|
||||
waitForRulesTableToBeLoaded,
|
||||
selectNumberOfRules,
|
||||
goToEditRuleActionsSettingsOf,
|
||||
disableAutoRefresh,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import {
|
||||
waitForBulkEditActionToFinish,
|
||||
submitBulkEditForm,
|
||||
checkOverwriteRuleActionsCheckbox,
|
||||
openBulkEditRuleActionsForm,
|
||||
openBulkActionsMenu,
|
||||
} from '../../tasks/rules_bulk_edit';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { createSlackConnector } from '../../tasks/api_calls/connectors';
|
||||
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../tasks/login';
|
||||
import {
|
||||
getEqlRule,
|
||||
getNewThreatIndicatorRule,
|
||||
getNewRule,
|
||||
getNewThresholdRule,
|
||||
getMachineLearningRule,
|
||||
getNewTermsRule,
|
||||
} from '../../objects/rule';
|
||||
import {
|
||||
createAndInstallMockedPrebuiltRules,
|
||||
excessivelyInstallAllPrebuiltRules,
|
||||
preventPrebuiltRulesPackageInstallation,
|
||||
} from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { MISSING_PRIVILEGES_CALLOUT, waitForCallOutToBeShown } from '../../tasks/common/callouts';
|
||||
import { createRuleAssetSavedObject } from '../../helpers/rules';
|
||||
openBulkActionsMenu,
|
||||
openBulkEditRuleActionsForm,
|
||||
submitBulkEditForm,
|
||||
waitForBulkEditActionToFinish,
|
||||
checkOverwriteRuleActionsCheckbox,
|
||||
} from '../../tasks/rules_bulk_edit';
|
||||
|
||||
const ruleNameToAssert = 'Custom rule name with actions';
|
||||
const expectedNumberOfCustomRulesToBeEdited = 7;
|
||||
// 7 custom rules of different types + 3 prebuilt.
|
||||
// number of selected rules doesn't matter, we only want to make sure they will be edited an no modal window displayed as for other actions
|
||||
const expectedNumberOfRulesToBeEdited = expectedNumberOfCustomRulesToBeEdited + 3;
|
||||
|
||||
const expectedExistingSlackMessage = 'Existing slack action';
|
||||
const expectedSlackMessage = 'Slack action test message';
|
||||
|
||||
// TODO: Fix flakiness and unskip https://github.com/elastic/kibana/issues/154721
|
||||
describe.skip('Detection rules, bulk edit of rule actions', () => {
|
||||
before(() => {
|
||||
describe('Detection rules, bulk edit of rule actions', () => {
|
||||
beforeEach(() => {
|
||||
cleanKibana();
|
||||
login();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
deleteAlertsAndRules();
|
||||
deleteConnectors();
|
||||
esArchiverResetKibana();
|
||||
|
@ -104,15 +92,31 @@ describe.skip('Detection rules, bulk edit of rule actions', () => {
|
|||
},
|
||||
];
|
||||
|
||||
createRule(getNewRule({ name: ruleNameToAssert, rule_id: '1', max_signals: 500, actions }));
|
||||
createRule(
|
||||
getNewRule({
|
||||
rule_id: '1',
|
||||
name: ruleNameToAssert,
|
||||
max_signals: 500,
|
||||
actions,
|
||||
enabled: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
createRule(getEqlRule({ rule_id: '2' }));
|
||||
createRule(getMachineLearningRule({ rule_id: '3' }));
|
||||
createRule(getNewThreatIndicatorRule({ rule_id: '4' }));
|
||||
createRule(getNewThresholdRule({ rule_id: '5' }));
|
||||
createRule(getNewTermsRule({ rule_id: '6' }));
|
||||
createRule(getNewRule({ saved_id: 'mocked', rule_id: '7' }));
|
||||
createRule(getEqlRule({ rule_id: '2', name: 'New EQL Rule', enabled: false }));
|
||||
createRule(getMachineLearningRule({ rule_id: '3', name: 'New ML Rule Test', enabled: false }));
|
||||
createRule(
|
||||
getNewThreatIndicatorRule({
|
||||
rule_id: '4',
|
||||
name: 'Threat Indicator Rule Test',
|
||||
enabled: false,
|
||||
})
|
||||
);
|
||||
createRule(getNewThresholdRule({ rule_id: '5', name: 'Threshold Rule', enabled: false }));
|
||||
createRule(getNewTermsRule({ rule_id: '6', name: 'New Terms Rule', enabled: false }));
|
||||
createRule(
|
||||
getNewRule({ saved_id: 'mocked', rule_id: '7', name: 'New Rule Test', enabled: false })
|
||||
);
|
||||
|
||||
createSlackConnector();
|
||||
|
||||
|
@ -134,11 +138,22 @@ describe.skip('Detection rules, bulk edit of rule actions', () => {
|
|||
context('Restricted action privileges', () => {
|
||||
it("User with no privileges can't add rule actions", () => {
|
||||
login(ROLES.hunter_no_actions);
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL, ROLES.hunter_no_actions);
|
||||
waitForCallOutToBeShown(MISSING_PRIVILEGES_CALLOUT, 'primary');
|
||||
waitForRulesTableToBeLoaded();
|
||||
visitSecurityDetectionRulesPage(ROLES.hunter_no_actions);
|
||||
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
expectManagementTableRules([
|
||||
ruleNameToAssert,
|
||||
'New EQL Rule',
|
||||
'New ML Rule Test',
|
||||
'Threat Indicator Rule Test',
|
||||
'Threshold Rule',
|
||||
'New Terms Rule',
|
||||
'New Rule Test',
|
||||
'Test rule 1',
|
||||
'Test rule 2',
|
||||
]);
|
||||
waitForCallOutToBeShown(MISSING_PRIVILEGES_CALLOUT, 'primary');
|
||||
|
||||
selectAllRules();
|
||||
|
||||
openBulkActionsMenu();
|
||||
|
||||
|
@ -149,9 +164,20 @@ describe.skip('Detection rules, bulk edit of rule actions', () => {
|
|||
context('All actions privileges', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
expectManagementTableRules([
|
||||
ruleNameToAssert,
|
||||
'New EQL Rule',
|
||||
'New ML Rule Test',
|
||||
'Threat Indicator Rule Test',
|
||||
'Threshold Rule',
|
||||
'New Terms Rule',
|
||||
'New Rule Test',
|
||||
'Test rule 1',
|
||||
'Test rule 2',
|
||||
]);
|
||||
});
|
||||
|
||||
it('Add a rule action to rules (existing connector)', () => {
|
||||
|
@ -162,62 +188,75 @@ describe.skip('Detection rules, bulk edit of rule actions', () => {
|
|||
|
||||
excessivelyInstallAllPrebuiltRules();
|
||||
|
||||
// select both custom and prebuilt rules
|
||||
selectNumberOfRules(expectedNumberOfRulesToBeEdited);
|
||||
openBulkEditRuleActionsForm();
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
// select both custom and prebuilt rules
|
||||
selectAllRules();
|
||||
openBulkEditRuleActionsForm();
|
||||
|
||||
// ensure rule actions info callout displayed on the form
|
||||
cy.get(RULES_BULK_EDIT_ACTIONS_INFO).should('be.visible');
|
||||
// ensure rule actions info callout displayed on the form
|
||||
cy.get(RULES_BULK_EDIT_ACTIONS_INFO).should('be.visible');
|
||||
|
||||
addSlackRuleAction(expectedSlackMessage);
|
||||
pickSummaryOfAlertsOption();
|
||||
pickCustomFrequencyOption(expectedActionFrequency);
|
||||
addSlackRuleAction(expectedSlackMessage);
|
||||
pickSummaryOfAlertsOption();
|
||||
pickCustomFrequencyOption(expectedActionFrequency);
|
||||
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfRulesToBeEdited });
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
|
||||
// check if rule has been updated
|
||||
goToEditRuleActionsSettingsOf(ruleNameToAssert);
|
||||
// check if rule has been updated
|
||||
goToEditRuleActionsSettingsOf(ruleNameToAssert);
|
||||
|
||||
assertSelectedSummaryOfAlertsOption();
|
||||
assertSelectedCustomFrequencyOption(expectedActionFrequency, 1);
|
||||
assertSlackRuleAction(expectedExistingSlackMessage, 0);
|
||||
assertSlackRuleAction(expectedSlackMessage, 1);
|
||||
// ensure there is no third action
|
||||
cy.get(actionFormSelector(2)).should('not.exist');
|
||||
assertSelectedSummaryOfAlertsOption();
|
||||
assertSelectedCustomFrequencyOption(expectedActionFrequency, 1);
|
||||
assertSlackRuleAction(expectedExistingSlackMessage, 0);
|
||||
assertSlackRuleAction(expectedSlackMessage, 1);
|
||||
// ensure there is no third action
|
||||
cy.get(actionFormSelector(2)).should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('Overwrite rule actions in rules', () => {
|
||||
excessivelyInstallAllPrebuiltRules();
|
||||
|
||||
// select both custom and prebuilt rules
|
||||
selectNumberOfRules(expectedNumberOfRulesToBeEdited);
|
||||
openBulkEditRuleActionsForm();
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
// select both custom and prebuilt rules
|
||||
selectAllRules();
|
||||
openBulkEditRuleActionsForm();
|
||||
|
||||
addSlackRuleAction(expectedSlackMessage);
|
||||
pickSummaryOfAlertsOption();
|
||||
pickPerRuleRunFrequencyOption();
|
||||
addSlackRuleAction(expectedSlackMessage);
|
||||
pickSummaryOfAlertsOption();
|
||||
pickPerRuleRunFrequencyOption();
|
||||
|
||||
// check overwrite box, ensure warning is displayed
|
||||
checkOverwriteRuleActionsCheckbox();
|
||||
cy.get(RULES_BULK_EDIT_ACTIONS_WARNING).contains(
|
||||
`You're about to overwrite rule actions for ${expectedNumberOfRulesToBeEdited} selected rules`
|
||||
);
|
||||
// check overwrite box, ensure warning is displayed
|
||||
checkOverwriteRuleActionsCheckbox();
|
||||
cy.get(RULES_BULK_EDIT_ACTIONS_WARNING).contains(
|
||||
`You're about to overwrite rule actions for ${rows.length} selected rules`
|
||||
);
|
||||
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfRulesToBeEdited });
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
|
||||
// check if rule has been updated
|
||||
goToEditRuleActionsSettingsOf(ruleNameToAssert);
|
||||
// check if rule has been updated
|
||||
goToEditRuleActionsSettingsOf(ruleNameToAssert);
|
||||
|
||||
assertSelectedSummaryOfAlertsOption();
|
||||
assertSelectedPerRuleRunFrequencyOption();
|
||||
assertSlackRuleAction(expectedSlackMessage);
|
||||
// ensure existing action was overwritten
|
||||
cy.get(actionFormSelector(1)).should('not.exist');
|
||||
assertSelectedSummaryOfAlertsOption();
|
||||
assertSelectedPerRuleRunFrequencyOption();
|
||||
assertSlackRuleAction(expectedSlackMessage);
|
||||
// ensure existing action was overwritten
|
||||
cy.get(actionFormSelector(1)).should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
it('Add a rule action to rules (new connector)', () => {
|
||||
const rulesToSelect = [
|
||||
ruleNameToAssert,
|
||||
'New EQL Rule',
|
||||
'New ML Rule Test',
|
||||
'Threat Indicator Rule Test',
|
||||
'Threshold Rule',
|
||||
'New Terms Rule',
|
||||
'New Rule Test',
|
||||
] as const;
|
||||
const expectedActionFrequency: RuleActionCustomFrequency = {
|
||||
throttle: 2,
|
||||
throttleUnit: 'h',
|
||||
|
@ -225,7 +264,7 @@ describe.skip('Detection rules, bulk edit of rule actions', () => {
|
|||
const expectedEmail = 'test@example.com';
|
||||
const expectedSubject = 'Subject';
|
||||
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
selectRulesByName(rulesToSelect);
|
||||
openBulkEditRuleActionsForm();
|
||||
|
||||
addEmailConnectorAndRuleAction(expectedEmail, expectedSubject);
|
||||
|
@ -233,7 +272,7 @@ describe.skip('Detection rules, bulk edit of rule actions', () => {
|
|||
pickCustomFrequencyOption(expectedActionFrequency);
|
||||
|
||||
submitBulkEditForm();
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
waitForBulkEditActionToFinish({ updatedCount: rulesToSelect.length });
|
||||
|
||||
// check if rule has been updated
|
||||
goToEditRuleActionsSettingsOf(ruleNameToAssert);
|
||||
|
|
|
@ -6,52 +6,44 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
RULES_BULK_EDIT_DATA_VIEWS_WARNING,
|
||||
RULES_BULK_EDIT_OVERWRITE_DATA_VIEW_CHECKBOX,
|
||||
} from '../../screens/rules_bulk_edit';
|
||||
|
||||
import { DATA_VIEW_DETAILS, INDEX_PATTERNS_DETAILS } from '../../screens/rule_details';
|
||||
|
||||
import {
|
||||
waitForRulesTableToBeLoaded,
|
||||
goToRuleDetails,
|
||||
selectNumberOfRules,
|
||||
goToTheRuleDetailsOf,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
|
||||
import {
|
||||
typeIndexPatterns,
|
||||
waitForBulkEditActionToFinish,
|
||||
submitBulkEditForm,
|
||||
checkOverwriteDataViewCheckbox,
|
||||
checkOverwriteIndexPatternsCheckbox,
|
||||
openBulkEditAddIndexPatternsForm,
|
||||
openBulkEditDeleteIndexPatternsForm,
|
||||
} from '../../tasks/rules_bulk_edit';
|
||||
|
||||
import { hasIndexPatterns, getDetails, assertDetailsNotExist } from '../../tasks/rule_details';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { cleanKibana, deleteAlertsAndRules, postDataView } from '../../tasks/common';
|
||||
|
||||
import {
|
||||
getNewRule,
|
||||
getEqlRule,
|
||||
getNewThreatIndicatorRule,
|
||||
getNewRule,
|
||||
getNewThresholdRule,
|
||||
getNewTermsRule,
|
||||
} from '../../objects/rule';
|
||||
|
||||
import {
|
||||
RULES_BULK_EDIT_DATA_VIEWS_WARNING,
|
||||
RULES_BULK_EDIT_OVERWRITE_DATA_VIEW_CHECKBOX,
|
||||
} from '../../screens/rules_bulk_edit';
|
||||
import { DATA_VIEW_DETAILS, INDEX_PATTERNS_DETAILS } from '../../screens/rule_details';
|
||||
import {
|
||||
disableAutoRefresh,
|
||||
expectManagementTableRules,
|
||||
getRulesManagementTableRows,
|
||||
selectAllRules,
|
||||
goToRuleDetails,
|
||||
goToTheRuleDetailsOf,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { cleanKibana, deleteAlertsAndRules, postDataView } from '../../tasks/common';
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../tasks/login';
|
||||
import {
|
||||
openBulkEditAddIndexPatternsForm,
|
||||
typeIndexPatterns,
|
||||
submitBulkEditForm,
|
||||
waitForBulkEditActionToFinish,
|
||||
checkOverwriteDataViewCheckbox,
|
||||
checkOverwriteIndexPatternsCheckbox,
|
||||
openBulkEditDeleteIndexPatternsForm,
|
||||
} from '../../tasks/rules_bulk_edit';
|
||||
import { getDetails, assertDetailsNotExist, hasIndexPatterns } from '../../tasks/rule_details';
|
||||
|
||||
const DATA_VIEW_ID = 'auditbeat';
|
||||
|
||||
const expectedIndexPatterns = ['index-1-*', 'index-2-*'];
|
||||
|
||||
const expectedNumberOfCustomRulesToBeEdited = 6;
|
||||
|
||||
describe('Bulk editing index patterns of rules with a data view only', () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
|
@ -64,123 +56,184 @@ describe('Bulk editing index patterns of rules with a data view only', () => {
|
|||
|
||||
postDataView(DATA_VIEW_ID);
|
||||
|
||||
createRule(getNewRule({ index: undefined, data_view_id: DATA_VIEW_ID, rule_id: '1' }));
|
||||
createRule(getEqlRule({ index: undefined, data_view_id: DATA_VIEW_ID, rule_id: '2' }));
|
||||
createRule(
|
||||
getNewThreatIndicatorRule({ index: undefined, data_view_id: DATA_VIEW_ID, rule_id: '3' })
|
||||
getNewRule({
|
||||
index: undefined,
|
||||
data_view_id: DATA_VIEW_ID,
|
||||
rule_id: '1',
|
||||
name: 'New Rule Test 1',
|
||||
enabled: false,
|
||||
})
|
||||
);
|
||||
createRule(getNewThresholdRule({ index: undefined, data_view_id: DATA_VIEW_ID, rule_id: '4' }));
|
||||
createRule(getNewTermsRule({ index: undefined, data_view_id: DATA_VIEW_ID, rule_id: '5' }));
|
||||
createRule(
|
||||
getNewRule({ index: undefined, data_view_id: DATA_VIEW_ID, saved_id: 'mocked', rule_id: '6' })
|
||||
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,
|
||||
})
|
||||
);
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
waitForRulesTableToBeLoaded();
|
||||
expectManagementTableRules([
|
||||
'New Rule Test 1',
|
||||
'New EQL Rule',
|
||||
'Threat Indicator Rule Test',
|
||||
'Threshold Rule',
|
||||
'New Terms Rule',
|
||||
'New Rule Test 2',
|
||||
]);
|
||||
});
|
||||
|
||||
it('Add index patterns to custom rules with configured data view: all rules are skipped', () => {
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
selectAllRules();
|
||||
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
submitBulkEditForm();
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
submitBulkEditForm();
|
||||
|
||||
waitForBulkEditActionToFinish({
|
||||
skippedCount: expectedNumberOfCustomRulesToBeEdited,
|
||||
showDataViewsWarning: true,
|
||||
waitForBulkEditActionToFinish({
|
||||
skippedCount: rows.length,
|
||||
showDataViewsWarning: true,
|
||||
});
|
||||
|
||||
// check if rule still has data view and index patterns field does not exist
|
||||
goToRuleDetails();
|
||||
getDetails(DATA_VIEW_DETAILS).contains(DATA_VIEW_ID);
|
||||
assertDetailsNotExist(INDEX_PATTERNS_DETAILS);
|
||||
});
|
||||
|
||||
// check if rule still has data view and index patterns field does not exist
|
||||
goToRuleDetails();
|
||||
getDetails(DATA_VIEW_DETAILS).contains(DATA_VIEW_ID);
|
||||
assertDetailsNotExist(INDEX_PATTERNS_DETAILS);
|
||||
});
|
||||
|
||||
it('Add index patterns to custom rules with configured data view when data view checkbox is checked: rules are updated', () => {
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
selectAllRules();
|
||||
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
|
||||
// click on data view overwrite checkbox, ensure warning is displayed
|
||||
cy.get(RULES_BULK_EDIT_DATA_VIEWS_WARNING).should('not.exist');
|
||||
checkOverwriteDataViewCheckbox();
|
||||
cy.get(RULES_BULK_EDIT_DATA_VIEWS_WARNING).should('be.visible');
|
||||
// click on data view overwrite checkbox, ensure warning is displayed
|
||||
cy.get(RULES_BULK_EDIT_DATA_VIEWS_WARNING).should('not.exist');
|
||||
checkOverwriteDataViewCheckbox();
|
||||
cy.get(RULES_BULK_EDIT_DATA_VIEWS_WARNING).should('be.visible');
|
||||
|
||||
submitBulkEditForm();
|
||||
submitBulkEditForm();
|
||||
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
|
||||
// check if rule has been updated with index patterns and data view does not exist
|
||||
goToRuleDetails();
|
||||
hasIndexPatterns(expectedIndexPatterns.join(''));
|
||||
assertDetailsNotExist(DATA_VIEW_DETAILS);
|
||||
// check if rule has been updated with index patterns and data view does not exist
|
||||
goToRuleDetails();
|
||||
hasIndexPatterns(expectedIndexPatterns.join(''));
|
||||
assertDetailsNotExist(DATA_VIEW_DETAILS);
|
||||
});
|
||||
});
|
||||
|
||||
it('Overwrite index patterns in custom rules with configured data view when overwrite data view checkbox is NOT checked:: rules are skipped', () => {
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
selectAllRules();
|
||||
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
checkOverwriteIndexPatternsCheckbox();
|
||||
submitBulkEditForm();
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
checkOverwriteIndexPatternsCheckbox();
|
||||
submitBulkEditForm();
|
||||
|
||||
waitForBulkEditActionToFinish({
|
||||
skippedCount: expectedNumberOfCustomRulesToBeEdited,
|
||||
showDataViewsWarning: true,
|
||||
waitForBulkEditActionToFinish({
|
||||
skippedCount: rows.length,
|
||||
showDataViewsWarning: true,
|
||||
});
|
||||
|
||||
// check if rule still has data view and index patterns field does not exist
|
||||
goToRuleDetails();
|
||||
getDetails(DATA_VIEW_DETAILS).contains(DATA_VIEW_ID);
|
||||
assertDetailsNotExist(INDEX_PATTERNS_DETAILS);
|
||||
});
|
||||
|
||||
// check if rule still has data view and index patterns field does not exist
|
||||
goToRuleDetails();
|
||||
getDetails(DATA_VIEW_DETAILS).contains(DATA_VIEW_ID);
|
||||
assertDetailsNotExist(INDEX_PATTERNS_DETAILS);
|
||||
});
|
||||
|
||||
it('Overwrite index patterns in custom rules with configured data view when overwrite data view checkbox is checked: rules are updated', () => {
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
selectAllRules();
|
||||
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
checkOverwriteIndexPatternsCheckbox();
|
||||
checkOverwriteDataViewCheckbox();
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
checkOverwriteIndexPatternsCheckbox();
|
||||
checkOverwriteDataViewCheckbox();
|
||||
|
||||
submitBulkEditForm();
|
||||
submitBulkEditForm();
|
||||
|
||||
waitForBulkEditActionToFinish({ updatedCount: expectedNumberOfCustomRulesToBeEdited });
|
||||
waitForBulkEditActionToFinish({ updatedCount: rows.length });
|
||||
|
||||
// check if rule has been overwritten with index patterns and data view does not exist
|
||||
goToRuleDetails();
|
||||
hasIndexPatterns(expectedIndexPatterns.join(''));
|
||||
assertDetailsNotExist(DATA_VIEW_DETAILS);
|
||||
// check if rule has been overwritten with index patterns and data view does not exist
|
||||
goToRuleDetails();
|
||||
hasIndexPatterns(expectedIndexPatterns.join(''));
|
||||
assertDetailsNotExist(DATA_VIEW_DETAILS);
|
||||
});
|
||||
});
|
||||
|
||||
it('Delete index patterns in custom rules with configured data view: rules are skipped', () => {
|
||||
selectNumberOfRules(expectedNumberOfCustomRulesToBeEdited);
|
||||
getRulesManagementTableRows().then((rows) => {
|
||||
selectAllRules();
|
||||
|
||||
openBulkEditDeleteIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
openBulkEditDeleteIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
|
||||
// in delete form data view checkbox is absent
|
||||
cy.get(RULES_BULK_EDIT_OVERWRITE_DATA_VIEW_CHECKBOX).should('not.exist');
|
||||
// in delete form data view checkbox is absent
|
||||
cy.get(RULES_BULK_EDIT_OVERWRITE_DATA_VIEW_CHECKBOX).should('not.exist');
|
||||
|
||||
submitBulkEditForm();
|
||||
submitBulkEditForm();
|
||||
|
||||
waitForBulkEditActionToFinish({
|
||||
skippedCount: expectedNumberOfCustomRulesToBeEdited,
|
||||
showDataViewsWarning: true,
|
||||
waitForBulkEditActionToFinish({
|
||||
skippedCount: rows.length,
|
||||
showDataViewsWarning: true,
|
||||
});
|
||||
|
||||
// check if rule still has data view and index patterns field does not exist
|
||||
goToRuleDetails();
|
||||
getDetails(DATA_VIEW_DETAILS).contains(DATA_VIEW_ID);
|
||||
});
|
||||
|
||||
// check if rule still has data view and index patterns field does not exist
|
||||
goToRuleDetails();
|
||||
getDetails(DATA_VIEW_DETAILS).contains(DATA_VIEW_ID);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Bulk editing index patterns of rules with index patterns and rules with a data view', () => {
|
||||
const customRulesNumber = 2;
|
||||
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
@ -197,13 +250,14 @@ describe('Bulk editing index patterns of rules with index patterns and rules wit
|
|||
);
|
||||
createRule(getNewRule({ name: 'no data view', index: ['test-index-1-*'], rule_id: '2' }));
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
waitForRulesTableToBeLoaded();
|
||||
expectManagementTableRules(['with dataview', 'no data view']);
|
||||
});
|
||||
|
||||
it('Add index patterns to custom rules: one rule is updated, one rule is skipped', () => {
|
||||
selectNumberOfRules(customRulesNumber);
|
||||
selectAllRules();
|
||||
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
|
@ -222,7 +276,7 @@ describe('Bulk editing index patterns of rules with index patterns and rules wit
|
|||
});
|
||||
|
||||
it('Add index patterns to custom rules when overwrite data view checkbox is checked: all rules are updated', () => {
|
||||
selectNumberOfRules(customRulesNumber);
|
||||
selectAllRules();
|
||||
|
||||
openBulkEditAddIndexPatternsForm();
|
||||
typeIndexPatterns(expectedIndexPatterns);
|
||||
|
|
|
@ -5,118 +5,113 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { removeExternalLinkText } from '@kbn/securitysolution-io-ts-utils';
|
||||
import { ruleFields } from '../../data/detection_engine';
|
||||
import { getNewRule, getExistingRule, getEditedRule, getNewOverrideRule } from '../../objects/rule';
|
||||
import { getNewRule, getNewOverrideRule, getExistingRule, getEditedRule } from '../../objects/rule';
|
||||
import { getTimeline } from '../../objects/timeline';
|
||||
import { ALERTS_COUNT, ALERT_GRID_CELL } from '../../screens/alerts';
|
||||
|
||||
import {
|
||||
CUSTOM_RULES_BTN,
|
||||
RISK_SCORE,
|
||||
RULE_NAME,
|
||||
RULES_ROW,
|
||||
RULES_MANAGEMENT_TABLE,
|
||||
RULE_SWITCH,
|
||||
RISK_SCORE,
|
||||
SEVERITY,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
ALERTS_COUNT,
|
||||
ALERT_GRID_CELL,
|
||||
} from '../../screens/alerts';
|
||||
import { CUSTOM_RULES_BTN, RULES_MANAGEMENT_TABLE } from '../../screens/alerts_detection_rules';
|
||||
import {
|
||||
ACTIONS_NOTIFY_WHEN_BUTTON,
|
||||
ACTIONS_SUMMARY_BUTTON,
|
||||
ACTIONS_NOTIFY_WHEN_BUTTON,
|
||||
} from '../../screens/common/rule_actions';
|
||||
import {
|
||||
ABOUT_CONTINUE_BTN,
|
||||
ABOUT_EDIT_BUTTON,
|
||||
CUSTOM_QUERY_INPUT,
|
||||
DEFINE_CONTINUE_BUTTON,
|
||||
ABOUT_CONTINUE_BTN,
|
||||
DEFINE_EDIT_BUTTON,
|
||||
DEFINE_INDEX_INPUT,
|
||||
DEFAULT_RISK_SCORE_INPUT,
|
||||
RULE_DESCRIPTION_INPUT,
|
||||
CUSTOM_QUERY_INPUT,
|
||||
ABOUT_EDIT_BUTTON,
|
||||
RULE_NAME_INPUT,
|
||||
SCHEDULE_CONTINUE_BUTTON,
|
||||
DEFINE_INDEX_INPUT,
|
||||
RULE_DESCRIPTION_INPUT,
|
||||
TAGS_FIELD,
|
||||
SEVERITY_DROPDOWN,
|
||||
DEFAULT_RISK_SCORE_INPUT,
|
||||
SCHEDULE_INTERVAL_AMOUNT_INPUT,
|
||||
SCHEDULE_INTERVAL_UNITS_INPUT,
|
||||
SCHEDULE_CONTINUE_BUTTON,
|
||||
SEVERITY_DROPDOWN,
|
||||
TAGS_CLEAR_BUTTON,
|
||||
TAGS_FIELD,
|
||||
} from '../../screens/create_new_rule';
|
||||
import {
|
||||
ADDITIONAL_LOOK_BACK_DETAILS,
|
||||
ABOUT_DETAILS,
|
||||
ABOUT_INVESTIGATION_NOTES,
|
||||
ABOUT_RULE_DESCRIPTION,
|
||||
CUSTOM_QUERY_DETAILS,
|
||||
DEFINITION_DETAILS,
|
||||
FALSE_POSITIVES_DETAILS,
|
||||
removeExternalLinkText,
|
||||
INDEX_PATTERNS_DETAILS,
|
||||
INVESTIGATION_NOTES_MARKDOWN,
|
||||
INVESTIGATION_NOTES_TOGGLE,
|
||||
REFERENCE_URLS_DETAILS,
|
||||
RISK_SCORE_DETAILS,
|
||||
RULE_SWITCH,
|
||||
RULE_NAME_HEADER,
|
||||
RULE_TYPE_DETAILS,
|
||||
RUNS_EVERY_DETAILS,
|
||||
SCHEDULE_DETAILS,
|
||||
ABOUT_RULE_DESCRIPTION,
|
||||
ABOUT_DETAILS,
|
||||
SEVERITY_DETAILS,
|
||||
RISK_SCORE_DETAILS,
|
||||
REFERENCE_URLS_DETAILS,
|
||||
FALSE_POSITIVES_DETAILS,
|
||||
TAGS_DETAILS,
|
||||
TIMELINE_TEMPLATE_DETAILS,
|
||||
THREAT_TACTIC,
|
||||
THREAT_TECHNIQUE,
|
||||
THREAT_SUBTECHNIQUE,
|
||||
INVESTIGATION_NOTES_TOGGLE,
|
||||
ABOUT_INVESTIGATION_NOTES,
|
||||
INVESTIGATION_NOTES_MARKDOWN,
|
||||
DEFINITION_DETAILS,
|
||||
INDEX_PATTERNS_DETAILS,
|
||||
CUSTOM_QUERY_DETAILS,
|
||||
RULE_TYPE_DETAILS,
|
||||
TIMELINE_TEMPLATE_DETAILS,
|
||||
SCHEDULE_DETAILS,
|
||||
RUNS_EVERY_DETAILS,
|
||||
ADDITIONAL_LOOK_BACK_DETAILS,
|
||||
} from '../../screens/rule_details';
|
||||
|
||||
import {
|
||||
deleteFirstRule,
|
||||
deleteRuleFromDetailsPage,
|
||||
deleteSelectedRules,
|
||||
editFirstRule,
|
||||
expectManagementTableRules,
|
||||
goToRuleDetails,
|
||||
selectNumberOfRules,
|
||||
getRulesManagementTableRows,
|
||||
deleteFirstRule,
|
||||
selectRulesByName,
|
||||
goToTheRuleDetailsOf,
|
||||
deleteRuleFromDetailsPage,
|
||||
editFirstRule,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { createTimeline } from '../../tasks/api_calls/timelines';
|
||||
import { cleanKibana, deleteAlertsAndRules, deleteConnectors } from '../../tasks/common';
|
||||
import { deleteAlertsAndRules, deleteConnectors } from '../../tasks/common';
|
||||
import { addEmailConnectorAndRuleAction } from '../../tasks/common/rule_actions';
|
||||
import {
|
||||
createAndEnableRule,
|
||||
expandAdvancedSettings,
|
||||
fillAboutRule,
|
||||
fillDescription,
|
||||
fillFalsePositiveExamples,
|
||||
fillFrom,
|
||||
fillNote,
|
||||
fillReferenceUrls,
|
||||
fillRiskScore,
|
||||
fillRuleName,
|
||||
fillRuleTags,
|
||||
fillSeverity,
|
||||
fillThreat,
|
||||
fillThreatSubtechnique,
|
||||
fillThreatTechnique,
|
||||
goToAboutStepTab,
|
||||
goToActionsStepTab,
|
||||
goToScheduleStepTab,
|
||||
importSavedQuery,
|
||||
fillRuleName,
|
||||
fillDescription,
|
||||
fillSeverity,
|
||||
fillRiskScore,
|
||||
fillRuleTags,
|
||||
expandAdvancedSettings,
|
||||
fillReferenceUrls,
|
||||
fillFalsePositiveExamples,
|
||||
fillThreat,
|
||||
fillThreatTechnique,
|
||||
fillThreatSubtechnique,
|
||||
fillNote,
|
||||
fillFrom,
|
||||
createAndEnableRule,
|
||||
waitForAlertsToPopulate,
|
||||
waitForTheRuleToBeExecuted,
|
||||
goToAboutStepTab,
|
||||
goToScheduleStepTab,
|
||||
goToActionsStepTab,
|
||||
fillAboutRule,
|
||||
} from '../../tasks/create_new_rule';
|
||||
import { saveEditedRule } from '../../tasks/edit_rule';
|
||||
import { login, visit } from '../../tasks/login';
|
||||
import { enablesRule, getDetails } from '../../tasks/rule_details';
|
||||
|
||||
import { RULE_CREATION, DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation';
|
||||
import { login, visit, visitSecurityDetectionRulesPage } from '../../tasks/login';
|
||||
import { deleteSelectedRules } from '../../tasks/rules_bulk_edit';
|
||||
import { getDetails, waitForTheRuleToBeExecuted, enablesRule } from '../../tasks/rule_details';
|
||||
import { RULE_CREATION } from '../../urls/navigation';
|
||||
|
||||
describe('Custom query rules', () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
beforeEach(() => {
|
||||
deleteAlertsAndRules();
|
||||
});
|
||||
|
||||
describe('Custom detection rules creation', () => {
|
||||
const expectedNumberOfRules = 1;
|
||||
|
||||
beforeEach(() => {
|
||||
deleteAlertsAndRules();
|
||||
createTimeline(getTimeline())
|
||||
.then((response) => {
|
||||
return response.body.data.persistTimeline.timeline.savedObjectId;
|
||||
|
@ -133,7 +128,7 @@ describe('Custom query rules', () => {
|
|||
cy.get(DEFINE_CONTINUE_BUTTON).click();
|
||||
|
||||
cy.log('Filling about section');
|
||||
fillRuleName();
|
||||
fillRuleName('Test Rule');
|
||||
fillDescription();
|
||||
fillSeverity();
|
||||
fillRiskScore();
|
||||
|
@ -167,7 +162,7 @@ describe('Custom query rules', () => {
|
|||
cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)');
|
||||
|
||||
cy.log('Asserting rule view in rules list');
|
||||
cy.get(RULES_MANAGEMENT_TABLE).find(RULES_ROW).should('have.length', expectedNumberOfRules);
|
||||
expectManagementTableRules(['Test Rule']);
|
||||
cy.get(RULE_NAME).should('have.text', ruleFields.ruleName);
|
||||
cy.get(RISK_SCORE).should('have.text', ruleFields.riskScore);
|
||||
cy.get(SEVERITY)
|
||||
|
@ -234,109 +229,104 @@ describe('Custom query rules', () => {
|
|||
describe('Custom detection rules deletion and edition', () => {
|
||||
context('Deletion', () => {
|
||||
beforeEach(() => {
|
||||
deleteAlertsAndRules();
|
||||
createRule(getNewRule({ rule_id: 'rule1', enabled: true, max_signals: 500 }));
|
||||
createRule(getNewOverrideRule({ rule_id: 'rule2', enabled: true, max_signals: 500 }));
|
||||
createRule(getExistingRule({ rule_id: 'rule3', enabled: true }));
|
||||
createRule(
|
||||
getNewRule({ rule_id: 'rule1', name: 'New Rule Test', enabled: false, max_signals: 500 })
|
||||
);
|
||||
createRule(
|
||||
getNewOverrideRule({
|
||||
rule_id: 'rule2',
|
||||
name: 'Override Rule',
|
||||
enabled: false,
|
||||
max_signals: 500,
|
||||
})
|
||||
);
|
||||
createRule(getExistingRule({ rule_id: 'rule3', name: 'Rule 1', enabled: false }));
|
||||
login();
|
||||
visit(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
});
|
||||
|
||||
it('Deletes one rule', () => {
|
||||
cy.get(RULES_MANAGEMENT_TABLE)
|
||||
.find(RULES_ROW)
|
||||
.then((rules) => {
|
||||
const initialNumberOfRules = rules.length;
|
||||
const expectedNumberOfRulesAfterDeletion = initialNumberOfRules - 1;
|
||||
getRulesManagementTableRows().then((rules) => {
|
||||
const initialNumberOfRules = rules.length;
|
||||
const expectedNumberOfRulesAfterDeletion = initialNumberOfRules - 1;
|
||||
|
||||
cy.request({ url: '/api/detection_engine/rules/_find' }).then(({ body }) => {
|
||||
const numberOfRules = body.data.length;
|
||||
expect(numberOfRules).to.eql(initialNumberOfRules);
|
||||
});
|
||||
|
||||
deleteFirstRule();
|
||||
|
||||
cy.get(RULES_MANAGEMENT_TABLE)
|
||||
.find(RULES_ROW)
|
||||
.should('have.length', expectedNumberOfRulesAfterDeletion);
|
||||
cy.request({ url: '/api/detection_engine/rules/_find' }).then(({ body }) => {
|
||||
const numberOfRules = body.data.length;
|
||||
expect(numberOfRules).to.eql(expectedNumberOfRulesAfterDeletion);
|
||||
});
|
||||
cy.get(CUSTOM_RULES_BTN).should(
|
||||
'have.text',
|
||||
`Custom rules (${expectedNumberOfRulesAfterDeletion})`
|
||||
);
|
||||
cy.request({ url: '/api/detection_engine/rules/_find' }).then(({ body }) => {
|
||||
const numberOfRules = body.data.length;
|
||||
expect(numberOfRules).to.eql(initialNumberOfRules);
|
||||
});
|
||||
|
||||
deleteFirstRule();
|
||||
|
||||
getRulesManagementTableRows().should('have.length', expectedNumberOfRulesAfterDeletion);
|
||||
cy.request({ url: '/api/detection_engine/rules/_find' }).then(({ body }) => {
|
||||
const numberOfRules = body.data.length;
|
||||
expect(numberOfRules).to.eql(expectedNumberOfRulesAfterDeletion);
|
||||
});
|
||||
cy.get(CUSTOM_RULES_BTN).should(
|
||||
'have.text',
|
||||
`Custom rules (${expectedNumberOfRulesAfterDeletion})`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('Deletes more than one rule', () => {
|
||||
cy.get(RULES_MANAGEMENT_TABLE)
|
||||
.find(RULES_ROW)
|
||||
.then((rules) => {
|
||||
const initialNumberOfRules = rules.length;
|
||||
const numberOfRulesToBeDeleted = 2;
|
||||
const expectedNumberOfRulesAfterDeletion =
|
||||
initialNumberOfRules - numberOfRulesToBeDeleted;
|
||||
getRulesManagementTableRows().then((rules) => {
|
||||
const rulesToDelete = ['New Rule Test', 'Override Rule'] as const;
|
||||
const initialNumberOfRules = rules.length;
|
||||
const numberOfRulesToBeDeleted = 2;
|
||||
const expectedNumberOfRulesAfterDeletion =
|
||||
initialNumberOfRules - numberOfRulesToBeDeleted;
|
||||
|
||||
selectNumberOfRules(numberOfRulesToBeDeleted);
|
||||
deleteSelectedRules();
|
||||
selectRulesByName(rulesToDelete);
|
||||
deleteSelectedRules();
|
||||
|
||||
cy.get(RULES_MANAGEMENT_TABLE)
|
||||
.get(RULES_ROW)
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get(RULE_SWITCH).should('not.exist');
|
||||
});
|
||||
getRulesManagementTableRows()
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get(RULE_SWITCH).should('not.exist');
|
||||
});
|
||||
|
||||
cy.get(RULES_MANAGEMENT_TABLE)
|
||||
.find(RULES_ROW)
|
||||
.should('have.length', expectedNumberOfRulesAfterDeletion);
|
||||
getRulesManagementTableRows().should('have.length', expectedNumberOfRulesAfterDeletion);
|
||||
cy.request({ url: '/api/detection_engine/rules/_find' }).then(({ body }) => {
|
||||
const numberOfRules = body.data.length;
|
||||
expect(numberOfRules).to.eql(expectedNumberOfRulesAfterDeletion);
|
||||
});
|
||||
getRulesManagementTableRows()
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get(RULE_SWITCH).should('exist');
|
||||
});
|
||||
cy.get(CUSTOM_RULES_BTN).should(
|
||||
'have.text',
|
||||
`Custom rules (${expectedNumberOfRulesAfterDeletion})`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('Deletes one rule from detail page', () => {
|
||||
getRulesManagementTableRows().then((rules) => {
|
||||
const initialNumberOfRules = rules.length;
|
||||
const expectedNumberOfRulesAfterDeletion = initialNumberOfRules - 1;
|
||||
|
||||
goToTheRuleDetailsOf('New Rule Test');
|
||||
cy.intercept('POST', '/api/detection_engine/rules/_bulk_delete').as('deleteRule');
|
||||
|
||||
deleteRuleFromDetailsPage();
|
||||
|
||||
// @ts-expect-error update types
|
||||
cy.waitFor('@deleteRule').then(() => {
|
||||
cy.get(RULES_MANAGEMENT_TABLE).should('exist');
|
||||
getRulesManagementTableRows().should('have.length', expectedNumberOfRulesAfterDeletion);
|
||||
cy.request({ url: '/api/detection_engine/rules/_find' }).then(({ body }) => {
|
||||
const numberOfRules = body.data.length;
|
||||
expect(numberOfRules).to.eql(expectedNumberOfRulesAfterDeletion);
|
||||
});
|
||||
cy.get(RULES_MANAGEMENT_TABLE)
|
||||
.get(RULES_ROW)
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get(RULE_SWITCH).should('exist');
|
||||
});
|
||||
cy.get(CUSTOM_RULES_BTN).should(
|
||||
'have.text',
|
||||
`Custom rules (${expectedNumberOfRulesAfterDeletion})`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('Deletes one rule from detail page', () => {
|
||||
cy.get(RULES_MANAGEMENT_TABLE)
|
||||
.find(RULES_ROW)
|
||||
.then((rules) => {
|
||||
const initialNumberOfRules = rules.length;
|
||||
const expectedNumberOfRulesAfterDeletion = initialNumberOfRules - 1;
|
||||
|
||||
goToRuleDetails();
|
||||
cy.intercept('POST', '/api/detection_engine/rules/_bulk_delete').as('deleteRule');
|
||||
|
||||
deleteRuleFromDetailsPage();
|
||||
|
||||
// @ts-expect-error update types
|
||||
cy.waitFor('@deleteRule').then(() => {
|
||||
cy.get(RULES_MANAGEMENT_TABLE).should('exist');
|
||||
cy.get(RULES_MANAGEMENT_TABLE)
|
||||
.find(RULES_ROW)
|
||||
.should('have.length', expectedNumberOfRulesAfterDeletion);
|
||||
cy.request({ url: '/api/detection_engine/rules/_find' }).then(({ body }) => {
|
||||
const numberOfRules = body.data.length;
|
||||
expect(numberOfRules).to.eql(expectedNumberOfRulesAfterDeletion);
|
||||
});
|
||||
cy.get(CUSTOM_RULES_BTN).should(
|
||||
'have.text',
|
||||
`Custom rules (${expectedNumberOfRulesAfterDeletion})`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -345,15 +335,11 @@ describe('Custom query rules', () => {
|
|||
const expectedEditedtags = rule.tags?.join('');
|
||||
const expectedEditedIndexPatterns = rule.index;
|
||||
|
||||
before(() => {
|
||||
deleteAlertsAndRules();
|
||||
beforeEach(() => {
|
||||
deleteConnectors();
|
||||
createRule(getExistingRule({ rule_id: 'rule1', enabled: true }));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
});
|
||||
|
||||
it('Only modifies rule active status on enable/disable', () => {
|
||||
|
|
|
@ -13,8 +13,6 @@ import {
|
|||
CUSTOM_RULES_BTN,
|
||||
RISK_SCORE,
|
||||
RULE_NAME,
|
||||
RULES_ROW,
|
||||
RULES_MANAGEMENT_TABLE,
|
||||
RULE_SWITCH,
|
||||
SEVERITY,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
|
@ -50,7 +48,7 @@ import {
|
|||
EDIT_RULE_SETTINGS_LINK,
|
||||
} from '../../screens/rule_details';
|
||||
|
||||
import { goToRuleDetails } from '../../tasks/alerts_detection_rules';
|
||||
import { getRulesManagementTableRows, goToRuleDetails } from '../../tasks/alerts_detection_rules';
|
||||
import { postDataView } from '../../tasks/common';
|
||||
import {
|
||||
createAndEnableRule,
|
||||
|
@ -99,7 +97,7 @@ describe('Custom query rules', () => {
|
|||
|
||||
cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)');
|
||||
|
||||
cy.get(RULES_MANAGEMENT_TABLE).find(RULES_ROW).should('have.length', expectedNumberOfRules);
|
||||
getRulesManagementTableRows().should('have.length', expectedNumberOfRules);
|
||||
cy.get(RULE_NAME).should('have.text', rule.name);
|
||||
cy.get(RISK_SCORE).should('have.text', rule.risk_score);
|
||||
cy.get(SEVERITY).should('have.text', 'High');
|
||||
|
|
|
@ -16,13 +16,12 @@ import {
|
|||
} from '../../screens/alerts_detection_rules';
|
||||
import {
|
||||
filterByElasticRules,
|
||||
selectNumberOfRules,
|
||||
bulkExportRules,
|
||||
selectAllRules,
|
||||
waitForRuleExecution,
|
||||
exportRule,
|
||||
importRules,
|
||||
expectManagementTableRules,
|
||||
bulkExportRules,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import { createExceptionList, deleteExceptionList } from '../../tasks/api_calls/exceptions';
|
||||
import { getExceptionList } from '../../objects/exception';
|
||||
|
@ -70,7 +69,7 @@ describe('Export rules', () => {
|
|||
// Prevent installation of whole prebuilt rules package, use mock prebuilt rules instead
|
||||
preventPrebuiltRulesPackageInstallation();
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
createRule(getNewRule({ name: 'Rule to export' })).as('ruleResponse');
|
||||
createRule(getNewRule({ name: 'Rule to export', enabled: false })).as('ruleResponse');
|
||||
});
|
||||
|
||||
it('exports a custom rule', function () {
|
||||
|
@ -102,7 +101,7 @@ describe('Export rules', () => {
|
|||
createAndInstallMockedPrebuiltRules({ rules: prebuiltRules });
|
||||
|
||||
filterByElasticRules();
|
||||
selectNumberOfRules(prebuiltRules.length);
|
||||
selectAllRules();
|
||||
bulkExportRules();
|
||||
|
||||
cy.get(MODAL_CONFIRMATION_BODY).contains(
|
||||
|
@ -156,6 +155,7 @@ describe('Export rules', () => {
|
|||
},
|
||||
],
|
||||
rule_id: '2',
|
||||
enabled: false,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
|
@ -60,10 +60,9 @@ import {
|
|||
duplicateFirstRule,
|
||||
duplicateRuleFromMenu,
|
||||
goToRuleDetails,
|
||||
selectNumberOfRules,
|
||||
checkDuplicatedRule,
|
||||
expectNumberOfRules,
|
||||
duplicateSelectedRulesWithExceptions,
|
||||
selectAllRules,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { loadPrepackagedTimelineTemplates } from '../../tasks/api_calls/timelines';
|
||||
|
@ -106,6 +105,7 @@ import { login, visit, visitWithoutDateRange } from '../../tasks/login';
|
|||
import { goBackToRulesTable, getDetails } from '../../tasks/rule_details';
|
||||
|
||||
import { DETECTIONS_RULE_MANAGEMENT_URL, RULE_CREATION } from '../../urls/navigation';
|
||||
import { duplicateSelectedRulesWithExceptions } from '../../tasks/rules_bulk_edit';
|
||||
|
||||
const DEFAULT_THREAT_MATCH_QUERY = '@timestamp >= "now-30d/d"';
|
||||
|
||||
|
@ -554,7 +554,7 @@ describe('indicator match', () => {
|
|||
});
|
||||
|
||||
it("Allows the rule to be duplicated from the table's bulk actions", () => {
|
||||
selectNumberOfRules(1);
|
||||
selectAllRules();
|
||||
duplicateSelectedRulesWithExceptions();
|
||||
checkDuplicatedRule();
|
||||
});
|
||||
|
|
|
@ -20,7 +20,7 @@ describe('Rules talbes links', () => {
|
|||
beforeEach(() => {
|
||||
login();
|
||||
deleteAlertsAndRules();
|
||||
createRule(getNewRule({ rule_id: 'rule1' }));
|
||||
createRule(getNewRule({ rule_id: 'rule1', enabled: false }));
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
});
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import { APP_PATH, RULES_ADD_PATH, RULES_UPDATES } from '../../../common/constants';
|
||||
import { createRuleAssetSavedObject } from '../../helpers/rules';
|
||||
import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules';
|
||||
import { createAndInstallMockedPrebuiltRules } from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { resetRulesTableState, deleteAlertsAndRules } from '../../tasks/common';
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
|
@ -58,7 +57,6 @@ describe('Detection rules, Prebuilt Rules Installation and Update - Authorizatio
|
|||
resetRulesTableState();
|
||||
deleteAlertsAndRules();
|
||||
esArchiverResetKibana();
|
||||
waitForRulesTableToBeLoaded();
|
||||
createAndInstallMockedPrebuiltRules({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] });
|
||||
});
|
||||
|
||||
|
@ -75,7 +73,6 @@ describe('Detection rules, Prebuilt Rules Installation and Update - Authorizatio
|
|||
// Now login with read-only user in preparation for test
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2], installToKibana: false });
|
||||
loadPageAsReadOnlyUser(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
});
|
||||
|
||||
it('should not be able to install prebuilt rules', () => {
|
||||
|
@ -103,7 +100,6 @@ describe('Detection rules, Prebuilt Rules Installation and Update - Authorizatio
|
|||
});
|
||||
// Now login with read-only user in preparation for test
|
||||
loadPageAsReadOnlyUser(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
});
|
||||
|
||||
it('should not be able to upgrade prebuilt rules', () => {
|
||||
|
|
|
@ -6,23 +6,21 @@
|
|||
*/
|
||||
|
||||
import { createRuleAssetSavedObject } from '../../helpers/rules';
|
||||
import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules';
|
||||
import { createAndInstallMockedPrebuiltRules } from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { resetRulesTableState, deleteAlertsAndRules, reload } from '../../tasks/common';
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../tasks/login';
|
||||
import {
|
||||
addElasticRulesButtonClick,
|
||||
assertRuleAvailableForInstallAndInstallOne,
|
||||
assertRuleAvailableForInstallAndInstallSelected,
|
||||
assertRuleAvailableForInstallAndInstallAllInPage,
|
||||
assertRuleAvailableForInstallAndInstallAll,
|
||||
ruleUpdatesTabClick,
|
||||
assertRuleUpgradeAvailableAndUpgradeOne,
|
||||
assertRuleUpgradeAvailableAndUpgradeSelected,
|
||||
assertRuleUpgradeAvailableAndUpgradeAllInPage,
|
||||
assertRuleUpgradeAvailableAndUpgradeAll,
|
||||
ruleUpdatesTabClick,
|
||||
} from '../../tasks/prebuilt_rules';
|
||||
|
||||
describe('Detection rules, Prebuilt Rules Installation and Update - Error handling', () => {
|
||||
|
@ -32,7 +30,7 @@ describe('Detection rules, Prebuilt Rules Installation and Update - Error handli
|
|||
deleteAlertsAndRules();
|
||||
esArchiverResetKibana();
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
});
|
||||
|
||||
describe('Installation of prebuilt rules - Should fail gracefully with toast error message when', () => {
|
||||
|
@ -46,7 +44,6 @@ describe('Detection rules, Prebuilt Rules Installation and Update - Error handli
|
|||
});
|
||||
beforeEach(() => {
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2], installToKibana: false });
|
||||
waitForRulesTableToBeLoaded();
|
||||
});
|
||||
|
||||
it('installing prebuilt rules one by one', () => {
|
||||
|
@ -72,7 +69,10 @@ describe('Detection rules, Prebuilt Rules Installation and Update - Error handli
|
|||
|
||||
it('installing all available rules at once', () => {
|
||||
addElasticRulesButtonClick();
|
||||
assertRuleAvailableForInstallAndInstallAll({ rules: [RULE_1, RULE_2], didRequestFail: true });
|
||||
assertRuleAvailableForInstallAndInstallAll({
|
||||
rules: [RULE_1, RULE_2],
|
||||
didRequestFail: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -107,7 +107,6 @@ describe('Detection rules, Prebuilt Rules Installation and Update - Error handli
|
|||
rules: [UPDATED_RULE_1, UPDATED_RULE_2],
|
||||
installToKibana: false,
|
||||
});
|
||||
waitForRulesTableToBeLoaded();
|
||||
reload();
|
||||
});
|
||||
|
||||
|
|
|
@ -9,37 +9,35 @@ import type { BulkInstallPackageInfo } from '@kbn/fleet-plugin/common';
|
|||
import type { Rule } from '../../../public/detection_engine/rule_management/logic/types';
|
||||
import { createRuleAssetSavedObject } from '../../helpers/rules';
|
||||
import {
|
||||
GO_BACK_TO_RULES_TABLE_BUTTON,
|
||||
INSTALL_ALL_RULES_BUTTON,
|
||||
INSTALL_SELECTED_RULES_BUTTON,
|
||||
NO_RULES_AVAILABLE_FOR_INSTALL_MESSSAGE,
|
||||
NO_RULES_AVAILABLE_FOR_UPGRADE_MESSSAGE,
|
||||
RULES_UPDATES_TAB,
|
||||
RULE_CHECKBOX,
|
||||
SELECT_ALL_RULES_ON_PAGE_CHECKBOX,
|
||||
TOASTER,
|
||||
RULE_CHECKBOX,
|
||||
NO_RULES_AVAILABLE_FOR_INSTALL_MESSSAGE,
|
||||
GO_BACK_TO_RULES_TABLE_BUTTON,
|
||||
SELECT_ALL_RULES_ON_PAGE_CHECKBOX,
|
||||
INSTALL_SELECTED_RULES_BUTTON,
|
||||
RULES_UPDATES_TAB,
|
||||
NO_RULES_AVAILABLE_FOR_UPGRADE_MESSSAGE,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules';
|
||||
import {
|
||||
createAndInstallMockedPrebuiltRules,
|
||||
getRuleAssets,
|
||||
createAndInstallMockedPrebuiltRules,
|
||||
} from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { deleteAlertsAndRules, reload, resetRulesTableState } from '../../tasks/common';
|
||||
import { resetRulesTableState, deleteAlertsAndRules, reload } from '../../tasks/common';
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../tasks/login';
|
||||
import {
|
||||
addElasticRulesButtonClick,
|
||||
assertRuleAvailableForInstallAndInstallOne,
|
||||
assertRuleAvailableForInstallAndInstallSelected,
|
||||
assertRuleAvailableForInstallAndInstallAllInPage,
|
||||
assertRuleAvailableForInstallAndInstallAll,
|
||||
ruleUpdatesTabClick,
|
||||
assertRuleUpgradeAvailableAndUpgradeOne,
|
||||
assertRuleUpgradeAvailableAndUpgradeSelected,
|
||||
assertRuleUpgradeAvailableAndUpgradeAllInPage,
|
||||
assertRuleUpgradeAvailableAndUpgradeAll,
|
||||
ruleUpdatesTabClick,
|
||||
} from '../../tasks/prebuilt_rules';
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
|
||||
describe('Detection rules, Prebuilt Rules Installation and Update workflow', () => {
|
||||
beforeEach(() => {
|
||||
|
@ -48,7 +46,7 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()
|
|||
deleteAlertsAndRules();
|
||||
esArchiverResetKibana();
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
});
|
||||
|
||||
describe('Installation of prebuilt rules package via Fleet', () => {
|
||||
|
@ -57,7 +55,6 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()
|
|||
cy.intercept('POST', '/api/fleet/epm/packages/security_detection_engine/*').as(
|
||||
'installPackage'
|
||||
);
|
||||
waitForRulesTableToBeLoaded();
|
||||
});
|
||||
|
||||
it('should install package from Fleet in the background', () => {
|
||||
|
@ -146,7 +143,6 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()
|
|||
});
|
||||
beforeEach(() => {
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2], installToKibana: false });
|
||||
waitForRulesTableToBeLoaded();
|
||||
cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/installation/_perform').as(
|
||||
'installPrebuiltRules'
|
||||
);
|
||||
|
@ -228,7 +224,6 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()
|
|||
rules: [UPDATED_RULE_1, UPDATED_RULE_2],
|
||||
installToKibana: false,
|
||||
});
|
||||
waitForRulesTableToBeLoaded();
|
||||
reload();
|
||||
});
|
||||
|
||||
|
@ -244,7 +239,9 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', ()
|
|||
|
||||
it('should upgrade multiple selected prebuilt rules by selecting all in page', () => {
|
||||
ruleUpdatesTabClick();
|
||||
assertRuleUpgradeAvailableAndUpgradeAllInPage({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] });
|
||||
assertRuleUpgradeAvailableAndUpgradeAllInPage({
|
||||
rules: [OUTDATED_RULE_1, OUTDATED_RULE_2],
|
||||
});
|
||||
});
|
||||
|
||||
it('should upgrade all rules with available upgrades at once', () => {
|
||||
|
|
|
@ -12,8 +12,6 @@ import {
|
|||
ADD_ELASTIC_RULES_BTN,
|
||||
RULES_EMPTY_PROMPT,
|
||||
RULES_MONITORING_TAB,
|
||||
RULES_ROW,
|
||||
RULES_MANAGEMENT_TABLE,
|
||||
RULE_SWITCH,
|
||||
SELECT_ALL_RULES_ON_PAGE_CHECKBOX,
|
||||
INSTALL_ALL_RULES_BUTTON,
|
||||
|
@ -21,12 +19,10 @@ import {
|
|||
import {
|
||||
confirmRulesDelete,
|
||||
deleteFirstRule,
|
||||
deleteSelectedRules,
|
||||
disableAutoRefresh,
|
||||
disableSelectedRules,
|
||||
enableSelectedRules,
|
||||
getRulesManagementTableRows,
|
||||
selectAllRules,
|
||||
selectNumberOfRules,
|
||||
selectRulesByName,
|
||||
waitForPrebuiltDetectionRulesToBeLoaded,
|
||||
waitForRuleToUpdate,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
|
@ -37,6 +33,11 @@ import {
|
|||
} from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { cleanKibana, deleteAlertsAndRules, deletePrebuiltRulesAssets } from '../../tasks/common';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
import {
|
||||
enableSelectedRules,
|
||||
disableSelectedRules,
|
||||
deleteSelectedRules,
|
||||
} from '../../tasks/rules_bulk_edit';
|
||||
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation';
|
||||
|
||||
const rules = Array.from(Array(5)).map((_, i) => {
|
||||
|
@ -66,7 +67,7 @@ describe('Prebuilt rules', () => {
|
|||
describe('Alerts rules, prebuilt rules', () => {
|
||||
it('Loads prebuilt rules', () => {
|
||||
// Check that the rules table contains rules
|
||||
cy.get(RULES_MANAGEMENT_TABLE).find(RULES_ROW).should('have.length.gte', 1);
|
||||
getRulesManagementTableRows().should('have.length.gte', 1);
|
||||
|
||||
// Check the correct count of prebuilt rules is displayed
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
|
@ -108,8 +109,7 @@ describe('Prebuilt rules', () => {
|
|||
});
|
||||
|
||||
it('Does not allow to delete one rule when more than one is selected', () => {
|
||||
const numberOfRulesToBeSelected = 2;
|
||||
selectNumberOfRules(numberOfRulesToBeSelected);
|
||||
selectAllRules();
|
||||
|
||||
cy.get(COLLAPSED_ACTION_BTN).each((collapsedItemActionBtn) => {
|
||||
cy.wrap(collapsedItemActionBtn).should('have.attr', 'disabled');
|
||||
|
@ -150,16 +150,16 @@ describe('Prebuilt rules', () => {
|
|||
|
||||
it('Deletes and recovers more than one rule', () => {
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
const numberOfRulesToBeSelected = 2;
|
||||
const rulesToDelete = ['Test rule 1', 'Test rule 2'] as const;
|
||||
const expectedNumberOfRulesAfterDeletion = availablePrebuiltRulesCount - 2;
|
||||
const expectedNumberOfRulesAfterRecovering = availablePrebuiltRulesCount;
|
||||
|
||||
selectNumberOfRules(numberOfRulesToBeSelected);
|
||||
selectRulesByName(rulesToDelete);
|
||||
deleteSelectedRules();
|
||||
|
||||
cy.get(ADD_ELASTIC_RULES_BTN).should(
|
||||
'have.text',
|
||||
`Add Elastic rules${numberOfRulesToBeSelected}`
|
||||
`Add Elastic rules${rulesToDelete.length}`
|
||||
);
|
||||
cy.get(ELASTIC_RULES_BTN).should(
|
||||
'have.text',
|
||||
|
|
|
@ -6,20 +6,23 @@
|
|||
*/
|
||||
|
||||
import { createRuleAssetSavedObject } from '../../helpers/rules';
|
||||
import { ADD_ELASTIC_RULES_BTN, RULES_UPDATES_TAB } from '../../screens/alerts_detection_rules';
|
||||
import { deleteFirstRule, waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules';
|
||||
import {
|
||||
installAllPrebuiltRulesRequest,
|
||||
ADD_ELASTIC_RULES_EMPTY_PROMPT_BTN,
|
||||
RULES_UPDATES_TAB,
|
||||
ADD_ELASTIC_RULES_BTN,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
import { deleteFirstRule } from '../../tasks/alerts_detection_rules';
|
||||
import {
|
||||
createAndInstallMockedPrebuiltRules,
|
||||
installAllPrebuiltRulesRequest,
|
||||
} from '../../tasks/api_calls/prebuilt_rules';
|
||||
import {
|
||||
resetRulesTableState,
|
||||
deleteAlertsAndRules,
|
||||
reload,
|
||||
deletePrebuiltRulesAssets,
|
||||
reload,
|
||||
} from '../../tasks/common';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../tasks/login';
|
||||
|
||||
const RULE_1 = createRuleAssetSavedObject({
|
||||
name: 'Test rule 1',
|
||||
|
@ -37,8 +40,10 @@ describe('Detection rules, Prebuilt Rules Installation and Update Notifications'
|
|||
|
||||
describe('No notifications', () => {
|
||||
it('should NOT display install or update notifications when no prebuilt assets and no rules are installed', () => {
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
visitSecurityDetectionRulesPage();
|
||||
|
||||
cy.get(ADD_ELASTIC_RULES_EMPTY_PROMPT_BTN).should('be.visible');
|
||||
|
||||
// TODO: test plan asserts "should NOT see a CTA to install prebuilt rules"
|
||||
// but current behavior is to always show the CTA, even with no prebuilt rule assets installed
|
||||
// Update that behaviour and then update this test.
|
||||
|
@ -47,8 +52,7 @@ describe('Detection rules, Prebuilt Rules Installation and Update Notifications'
|
|||
|
||||
it('should NOT display install or update notifications when latest rules are installed', () => {
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1], installToKibana: true });
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
visitSecurityDetectionRulesPage();
|
||||
|
||||
/* Assert that there are no installation or update notifications */
|
||||
/* Add Elastic Rules button should not contain a number badge */
|
||||
|
@ -65,7 +69,7 @@ describe('Detection rules, Prebuilt Rules Installation and Update Notifications'
|
|||
|
||||
describe('Rules installation notification when no rules have been installed', () => {
|
||||
beforeEach(() => {
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
});
|
||||
|
||||
it('should notify user about prebuilt rules available for installation', () => {
|
||||
|
@ -89,9 +93,11 @@ describe('Detection rules, Prebuilt Rules Installation and Update Notifications'
|
|||
rule_id: 'rule_3',
|
||||
});
|
||||
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_2, RULE_3], installToKibana: false });
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
createAndInstallMockedPrebuiltRules({
|
||||
rules: [RULE_2, RULE_3],
|
||||
installToKibana: false,
|
||||
});
|
||||
visitSecurityDetectionRulesPage();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -128,8 +134,7 @@ describe('Detection rules, Prebuilt Rules Installation and Update Notifications'
|
|||
version: 2,
|
||||
});
|
||||
createAndInstallMockedPrebuiltRules({ rules: [UPDATED_RULE], installToKibana: false });
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
visitSecurityDetectionRulesPage();
|
||||
reload();
|
||||
});
|
||||
});
|
||||
|
@ -163,8 +168,7 @@ describe('Detection rules, Prebuilt Rules Installation and Update Notifications'
|
|||
rules: [RULE_2, UPDATED_RULE],
|
||||
installToKibana: false,
|
||||
});
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
visitSecurityDetectionRulesPage();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { cleanKibana, resetRulesTableState, deleteAlertsAndRules } from '../../tasks/common';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../tasks/login';
|
||||
import { esArchiverResetKibana } from '../../tasks/es_archiver';
|
||||
import {
|
||||
expectRulesWithExecutionStatus,
|
||||
|
@ -14,14 +14,10 @@ import {
|
|||
expectNumberOfRulesShownOnPage,
|
||||
} from '../../tasks/rule_filters';
|
||||
|
||||
import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
|
||||
import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules';
|
||||
|
||||
import { createRule, waitForRulesToFinishExecution } from '../../tasks/api_calls/rules';
|
||||
import { deleteIndex, createIndex, createDocument } from '../../tasks/api_calls/elasticsearch';
|
||||
|
||||
import { getNewRule } from '../../objects/rule';
|
||||
import { disableAutoRefresh } from '../../tasks/alerts_detection_rules';
|
||||
|
||||
describe('Rule management filters', () => {
|
||||
before(() => {
|
||||
|
@ -53,6 +49,7 @@ describe('Rule management filters', () => {
|
|||
name: 'Successful rule',
|
||||
rule_id: 'successful_rule',
|
||||
index: ['test_index'],
|
||||
enabled: true,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -61,6 +58,7 @@ describe('Rule management filters', () => {
|
|||
name: 'Warning rule',
|
||||
rule_id: 'warning_rule',
|
||||
index: ['non_existent_index'],
|
||||
enabled: true,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -71,14 +69,14 @@ describe('Rule management filters', () => {
|
|||
index: ['test_index'],
|
||||
// Setting a crazy large "Additional look-back time" to force a failure
|
||||
from: 'now-9007199254746990s',
|
||||
enabled: true,
|
||||
})
|
||||
);
|
||||
|
||||
waitForRulesToFinishExecution(['successful_rule', 'warning_rule', 'failed_rule'], new Date());
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
|
||||
waitForRulesTableToBeLoaded();
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
// Initial table state - before filtering by status
|
||||
expectNumberOfRulesShownOnPage(3);
|
||||
|
|
|
@ -7,35 +7,39 @@
|
|||
|
||||
import { INTERNAL_ALERTING_API_FIND_RULES_PATH } from '@kbn/alerting-plugin/common';
|
||||
import type { RuleResponse } from '../../../common/detection_engine/rule_schema';
|
||||
import { getNewRule } from '../../objects/rule';
|
||||
import { RULE_NAME } from '../../screens/alerts';
|
||||
import { RULES_MANAGEMENT_TABLE } from '../../screens/alerts_detection_rules';
|
||||
import { TOOLTIP } from '../../screens/common';
|
||||
import { ACTIONS } from '../../screens/rule_details';
|
||||
import { DISABLED_SNOOZE_BADGE } from '../../screens/rule_snoozing';
|
||||
import {
|
||||
disableAutoRefresh,
|
||||
duplicateFirstRule,
|
||||
importRules,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import { createSlackConnector } from '../../tasks/api_calls/connectors';
|
||||
import { createRule, snoozeRule as snoozeRuleViaAPI } from '../../tasks/api_calls/rules';
|
||||
import { cleanKibana, deleteAlertsAndRules, deleteConnectors } from '../../tasks/common';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
import { getNewRule } from '../../objects/rule';
|
||||
import { ruleDetailsUrl, ruleEditUrl, SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation';
|
||||
import { internalAlertingSnoozeRule } from '../../urls/routes';
|
||||
import { RULES_MANAGEMENT_TABLE, RULE_NAME } from '../../screens/alerts_detection_rules';
|
||||
import {
|
||||
expectRuleSnoozed,
|
||||
expectRuleSnoozedInTable,
|
||||
expectRuleUnsnoozed,
|
||||
expectRuleUnsnoozedInTable,
|
||||
expectSnoozeErrorToast,
|
||||
expectSnoozeSuccessToast,
|
||||
expectUnsnoozeSuccessToast,
|
||||
snoozeRule,
|
||||
snoozeRuleInTable,
|
||||
unsnoozeRuleInTable,
|
||||
} from '../../tasks/rule_snoozing';
|
||||
import { createSlackConnector } from '../../tasks/api_calls/connectors';
|
||||
import { duplicateFirstRule, importRules } from '../../tasks/alerts_detection_rules';
|
||||
import { goToActionsStepTab } from '../../tasks/create_new_rule';
|
||||
import { goToRuleEditSettings } from '../../tasks/rule_details';
|
||||
import { actionFormSelector } from '../../screens/common/rule_actions';
|
||||
import { RULE_INDICES } from '../../screens/create_new_rule';
|
||||
import { addEmailConnectorAndRuleAction } from '../../tasks/common/rule_actions';
|
||||
import { goToActionsStepTab } from '../../tasks/create_new_rule';
|
||||
import { saveEditedRule } from '../../tasks/edit_rule';
|
||||
import { DISABLED_SNOOZE_BADGE } from '../../screens/rule_snoozing';
|
||||
import { TOOLTIP } from '../../screens/common';
|
||||
import { login, visitSecurityDetectionRulesPage, visitWithoutDateRange } from '../../tasks/login';
|
||||
import { goToRuleEditSettings } from '../../tasks/rule_details';
|
||||
import {
|
||||
snoozeRuleInTable,
|
||||
expectRuleSnoozed,
|
||||
expectSnoozeSuccessToast,
|
||||
expectRuleSnoozedInTable,
|
||||
unsnoozeRuleInTable,
|
||||
expectUnsnoozeSuccessToast,
|
||||
expectRuleUnsnoozedInTable,
|
||||
snoozeRule,
|
||||
expectSnoozeErrorToast,
|
||||
expectRuleUnsnoozed,
|
||||
} from '../../tasks/rule_snoozing';
|
||||
import { ruleEditUrl, ruleDetailsUrl } from '../../urls/navigation';
|
||||
import { internalAlertingSnoozeRule } from '../../urls/routes';
|
||||
|
||||
const RULES_TO_IMPORT_FILENAME = 'cypress/fixtures/7_16_rules.ndjson';
|
||||
|
||||
|
@ -50,9 +54,10 @@ describe('rule snoozing', () => {
|
|||
});
|
||||
|
||||
it('ensures the rule is snoozed on the rules management page, rule details page and rule editing page', () => {
|
||||
createRule(getNewRule({ name: 'Test on all pages' }));
|
||||
createRule(getNewRule({ name: 'Test on all pages', enabled: false }));
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
snoozeRuleInTable({
|
||||
tableSelector: RULES_MANAGEMENT_TABLE,
|
||||
|
@ -74,9 +79,10 @@ describe('rule snoozing', () => {
|
|||
|
||||
describe('Rules management table', () => {
|
||||
it('snoozes a rule without actions for 3 hours', () => {
|
||||
createRule(getNewRule({ name: 'Test rule without actions' }));
|
||||
createRule(getNewRule({ name: 'Test rule without actions', enabled: false }));
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
snoozeRuleInTable({
|
||||
tableSelector: RULES_MANAGEMENT_TABLE,
|
||||
|
@ -95,7 +101,8 @@ describe('rule snoozing', () => {
|
|||
it('snoozes a rule with actions for 2 days', () => {
|
||||
createRuleWithActions({ name: 'Test rule with actions' }, createRule);
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
snoozeRuleInTable({
|
||||
tableSelector: RULES_MANAGEMENT_TABLE,
|
||||
|
@ -114,7 +121,8 @@ describe('rule snoozing', () => {
|
|||
it('unsnoozes a rule with actions', () => {
|
||||
createSnoozedRule(getNewRule({ name: 'Snoozed rule' }));
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
unsnoozeRuleInTable({
|
||||
tableSelector: RULES_MANAGEMENT_TABLE,
|
||||
|
@ -129,9 +137,10 @@ describe('rule snoozing', () => {
|
|||
});
|
||||
|
||||
it('ensures snooze settings persist after page reload', () => {
|
||||
createRule(getNewRule({ name: 'Test persistence' }));
|
||||
createRule(getNewRule({ name: 'Test persistence', enabled: false }));
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
snoozeRuleInTable({
|
||||
tableSelector: RULES_MANAGEMENT_TABLE,
|
||||
|
@ -149,14 +158,16 @@ describe('rule snoozing', () => {
|
|||
});
|
||||
|
||||
it('ensures a duplicated rule is not snoozed', () => {
|
||||
createRule(getNewRule({ name: 'Test rule' }));
|
||||
createRule(getNewRule({ name: 'Test rule', enabled: false }));
|
||||
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
duplicateFirstRule();
|
||||
|
||||
// Make sure rules table is shown as it navigates to rule editing page after successful duplication
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
disableAutoRefresh();
|
||||
|
||||
expectRuleUnsnoozedInTable({
|
||||
tableSelector: RULES_MANAGEMENT_TABLE,
|
||||
|
@ -165,8 +176,7 @@ describe('rule snoozing', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// SKIPPED: https://github.com/elastic/kibana/issues/159349
|
||||
describe.skip('Rule editing page / actions tab', () => {
|
||||
describe('Rule editing page / actions tab', () => {
|
||||
beforeEach(() => {
|
||||
deleteConnectors();
|
||||
});
|
||||
|
@ -174,17 +184,12 @@ describe('rule snoozing', () => {
|
|||
it('adds an action to a snoozed rule', () => {
|
||||
createSnoozedRule(getNewRule({ name: 'Snoozed rule' })).then(({ body: rule }) => {
|
||||
visitWithoutDateRange(ruleEditUrl(rule.id));
|
||||
// Wait for rule data being loaded
|
||||
cy.get(RULE_INDICES).should('be.visible');
|
||||
goToActionsStepTab();
|
||||
|
||||
addEmailConnectorAndRuleAction('abc@example.com', 'Test action');
|
||||
saveEditedRule();
|
||||
|
||||
goToRuleEditSettings();
|
||||
goToActionsStepTab();
|
||||
|
||||
cy.get(actionFormSelector(0)).should('be.visible');
|
||||
cy.get(ACTIONS).should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -195,7 +200,7 @@ describe('rule snoozing', () => {
|
|||
});
|
||||
|
||||
it('ensures imported rules are unsnoozed', () => {
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL);
|
||||
visitSecurityDetectionRulesPage();
|
||||
|
||||
importRules(RULES_TO_IMPORT_FILENAME);
|
||||
|
||||
|
@ -212,7 +217,7 @@ describe('rule snoozing', () => {
|
|||
|
||||
describe('Handling errors', () => {
|
||||
it('shows an error if unable to load snooze settings', () => {
|
||||
createRule(getNewRule({ name: 'Test rule' })).then(({ body: rule }) => {
|
||||
createRule(getNewRule({ name: 'Test rule', enabled: false })).then(({ body: rule }) => {
|
||||
cy.intercept('GET', `${INTERNAL_ALERTING_API_FIND_RULES_PATH}*`, {
|
||||
statusCode: 500,
|
||||
});
|
||||
|
@ -226,7 +231,7 @@ describe('rule snoozing', () => {
|
|||
});
|
||||
|
||||
it('shows an error if unable to save snooze settings', () => {
|
||||
createRule(getNewRule({ name: 'Test rule' })).then(({ body: rule }) => {
|
||||
createRule(getNewRule({ name: 'Test rule', enabled: false })).then(({ body: rule }) => {
|
||||
cy.intercept('POST', internalAlertingSnoozeRule(rule.id), { forceNetworkError: true });
|
||||
|
||||
visitWithoutDateRange(ruleDetailsUrl(rule.id));
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { createRuleAssetSavedObject } from '../../helpers/rules';
|
||||
import {
|
||||
SELECTED_RULES_NUMBER_LABEL,
|
||||
|
@ -11,13 +12,13 @@ import {
|
|||
SELECT_ALL_RULES_ON_PAGE_CHECKBOX,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
import {
|
||||
selectNumberOfRules,
|
||||
unselectNumberOfRules,
|
||||
waitForPrebuiltDetectionRulesToBeLoaded,
|
||||
selectRulesByName,
|
||||
unselectRulesByName,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import {
|
||||
getAvailablePrebuiltRulesCount,
|
||||
createAndInstallMockedPrebuiltRules,
|
||||
getAvailablePrebuiltRulesCount,
|
||||
} from '../../tasks/api_calls/prebuilt_rules';
|
||||
import { cleanKibana } from '../../tasks/common';
|
||||
import { login, visitWithoutDateRange } from '../../tasks/login';
|
||||
|
@ -32,7 +33,7 @@ const RULE_2 = createRuleAssetSavedObject({
|
|||
rule_id: 'rule_2',
|
||||
});
|
||||
|
||||
describe('Rules selection', () => {
|
||||
describe('Rules table: selection', () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
@ -48,11 +49,11 @@ describe('Rules selection', () => {
|
|||
it('should correctly update the selection label when rules are individually selected and unselected', () => {
|
||||
waitForPrebuiltDetectionRulesToBeLoaded();
|
||||
|
||||
selectNumberOfRules(2);
|
||||
selectRulesByName(['Test rule 1', 'Test rule 2']);
|
||||
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', '2');
|
||||
|
||||
unselectNumberOfRules(2);
|
||||
unselectRulesByName(['Test rule 1', 'Test rule 2']);
|
||||
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', '0');
|
||||
});
|
||||
|
|
|
@ -5,29 +5,29 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getNewRule } from '../../objects/rule';
|
||||
import {
|
||||
RULE_CHECKBOX,
|
||||
REFRESH_RULES_STATUS,
|
||||
RULES_TABLE_AUTOREFRESH_INDICATOR,
|
||||
RULES_MANAGEMENT_TABLE,
|
||||
RULES_TABLE_AUTOREFRESH_INDICATOR,
|
||||
REFRESH_RULES_STATUS,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
import { EUI_CHECKBOX } from '../../screens/common/controls';
|
||||
import {
|
||||
selectAllRules,
|
||||
clearAllRuleSelection,
|
||||
selectNumberOfRules,
|
||||
mockGlobalClock,
|
||||
expectNumberOfRules,
|
||||
selectRulesByName,
|
||||
getRuleRow,
|
||||
expectAutoRefreshIsEnabled,
|
||||
selectAllRules,
|
||||
expectAutoRefreshIsDeactivated,
|
||||
clearAllRuleSelection,
|
||||
disableAutoRefresh,
|
||||
expectAutoRefreshIsDisabled,
|
||||
expectAutoRefreshIsEnabled,
|
||||
expectAutoRefreshIsDeactivated,
|
||||
expectNumberOfRules,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import { login, visit, visitWithoutDateRange } from '../../tasks/login';
|
||||
|
||||
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { cleanKibana } from '../../tasks/common';
|
||||
import { getNewRule } from '../../objects/rule';
|
||||
import { login, visitWithoutDateRange, visit } from '../../tasks/login';
|
||||
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation';
|
||||
|
||||
const DEFAULT_RULE_REFRESH_INTERVAL_VALUE = 60000;
|
||||
const NUM_OF_TEST_RULES = 6;
|
||||
|
@ -38,7 +38,7 @@ describe('Rules table: auto-refresh', () => {
|
|||
login();
|
||||
|
||||
for (let i = 1; i <= NUM_OF_TEST_RULES; ++i) {
|
||||
createRule(getNewRule({ name: `Test rule ${i}`, rule_id: `${i}` }));
|
||||
createRule(getNewRule({ name: `Test rule ${i}`, rule_id: `${i}`, enabled: false }));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -66,7 +66,7 @@ describe('Rules table: auto-refresh', () => {
|
|||
|
||||
expectNumberOfRules(RULES_MANAGEMENT_TABLE, NUM_OF_TEST_RULES);
|
||||
|
||||
selectNumberOfRules(1);
|
||||
selectRulesByName(['Test rule 1']);
|
||||
|
||||
// mock 1 minute passing to make sure refresh is not conducted
|
||||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should('not.exist');
|
||||
|
@ -74,7 +74,7 @@ describe('Rules table: auto-refresh', () => {
|
|||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should('not.exist');
|
||||
|
||||
// ensure rule is still selected
|
||||
cy.get(RULE_CHECKBOX).first().should('be.checked');
|
||||
getRuleRow('Test rule 1').find(EUI_CHECKBOX).should('be.checked');
|
||||
|
||||
cy.get(REFRESH_RULES_STATUS).should('have.not.text', 'Updated now');
|
||||
});
|
||||
|
|
|
@ -5,42 +5,40 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
FIRST_RULE,
|
||||
RULE_NAME,
|
||||
RULE_SWITCH,
|
||||
SECOND_RULE,
|
||||
FOURTH_RULE,
|
||||
RULES_MANAGEMENT_TABLE,
|
||||
RULES_ROW,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
import {
|
||||
enableRule,
|
||||
waitForRulesTableToBeLoaded,
|
||||
waitForRuleToUpdate,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import { login, visit } from '../../tasks/login';
|
||||
|
||||
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { cleanKibana } from '../../tasks/common';
|
||||
import {
|
||||
getExistingRule,
|
||||
getNewOverrideRule,
|
||||
getNewRule,
|
||||
getNewThresholdRule,
|
||||
} from '../../objects/rule';
|
||||
import { goToTablePage, setRowsPerPageTo, sortByTableColumn } from '../../tasks/table_pagination';
|
||||
import { RULE_NAME } from '../../screens/alerts';
|
||||
import {
|
||||
SECOND_RULE,
|
||||
FOURTH_RULE,
|
||||
FIRST_RULE,
|
||||
RULES_MANAGEMENT_TABLE,
|
||||
} from '../../screens/alerts_detection_rules';
|
||||
import { RULE_SWITCH } from '../../screens/rule_details';
|
||||
import { TABLE_FIRST_PAGE, TABLE_SECOND_PAGE } from '../../screens/table_pagination';
|
||||
import {
|
||||
enableRule,
|
||||
waitForRuleToUpdate,
|
||||
getRulesManagementTableRows,
|
||||
} from '../../tasks/alerts_detection_rules';
|
||||
import { createRule } from '../../tasks/api_calls/rules';
|
||||
import { cleanKibana } from '../../tasks/common';
|
||||
import { login, visit } from '../../tasks/login';
|
||||
import { sortByTableColumn, setRowsPerPageTo, goToTablePage } from '../../tasks/table_pagination';
|
||||
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation';
|
||||
|
||||
describe('Alerts detection rules', () => {
|
||||
describe('Rules table: sorting', () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
login();
|
||||
createRule(getNewRule({ rule_id: '1' }));
|
||||
createRule(getExistingRule({ rule_id: '2' }));
|
||||
createRule(getNewOverrideRule({ rule_id: '3' }));
|
||||
createRule(getNewThresholdRule({ rule_id: '4' }));
|
||||
createRule(getNewRule({ name: 'New Rule', rule_id: '1', enabled: false }));
|
||||
createRule(getExistingRule({ rule_id: '2', enabled: false }));
|
||||
createRule(getNewOverrideRule({ rule_id: '3', enabled: false }));
|
||||
createRule(getNewThresholdRule({ rule_id: '4', enabled: false }));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -49,7 +47,6 @@ describe('Alerts detection rules', () => {
|
|||
|
||||
it('Sorts by enabled rules', () => {
|
||||
visit(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
|
||||
enableRule(SECOND_RULE);
|
||||
waitForRuleToUpdate();
|
||||
|
@ -66,11 +63,10 @@ describe('Alerts detection rules', () => {
|
|||
});
|
||||
|
||||
it('Pagination updates page number and results', () => {
|
||||
createRule(getNewRule({ name: 'Test a rule', rule_id: '5' }));
|
||||
createRule(getNewRule({ name: 'Not same as first rule', rule_id: '6' }));
|
||||
createRule(getNewRule({ name: 'Test a rule', rule_id: '5', enabled: false }));
|
||||
createRule(getNewRule({ name: 'Not same as first rule', rule_id: '6', enabled: false }));
|
||||
|
||||
visit(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
waitForRulesTableToBeLoaded();
|
||||
setRowsPerPageTo(5);
|
||||
|
||||
cy.get(RULES_MANAGEMENT_TABLE).find(TABLE_FIRST_PAGE).should('have.attr', 'aria-current');
|
||||
|
@ -82,7 +78,7 @@ describe('Alerts detection rules', () => {
|
|||
.then((ruleNameFirstPage) => {
|
||||
goToTablePage(2);
|
||||
// Check that the rules table shows at least one row
|
||||
cy.get(RULES_MANAGEMENT_TABLE).find(RULES_ROW).should('have.length.gte', 1);
|
||||
getRulesManagementTableRows().should('have.length.gte', 1);
|
||||
// Check that the rules table doesn't show the rule from the first page
|
||||
cy.get(RULES_MANAGEMENT_TABLE).should('not.contain', ruleNameFirstPage);
|
||||
});
|
||||
|
|
|
@ -4,20 +4,15 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { ROLES } from '../../../../common/test';
|
||||
|
||||
import { getExceptionList } from '../../../objects/exception';
|
||||
import { getNewRule } from '../../../objects/rule';
|
||||
import { ROLES } from '../../../../common/test';
|
||||
import { createRule } from '../../../tasks/api_calls/rules';
|
||||
import { login, visitWithoutDateRange } from '../../../tasks/login';
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../../tasks/login';
|
||||
import { goToExceptionsTab, goToAlertsTab } from '../../../tasks/rule_details';
|
||||
import {
|
||||
disableAutoRefresh,
|
||||
goToRuleDetails,
|
||||
waitForRulesTableToBeLoaded,
|
||||
} from '../../../tasks/alerts_detection_rules';
|
||||
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation';
|
||||
import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common';
|
||||
import { goToTheRuleDetailsOf } from '../../../tasks/alerts_detection_rules';
|
||||
import { deleteAlertsAndRules } from '../../../tasks/common';
|
||||
import {
|
||||
NO_EXCEPTIONS_EXIST_PROMPT,
|
||||
EXCEPTION_ITEM_VIEWER_CONTAINER,
|
||||
|
@ -34,12 +29,15 @@ import {
|
|||
describe('Exceptions viewer read only', () => {
|
||||
const exceptionList = getExceptionList();
|
||||
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
beforeEach(() => {
|
||||
deleteAlertsAndRules();
|
||||
deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type);
|
||||
|
||||
// create rule with exceptions
|
||||
createExceptionList(exceptionList, exceptionList.list_id).then((response) => {
|
||||
createRule(
|
||||
getNewRule({
|
||||
name: 'Test exceptions rule',
|
||||
query: 'agent.name:*',
|
||||
index: ['exceptions*'],
|
||||
exceptions_list: [
|
||||
|
@ -54,22 +52,13 @@ describe('Exceptions viewer read only', () => {
|
|||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login(ROLES.reader);
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL, ROLES.reader);
|
||||
waitForRulesTableToBeLoaded();
|
||||
disableAutoRefresh();
|
||||
goToRuleDetails();
|
||||
visitSecurityDetectionRulesPage(ROLES.reader);
|
||||
goToTheRuleDetailsOf('Test exceptions rule');
|
||||
goToExceptionsTab();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
deleteAlertsAndRules();
|
||||
deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type);
|
||||
});
|
||||
|
||||
it('Cannot add an exception from empty viewer screen', () => {
|
||||
// when no exceptions exist, empty component shows with action to add exception
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist');
|
||||
|
|
|
@ -85,9 +85,9 @@ export const MESSAGE = '[data-test-subj="formatted-field-message"]';
|
|||
export const REASON =
|
||||
'[data-test-subj="dataGridRowCell"][data-gridcell-column-id="kibana.alert.reason"]';
|
||||
|
||||
export const RISK_SCORE = '[data-test-subj^=formatted-field][data-test-subj$=risk_score]';
|
||||
export const RISK_SCORE = '[data-test-subj$=riskScore]';
|
||||
|
||||
export const RULE_NAME = '[data-test-subj^=formatted-field][data-test-subj$=rule\\.name]';
|
||||
export const RULE_NAME = '[data-test-subj$=ruleName]';
|
||||
|
||||
export const SELECTED_ALERTS = '[data-test-subj="selectedShowBulkActionsButton"]';
|
||||
|
||||
|
@ -99,7 +99,7 @@ export const OPEN_ANALYZER_BTN = '[data-test-subj="view-in-analyzer"]';
|
|||
|
||||
export const ANALYZER_NODE = '[data-test-subj="resolver:node"';
|
||||
|
||||
export const SEVERITY = '[data-test-subj^=formatted-field][data-test-subj$=severity]';
|
||||
export const SEVERITY = '[data-test-subj$=severity]';
|
||||
|
||||
export const SOURCE_IP = '[data-test-subj^=formatted-field][data-test-subj$=source\\.ip]';
|
||||
|
||||
|
|
|
@ -74,9 +74,6 @@ export const UPGRADE_SELECTED_RULES_BUTTON = '[data-test-subj="upgradeSelectedRu
|
|||
|
||||
export const GO_BACK_TO_RULES_TABLE_BUTTON = '[data-test-subj="addRulesGoBackToRulesTableBtn"]';
|
||||
|
||||
export const RULES_TABLE_INITIAL_LOADING_INDICATOR =
|
||||
'[data-test-subj="initialLoadingPanelAllRulesTable"]';
|
||||
|
||||
export const RULES_TABLE_REFRESH_INDICATOR = '[data-test-subj="loading-spinner"]';
|
||||
|
||||
export const RULES_TABLE_AUTOREFRESH_INDICATOR = '[data-test-subj="loadingRulesInfoProgress"]';
|
||||
|
|
|
@ -10,3 +10,5 @@ export const PAGE_TITLE = '[data-test-subj="header-page-title"]';
|
|||
export const NOT_FOUND = '[data-test-subj="notFoundPage"]';
|
||||
|
||||
export const LOADING_SPINNER = '.euiLoadingSpinner';
|
||||
|
||||
export const PAGE_CONTENT_SPINNER = `[data-test-subj="pageContainer"] ${LOADING_SPINNER}`;
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export const ALL_ACTIONS = '[data-test-subj="rules-details-popover-button-icon"]';
|
||||
export const POPOVER_ACTIONS_TRIGGER_BUTTON =
|
||||
'[data-test-subj="rules-details-popover-button-icon"]';
|
||||
|
||||
export const ABOUT_INVESTIGATION_NOTES = '[data-test-subj="stepAboutDetailsNoteContent"]';
|
||||
|
||||
|
@ -14,6 +15,8 @@ export const ABOUT_RULE_DESCRIPTION = '[data-test-subj=stepAboutRuleDetailsToggl
|
|||
export const ABOUT_DETAILS =
|
||||
'[data-test-subj="aboutRule"] [data-test-subj="listItemColumnStepRuleDescription"]';
|
||||
|
||||
export const ACTIONS = '[data-test-subj="actions"]';
|
||||
|
||||
export const ADDITIONAL_LOOK_BACK_DETAILS = 'Additional look-back time';
|
||||
|
||||
export const ALERTS_TAB = '[data-test-subj="navigation-alerts"]';
|
||||
|
|
|
@ -7,15 +7,10 @@
|
|||
|
||||
import { duplicatedRuleName } from '../objects/rule';
|
||||
import {
|
||||
BULK_ACTIONS_BTN,
|
||||
COLLAPSED_ACTION_BTN,
|
||||
CUSTOM_RULES_BTN,
|
||||
DELETE_RULE_ACTION_BTN,
|
||||
DELETE_RULE_BULK_BTN,
|
||||
RULES_SELECTED_TAG,
|
||||
RULES_TABLE_INITIAL_LOADING_INDICATOR,
|
||||
RULES_TABLE_AUTOREFRESH_INDICATOR,
|
||||
RULE_CHECKBOX,
|
||||
RULE_NAME,
|
||||
RULE_SWITCH,
|
||||
RULE_SWITCH_LOADER,
|
||||
|
@ -24,14 +19,11 @@ import {
|
|||
EDIT_RULE_ACTION_BTN,
|
||||
DUPLICATE_RULE_ACTION_BTN,
|
||||
DUPLICATE_RULE_MENU_PANEL_BTN,
|
||||
DUPLICATE_RULE_BULK_BTN,
|
||||
CONFIRM_DUPLICATE_RULE,
|
||||
RULES_ROW,
|
||||
SELECT_ALL_RULES_BTN,
|
||||
MODAL_CONFIRMATION_BTN,
|
||||
RULES_DELETE_CONFIRMATION_MODAL,
|
||||
ENABLE_RULE_BULK_BTN,
|
||||
DISABLE_RULE_BULK_BTN,
|
||||
RULE_DETAILS_DELETE_BTN,
|
||||
RULE_IMPORT_MODAL_BUTTON,
|
||||
RULE_IMPORT_MODAL,
|
||||
|
@ -44,7 +36,6 @@ import {
|
|||
SELECTED_RULES_NUMBER_LABEL,
|
||||
REFRESH_SETTINGS_SWITCH,
|
||||
ELASTIC_RULES_BTN,
|
||||
BULK_EXPORT_ACTION_BTN,
|
||||
TOASTER_ERROR_BTN,
|
||||
MODAL_CONFIRMATION_CANCEL_BTN,
|
||||
MODAL_CONFIRMATION_BODY,
|
||||
|
@ -59,22 +50,25 @@ import {
|
|||
DISABLED_RULES_BTN,
|
||||
REFRESH_RULES_TABLE_BUTTON,
|
||||
RULE_LAST_RUN,
|
||||
DUPLICATE_WITHOUT_EXCEPTIONS_OPTION,
|
||||
DUPLICATE_WITH_EXCEPTIONS_OPTION,
|
||||
DUPLICATE_WITH_EXCEPTIONS_WITHOUT_EXPIRED_OPTION,
|
||||
TOASTER_CLOSE_ICON,
|
||||
ADD_ELASTIC_RULES_EMPTY_PROMPT_BTN,
|
||||
AUTO_REFRESH_POPOVER_TRIGGER_BUTTON,
|
||||
SELECT_ALL_RULES_ON_PAGE_CHECKBOX,
|
||||
BULK_ACTIONS_BTN,
|
||||
BULK_EXPORT_ACTION_BTN,
|
||||
} from '../screens/alerts_detection_rules';
|
||||
import type { RULES_MONITORING_TABLE } from '../screens/alerts_detection_rules';
|
||||
import { EUI_CHECKBOX } from '../screens/common/controls';
|
||||
import { ALL_ACTIONS } from '../screens/rule_details';
|
||||
import { POPOVER_ACTIONS_TRIGGER_BUTTON, RULE_NAME_HEADER } from '../screens/rule_details';
|
||||
import { EDIT_SUBMIT_BUTTON } from '../screens/edit_rule';
|
||||
import { LOADING_INDICATOR } from '../screens/security_header';
|
||||
import { PAGE_CONTENT_SPINNER } from '../screens/common/page';
|
||||
|
||||
import { goToRuleEditSettings } from './rule_details';
|
||||
import { goToActionsStepTab } from './create_new_rule';
|
||||
|
||||
export const getRulesManagementTableRows = () => cy.get(RULES_MANAGEMENT_TABLE).find(RULES_ROW);
|
||||
|
||||
export const enableRule = (rulePosition: number) => {
|
||||
cy.get(RULE_SWITCH).eq(rulePosition).click();
|
||||
};
|
||||
|
@ -102,7 +96,7 @@ export const duplicateFirstRule = () => {
|
|||
*/
|
||||
export const duplicateRuleFromMenu = () => {
|
||||
cy.get(LOADING_INDICATOR).should('not.exist');
|
||||
cy.get(ALL_ACTIONS).click({ force: true });
|
||||
cy.get(POPOVER_ACTIONS_TRIGGER_BUTTON).click({ force: true });
|
||||
cy.get(DUPLICATE_RULE_MENU_PANEL_BTN).should('be.visible');
|
||||
|
||||
// Because of a fade effect and fast clicking this can produce more than one click
|
||||
|
@ -126,59 +120,10 @@ export const deleteFirstRule = () => {
|
|||
cy.get(DELETE_RULE_ACTION_BTN).click();
|
||||
};
|
||||
|
||||
export const deleteSelectedRules = () => {
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(DELETE_RULE_BULK_BTN).click();
|
||||
};
|
||||
|
||||
export const deleteRuleFromDetailsPage = () => {
|
||||
cy.get(ALL_ACTIONS).should('be.visible');
|
||||
// We cannot use cy.root().pipe($el) withing this function and instead have to use a cy.wait()
|
||||
// for the click handler to be registered. If you see flake here because of click handler issues
|
||||
// increase the cy.wait(). The reason we cannot use cypress pipe is because multiple clicks on ALL_ACTIONS
|
||||
// causes the pop up to show and then the next click for it to hide. Multiple clicks can cause
|
||||
// the DOM to queue up and once we detect that the element is visible it can then become invisible later
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(1000);
|
||||
cy.get(ALL_ACTIONS).click();
|
||||
cy.get(POPOVER_ACTIONS_TRIGGER_BUTTON).click();
|
||||
cy.get(RULE_DETAILS_DELETE_BTN).click();
|
||||
cy.get(RULE_DETAILS_DELETE_BTN).should('not.be.visible');
|
||||
};
|
||||
|
||||
export const duplicateSelectedRulesWithoutExceptions = () => {
|
||||
cy.log('Duplicate selected rules');
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(DUPLICATE_RULE_BULK_BTN).click();
|
||||
cy.get(DUPLICATE_WITHOUT_EXCEPTIONS_OPTION).click();
|
||||
cy.get(CONFIRM_DUPLICATE_RULE).click();
|
||||
};
|
||||
|
||||
export const duplicateSelectedRulesWithExceptions = () => {
|
||||
cy.log('Duplicate selected rules');
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(DUPLICATE_RULE_BULK_BTN).click();
|
||||
cy.get(DUPLICATE_WITH_EXCEPTIONS_OPTION).click();
|
||||
cy.get(CONFIRM_DUPLICATE_RULE).click();
|
||||
};
|
||||
|
||||
export const duplicateSelectedRulesWithNonExpiredExceptions = () => {
|
||||
cy.log('Duplicate selected rules');
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(DUPLICATE_RULE_BULK_BTN).click();
|
||||
cy.get(DUPLICATE_WITH_EXCEPTIONS_WITHOUT_EXPIRED_OPTION).click();
|
||||
cy.get(CONFIRM_DUPLICATE_RULE).click();
|
||||
};
|
||||
|
||||
export const enableSelectedRules = () => {
|
||||
cy.log('Enable selected rules');
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(ENABLE_RULE_BULK_BTN).click();
|
||||
};
|
||||
|
||||
export const disableSelectedRules = () => {
|
||||
cy.log('Disable selected rules');
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(DISABLE_RULE_BULK_BTN).click();
|
||||
cy.get(RULE_DETAILS_DELETE_BTN).should('not.exist');
|
||||
};
|
||||
|
||||
export const exportRule = (name: string) => {
|
||||
|
@ -233,48 +178,34 @@ 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) => {
|
||||
cy.contains(RULE_NAME, ruleName).click();
|
||||
|
||||
cy.get(PAGE_CONTENT_SPINNER).should('be.visible');
|
||||
cy.contains(RULE_NAME_HEADER, ruleName).should('be.visible');
|
||||
cy.get(PAGE_CONTENT_SPINNER).should('not.exist');
|
||||
};
|
||||
|
||||
export const openIntegrationsPopover = () => {
|
||||
cy.get(INTEGRATIONS_POPOVER).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Selects the number of rules. Since there can be missing click handlers
|
||||
* when the page loads at first, we use a pipe and a trigger of click
|
||||
* on it and then check to ensure that it is checked before continuing
|
||||
* with the tests.
|
||||
* @param numberOfRules The number of rules to click/check
|
||||
*/
|
||||
export const selectNumberOfRules = (numberOfRules: number) => {
|
||||
for (let i = 0; i < numberOfRules; i++) {
|
||||
cy.get(RULE_CHECKBOX).eq(i).check();
|
||||
cy.get(RULE_CHECKBOX).eq(i).should('be.checked');
|
||||
export const selectRulesByName = (ruleNames: Readonly<string[]>) => {
|
||||
for (const ruleName of ruleNames) {
|
||||
selectRuleByName(ruleName);
|
||||
}
|
||||
};
|
||||
|
||||
export const unselectRuleByName = (ruleName: string) => {
|
||||
cy.contains(RULE_NAME, ruleName).parents(RULES_ROW).find(EUI_CHECKBOX).uncheck();
|
||||
cy.contains(RULE_NAME, ruleName).parents(RULES_ROW).find(EUI_CHECKBOX).should('not.be.checked');
|
||||
};
|
||||
|
||||
/**
|
||||
* Unselects a passed number of rules. To use together with selectNumberOfRules
|
||||
* as this utility will expect and check the passed number of rules
|
||||
* to have been previously checked.
|
||||
* @param numberOfRules The number of rules to click/check
|
||||
*/
|
||||
export const unselectNumberOfRules = (numberOfRules: number) => {
|
||||
for (let i = 0; i < numberOfRules; i++) {
|
||||
cy.get(RULE_CHECKBOX).eq(i).should('be.checked');
|
||||
cy.get(RULE_CHECKBOX).eq(i).uncheck();
|
||||
cy.get(RULE_CHECKBOX).eq(i).should('not.be.checked');
|
||||
export const unselectRulesByName = (ruleNames: Readonly<string[]>) => {
|
||||
for (const ruleName of ruleNames) {
|
||||
unselectRuleByName(ruleName);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -284,6 +215,12 @@ export const selectAllRules = () => {
|
|||
cy.get(SELECT_ALL_RULES_BTN).contains('Clear');
|
||||
};
|
||||
|
||||
export const selectAllRulesOnPage = () => {
|
||||
cy.log('Select all rules on page');
|
||||
cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).check();
|
||||
cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).should('be.checked');
|
||||
};
|
||||
|
||||
export const clearAllRuleSelection = () => {
|
||||
cy.log('Clear all rules selection');
|
||||
cy.get(SELECT_ALL_RULES_BTN).contains('Clear').click();
|
||||
|
@ -314,21 +251,6 @@ export const waitForRulesTableToShow = () => {
|
|||
cy.get(RULES_MANAGEMENT_TABLE, { timeout: 300000 }).should('exist');
|
||||
};
|
||||
|
||||
/**
|
||||
* Because the Rule Management page is relatively slow, in order to avoid timeouts and flakiness,
|
||||
* we almost always want to wait until the Rules table is "loaded" before we do anything with it.
|
||||
*
|
||||
* This task can be needed for some tests that e.g. check the table load/refetch/pagination logic.
|
||||
* It waits for the table's own loading indicator to show up and disappear.
|
||||
*
|
||||
* NOTE: Normally, we should not rely on loading indicators in tests, because due to their
|
||||
* dynamic nature it's possible to introduce race conditions and flakiness.
|
||||
*/
|
||||
export const waitForRulesTableToBeLoaded = () => {
|
||||
// Wait up to 5 minutes for the rules to load as in CI containers this can be very slow
|
||||
cy.get(RULES_TABLE_INITIAL_LOADING_INDICATOR, { timeout: 300000 }).should('not.exist');
|
||||
};
|
||||
|
||||
export const waitForRulesTableToBeRefreshed = () => {
|
||||
cy.get(RULES_TABLE_REFRESH_INDICATOR).should('exist');
|
||||
cy.get(RULES_TABLE_REFRESH_INDICATOR).should('not.exist');
|
||||
|
@ -352,12 +274,6 @@ export const waitForRuleToUpdate = () => {
|
|||
cy.get(RULE_SWITCH_LOADER, { timeout: 300000 }).should('not.exist');
|
||||
};
|
||||
|
||||
export const checkAutoRefresh = (ms: number, condition: string) => {
|
||||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should('not.exist');
|
||||
cy.tick(ms);
|
||||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should(condition);
|
||||
};
|
||||
|
||||
export const importRules = (rulesFile: string) => {
|
||||
cy.get(RULE_IMPORT_MODAL).click();
|
||||
cy.get(INPUT_FILE).click({ force: true });
|
||||
|
@ -582,3 +498,19 @@ export const goToEditRuleActionsSettingsOf = (name: string) => {
|
|||
cy.get(EDIT_SUBMIT_BUTTON).should('be.enabled');
|
||||
goToActionsStepTab();
|
||||
};
|
||||
|
||||
export const getRuleRow = (ruleName: string) => cy.contains(RULE_NAME, ruleName).parents(RULES_ROW);
|
||||
|
||||
const selectRuleByName = (ruleName: string) => {
|
||||
cy.log(`Select rule "${ruleName}"`);
|
||||
getRuleRow(ruleName).find(EUI_CHECKBOX).check();
|
||||
cy.log(`Make sure rule "${ruleName}" has been selected`);
|
||||
getRuleRow(ruleName).find(EUI_CHECKBOX).should('be.checked');
|
||||
};
|
||||
|
||||
const unselectRuleByName = (ruleName: string) => {
|
||||
cy.log(`Unselect rule "${ruleName}"`);
|
||||
getRuleRow(ruleName).find(EUI_CHECKBOX).uncheck();
|
||||
cy.log(`Make sure rule "${ruleName}" has been unselected`);
|
||||
getRuleRow(ruleName).find(EUI_CHECKBOX).should('not.be.checked');
|
||||
};
|
||||
|
|
|
@ -83,7 +83,7 @@ export const createNewRuleAsset = ({
|
|||
}) => {
|
||||
const url = `${Cypress.env('ELASTICSEARCH_URL')}/${index}/_doc/security-rule:${
|
||||
rule['security-rule'].rule_id
|
||||
}`;
|
||||
}&refresh`;
|
||||
cy.waitUntil(
|
||||
() => {
|
||||
return cy
|
||||
|
@ -188,14 +188,14 @@ export const createAndInstallMockedPrebuiltRules = ({
|
|||
rules,
|
||||
installToKibana = true,
|
||||
}: {
|
||||
rules?: Array<typeof SAMPLE_PREBUILT_RULE>;
|
||||
rules: Array<typeof SAMPLE_PREBUILT_RULE>;
|
||||
installToKibana?: boolean;
|
||||
}) => {
|
||||
cy.log('Install prebuilt rules');
|
||||
preventPrebuiltRulesPackageInstallation();
|
||||
// TODO: use this bulk method once the issue with Cypress is fixed
|
||||
// bulkCreateRuleAssets({ rules });
|
||||
rules?.forEach((rule) => {
|
||||
rules.forEach((rule) => {
|
||||
createNewRuleAsset({ rule });
|
||||
});
|
||||
if (installToKibana) {
|
||||
|
|
|
@ -117,7 +117,7 @@ export const deleteAlertsAndRules = () => {
|
|||
|
||||
rootRequest({
|
||||
method: 'POST',
|
||||
url: `${kibanaIndexUrl}/_delete_by_query?conflicts=proceed`,
|
||||
url: `${kibanaIndexUrl}/_delete_by_query?conflicts=proceed&refresh`,
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
|
@ -137,7 +137,7 @@ export const deleteAlertsAndRules = () => {
|
|||
method: 'POST',
|
||||
url: `${Cypress.env(
|
||||
'ELASTICSEARCH_URL'
|
||||
)}/.lists-*,.items-*,.alerts-security.alerts-*/_delete_by_query?conflicts=proceed&scroll_size=10000`,
|
||||
)}/.lists-*,.items-*,.alerts-security.alerts-*/_delete_by_query?conflicts=proceed&scroll_size=10000&refresh`,
|
||||
body: {
|
||||
query: {
|
||||
match_all: {},
|
||||
|
@ -150,7 +150,7 @@ export const deleteTimelines = () => {
|
|||
const kibanaIndexUrl = `${Cypress.env('ELASTICSEARCH_URL')}/.kibana_\*`;
|
||||
rootRequest({
|
||||
method: 'POST',
|
||||
url: `${kibanaIndexUrl}/_delete_by_query?conflicts=proceed`,
|
||||
url: `${kibanaIndexUrl}/_delete_by_query?conflicts=proceed&refresh`,
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
|
@ -180,7 +180,7 @@ export const deleteCases = () => {
|
|||
const kibanaIndexUrl = `${Cypress.env('ELASTICSEARCH_URL')}/.kibana_\*`;
|
||||
rootRequest({
|
||||
method: 'POST',
|
||||
url: `${kibanaIndexUrl}/_delete_by_query?conflicts=proceed`,
|
||||
url: `${kibanaIndexUrl}/_delete_by_query?conflicts=proceed&refresh`,
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
|
@ -201,7 +201,7 @@ export const deleteConnectors = () => {
|
|||
const kibanaIndexUrl = `${Cypress.env('ELASTICSEARCH_URL')}/.kibana_\*`;
|
||||
rootRequest({
|
||||
method: 'POST',
|
||||
url: `${kibanaIndexUrl}/_delete_by_query?conflicts=proceed`,
|
||||
url: `${kibanaIndexUrl}/_delete_by_query?conflicts=proceed&refresh`,
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
|
|
|
@ -12,8 +12,13 @@ import Url from 'url';
|
|||
|
||||
import type { ROLES } from '../../common/test';
|
||||
import { NEW_FEATURES_TOUR_STORAGE_KEYS } from '../../common/constants';
|
||||
import { hostDetailsUrl, LOGOUT_URL, userDetailsUrl } from '../urls/navigation';
|
||||
import { waitForPageToBeLoaded } from './common';
|
||||
import {
|
||||
hostDetailsUrl,
|
||||
LOGOUT_URL,
|
||||
SECURITY_DETECTIONS_RULES_URL,
|
||||
userDetailsUrl,
|
||||
} from '../urls/navigation';
|
||||
import { resetRulesTableState, waitForPageToBeLoaded } from './common';
|
||||
|
||||
/**
|
||||
* Credentials in the `kibana.dev.yml` config file will be used to authenticate
|
||||
|
@ -387,6 +392,11 @@ export const visitHostDetailsPage = (hostName = 'suricata-iowa') => {
|
|||
cy.get('[data-test-subj="loading-spinner"]').should('not.exist');
|
||||
};
|
||||
|
||||
export const visitSecurityDetectionRulesPage = (role?: ROLES) => {
|
||||
resetRulesTableState(); // Clear persistent rules filter data before page loading
|
||||
visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL, role);
|
||||
};
|
||||
|
||||
export const visitUserDetailsPage = (userName = 'test') => {
|
||||
visit(userDetailsUrl(userName));
|
||||
};
|
||||
|
|
|
@ -15,6 +15,14 @@ import {
|
|||
MODAL_CONFIRMATION_BODY,
|
||||
TOASTER_BODY,
|
||||
RULES_TAGS_FILTER_BTN,
|
||||
CONFIRM_DUPLICATE_RULE,
|
||||
DELETE_RULE_BULK_BTN,
|
||||
DISABLE_RULE_BULK_BTN,
|
||||
DUPLICATE_RULE_BULK_BTN,
|
||||
DUPLICATE_WITHOUT_EXCEPTIONS_OPTION,
|
||||
DUPLICATE_WITH_EXCEPTIONS_OPTION,
|
||||
DUPLICATE_WITH_EXCEPTIONS_WITHOUT_EXPIRED_OPTION,
|
||||
ENABLE_RULE_BULK_BTN,
|
||||
} from '../screens/alerts_detection_rules';
|
||||
|
||||
import {
|
||||
|
@ -43,6 +51,50 @@ import {
|
|||
} from '../screens/rules_bulk_edit';
|
||||
import { SCHEDULE_DETAILS } from '../screens/rule_details';
|
||||
|
||||
// DELETE
|
||||
export const deleteSelectedRules = () => {
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(DELETE_RULE_BULK_BTN).click();
|
||||
};
|
||||
|
||||
// DUPLICATE
|
||||
export const duplicateSelectedRulesWithoutExceptions = () => {
|
||||
cy.log('Bulk duplicate selected rules without exceptions');
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(DUPLICATE_RULE_BULK_BTN).click();
|
||||
cy.get(DUPLICATE_WITHOUT_EXCEPTIONS_OPTION).click();
|
||||
cy.get(CONFIRM_DUPLICATE_RULE).click();
|
||||
};
|
||||
|
||||
export const duplicateSelectedRulesWithExceptions = () => {
|
||||
cy.log('Bulk duplicate selected rules with exceptions');
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(DUPLICATE_RULE_BULK_BTN).click();
|
||||
cy.get(DUPLICATE_WITH_EXCEPTIONS_OPTION).click();
|
||||
cy.get(CONFIRM_DUPLICATE_RULE).click();
|
||||
};
|
||||
|
||||
export const duplicateSelectedRulesWithNonExpiredExceptions = () => {
|
||||
cy.log('Bulk duplicate selected rules with non expired exceptions');
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(DUPLICATE_RULE_BULK_BTN).click();
|
||||
cy.get(DUPLICATE_WITH_EXCEPTIONS_WITHOUT_EXPIRED_OPTION).click();
|
||||
cy.get(CONFIRM_DUPLICATE_RULE).click();
|
||||
};
|
||||
|
||||
// ENABLE/DISABLE
|
||||
export const enableSelectedRules = () => {
|
||||
cy.log('Bulk enable selected rules');
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(ENABLE_RULE_BULK_BTN).click();
|
||||
};
|
||||
|
||||
export const disableSelectedRules = () => {
|
||||
cy.log('Bulk disable selected rules');
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(DISABLE_RULE_BULK_BTN).click();
|
||||
};
|
||||
|
||||
export const clickApplyTimelineTemplatesMenuItem = () => {
|
||||
cy.get(BULK_ACTIONS_BTN).click();
|
||||
cy.get(APPLY_TIMELINE_RULE_BULK_MENU_ITEM).click();
|
||||
|
|
|
@ -38,5 +38,6 @@
|
|||
"@kbn/core-http-common",
|
||||
"@kbn/data-views-plugin",
|
||||
"@kbn/fleet-plugin",
|
||||
"@kbn/securitysolution-io-ts-utils",
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue