diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts index f844a2960deb3..4451048ee0816 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts @@ -21,12 +21,16 @@ import { bulkExportRules, selectAllRules, } from '../../tasks/alerts_detection_rules'; +import { createExceptionList, deleteExceptionList } from '../../tasks/api_calls/exceptions'; +import { getExceptionList } from '../../objects/exception'; import { createCustomRule } from '../../tasks/api_calls/rules'; import { cleanKibana, deleteAlertsAndRules } from '../../tasks/common'; import { login, visitWithoutDateRange } from '../../tasks/login'; import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +const exceptionList = getExceptionList(); + describe('Export rules', () => { before(() => { cleanKibana(); @@ -86,4 +90,48 @@ describe('Export rules', () => { `Successfully exported ${expectedNumberCustomRulesToBeExported} of ${totalNumberOfRules} rules. Prebuilt rules were excluded from the resulting file.` ); }); + + context('rules with exceptions', () => { + beforeEach(() => { + deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type); + // create rule with exceptions + createExceptionList(exceptionList, exceptionList.list_id).then((response) => + createCustomRule( + { + ...getNewRule(), + name: 'rule with exceptions', + exceptionLists: [ + { + id: response.body.id, + list_id: exceptionList.list_id, + type: exceptionList.type, + namespace_type: exceptionList.namespace_type, + }, + ], + }, + '2' + ) + ); + }); + + it('exports custom rules with exceptions', function () { + // one rule with exception, one without it + const expectedNumberCustomRulesToBeExported = 2; + + loadPrebuiltDetectionRulesFromHeaderBtn(); + + selectAllRules(); + bulkExportRules(); + + // should display correct number of custom rules when one of them has exceptions + cy.get(MODAL_CONFIRMATION_BTN) + .should('have.text', `Export ${expectedNumberCustomRulesToBeExported} custom rules`) + .click(); + + cy.get(TOASTER_BODY).should( + 'contain', + `Successfully exported ${expectedNumberCustomRulesToBeExported}` + ); + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/utils/dry_run_result.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/utils/dry_run_result.ts index 7fe7a9bd86012..5a15f03b9810d 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/utils/dry_run_result.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/utils/dry_run_result.ts @@ -38,7 +38,7 @@ export const processDryRunResult = (response: BulkActionResponse | undefined): D */ export const transformExportDetailsToDryRunResult = (details: ExportRulesDetails): DryRunResult => { return { - succeededRulesCount: details.exported_count, + succeededRulesCount: details.exported_rules_count, failedRulesCount: details.missing_rules_count, // if there are rules that can't be exported, it means they are immutable. So we can safely put error code as immutable ruleErrors: details.missing_rules.length