[8.18] [Security Solution] Adds prebuilt rule import/export cypress tests (#212172) (#212309)

# Backport

This will backport the following commits from `main` to `8.18`:
- [[Security Solution] Adds prebuilt rule import/export cypress tests
(#212172)](https://github.com/elastic/kibana/pull/212172)

<!--- Backport version: 9.6.6 -->

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

<!--BACKPORT [{"author":{"name":"Davis
Plumlee","email":"56367316+dplumlee@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-02-24T21:17:44Z","message":"[Security
Solution] Adds prebuilt rule import/export cypress tests
(#212172)\n\n**Partially addresses:**
https://github.com/elastic/kibana/issues/202079\n\n## Summary\n\nAdds
cypress tests in accordance
to\nhttps://github.com/elastic/kibana/pull/204889\n\nFollow-up to:
https://github.com/elastic/kibana/pull/206893\n\nAdds tests for rule
import and export related to the prebuilt rule\ncustomization epic.\n###
Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers
should verify this PR satisfies this list as well.\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common scenarios\n- [x] [Flaky
Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\nused on any tests changed\n- [x] 🟢 ESS
x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7923\n-
[x] 🟢 Serverless
x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7924","sha":"427d2d992988a125f00075ae959c33f6d2bc7a6e","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["test","release_note:skip","v9.0.0","Team:Detections
and Resp","Team: SecuritySolution","Team:Detection Rule
Management","Feature:Prebuilt Detection
Rules","backport:version","v8.18.0","v9.1.0","v8.19.0"],"title":"[Security
Solution] Adds prebuilt rule import/export cypress
tests","number":212172,"url":"https://github.com/elastic/kibana/pull/212172","mergeCommit":{"message":"[Security
Solution] Adds prebuilt rule import/export cypress tests
(#212172)\n\n**Partially addresses:**
https://github.com/elastic/kibana/issues/202079\n\n## Summary\n\nAdds
cypress tests in accordance
to\nhttps://github.com/elastic/kibana/pull/204889\n\nFollow-up to:
https://github.com/elastic/kibana/pull/206893\n\nAdds tests for rule
import and export related to the prebuilt rule\ncustomization epic.\n###
Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers
should verify this PR satisfies this list as well.\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common scenarios\n- [x] [Flaky
Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\nused on any tests changed\n- [x] 🟢 ESS
x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7923\n-
[x] 🟢 Serverless
x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7924","sha":"427d2d992988a125f00075ae959c33f6d2bc7a6e"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.18","8.x"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/212172","number":212172,"mergeCommit":{"message":"[Security
Solution] Adds prebuilt rule import/export cypress tests
(#212172)\n\n**Partially addresses:**
https://github.com/elastic/kibana/issues/202079\n\n## Summary\n\nAdds
cypress tests in accordance
to\nhttps://github.com/elastic/kibana/pull/204889\n\nFollow-up to:
https://github.com/elastic/kibana/pull/206893\n\nAdds tests for rule
import and export related to the prebuilt rule\ncustomization epic.\n###
Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers
should verify this PR satisfies this list as well.\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common scenarios\n- [x] [Flaky
Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\nused on any tests changed\n- [x] 🟢 ESS
x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7923\n-
[x] 🟢 Serverless
x50:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7924","sha":"427d2d992988a125f00075ae959c33f6d2bc7a6e"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Davis Plumlee <56367316+dplumlee@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2025-02-26 00:57:19 +11:00 committed by GitHub
parent ffddd1d4af
commit 72aa9f258f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 414 additions and 25 deletions

View file

@ -0,0 +1,230 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { bulkExportRules } from '../../../../tasks/rules_bulk_actions';
import { exportRuleFromDetailsPage } from '../../../../tasks/rule_details';
import {
expectedExportedRule,
expectedExportedRules,
getIndexPatterns,
getNewRule,
} from '../../../../objects/rule';
import {
exportRule,
filterByCustomRules,
filterByElasticRules,
selectAllRules,
selectRulesByName,
} from '../../../../tasks/alerts_detection_rules';
import { RULE_NAME, TOASTER_BODY } from '../../../../screens/alerts_detection_rules';
import { createRuleAssetSavedObject } from '../../../../helpers/rules';
import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common';
import { createAndInstallMockedPrebuiltRules } from '../../../../tasks/api_calls/prebuilt_rules';
import { createRule, findRuleByRuleId, patchRule } from '../../../../tasks/api_calls/rules';
import { login } from '../../../../tasks/login';
import { visitRulesManagementTable } from '../../../../tasks/rules_management';
const PREBUILT_RULE_ID = 'rule_1';
describe(
'Detection rules, Prebuilt Rules Export workflow - With Rule Customization',
{
tags: ['@ess', '@serverless', '@skipInServerlessMKI'],
env: {
ftrConfig: {
kbnServerArgs: [
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'prebuiltRulesCustomizationEnabled',
])}`,
],
},
},
},
() => {
describe('Rule export workflow with single rules', () => {
const PREBUILT_RULE = createRuleAssetSavedObject({
name: 'Non-customized prebuilt rule',
rule_id: PREBUILT_RULE_ID,
version: 1,
index: getIndexPatterns(),
});
beforeEach(() => {
login();
deleteAlertsAndRules();
cy.intercept('POST', '/api/detection_engine/rules/_bulk_action').as('bulk_action');
/* Create a new rule and install it */
createAndInstallMockedPrebuiltRules([PREBUILT_RULE]);
createRule(
getNewRule({ name: 'Custom rule to export', rule_id: 'custom_rule_id', enabled: false })
).as('customRuleResponse');
visitRulesManagementTable();
});
it('can export non-customized prebuilt rules from the rule management table individually', function () {
findRuleByRuleId(PREBUILT_RULE_ID).as('prebuiltRuleResponse');
exportRule('Non-customized prebuilt rule');
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should('eql', expectedExportedRule(this.prebuiltRuleResponse));
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
});
});
it('can export customized prebuilt rules from the rule management table individually', function () {
patchRule(PREBUILT_RULE_ID, { name: 'Customized prebuilt rule' }).as(
'prebuiltRuleResponse'
); // We want to make this a customized prebuilt rule
exportRule('Customized prebuilt rule');
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should('eql', expectedExportedRule(this.prebuiltRuleResponse));
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
});
});
it('can export custom rules from the rule management table individually', function () {
exportRule('Custom rule to export');
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should('eql', expectedExportedRule(this.customRuleResponse));
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
});
});
it('can export a non-customized prebuilt rule from the rule details page', function () {
findRuleByRuleId(PREBUILT_RULE_ID).as('prebuiltRuleResponse');
cy.get(RULE_NAME).contains('Non-customized prebuilt rule').click();
exportRuleFromDetailsPage();
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should('eql', expectedExportedRule(this.prebuiltRuleResponse));
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
});
});
it('can export a customized prebuilt rule from the rule details page', function () {
patchRule(PREBUILT_RULE_ID, { name: 'Customized prebuilt rule' }).as(
'prebuiltRuleResponse'
); // We want to make this a customized prebuilt rule
cy.get(RULE_NAME).contains('Customized prebuilt rule').click();
exportRuleFromDetailsPage();
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should('eql', expectedExportedRule(this.prebuiltRuleResponse));
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
});
});
it('can export a custom rule from the rule details page', function () {
cy.get(RULE_NAME).contains('Custom rule to export').click();
exportRuleFromDetailsPage();
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should('eql', expectedExportedRule(this.customRuleResponse));
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
});
});
});
describe('Rule export workflow with multiple rules', () => {
const PREBUILT_RULE_1 = createRuleAssetSavedObject({
name: 'Non-customized prebuilt rule',
rule_id: PREBUILT_RULE_ID,
version: 1,
index: getIndexPatterns(),
});
const PREBUILT_RULE_2 = createRuleAssetSavedObject({
name: 'Non-customized prebuilt rule',
rule_id: 'rule_2',
version: 1,
index: getIndexPatterns(),
});
beforeEach(() => {
login();
deleteAlertsAndRules();
cy.intercept('POST', '/api/detection_engine/rules/_bulk_action').as('bulk_action');
/* Create a new rule and install it */
createAndInstallMockedPrebuiltRules([PREBUILT_RULE_1, PREBUILT_RULE_2]);
findRuleByRuleId(PREBUILT_RULE_ID).as('nonCustomizedPrebuiltRuleResponse');
// We want to make this a customized prebuilt rule
patchRule('rule_2', { name: 'Customized prebuilt rule' }).as(
'customizedPrebuiltRuleResponse'
);
createRule(getNewRule({ name: 'Custom rule to export', enabled: false })).as(
'customRuleResponse'
);
visitRulesManagementTable();
});
it('can export a non-customized prebuilt rule from the rule management table using the bulk actions menu', function () {
selectRulesByName(['Non-customized prebuilt rule']);
bulkExportRules();
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should(
'eql',
expectedExportedRule(this.nonCustomizedPrebuiltRuleResponse)
);
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
});
});
it('can export a customized prebuilt rule from the rule management table using the bulk actions menu', function () {
selectRulesByName(['Customized prebuilt rule']);
bulkExportRules();
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should(
'eql',
expectedExportedRule(this.customizedPrebuiltRuleResponse)
);
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
});
});
it('can export a custom rule from the rule management table using the bulk actions menu', function () {
filterByCustomRules();
selectAllRules();
bulkExportRules();
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should('eql', expectedExportedRule(this.customRuleResponse));
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 1 of 1 rule.');
});
});
it('can export all rule types from the rule management table using the bulk actions menu', function () {
selectAllRules();
bulkExportRules();
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should(
'eql',
expectedExportedRules([
this.nonCustomizedPrebuiltRuleResponse,
this.customizedPrebuiltRuleResponse,
this.customRuleResponse,
])
);
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 3 of 3 rules.');
});
});
it('can export customized and non-customized prebuilt rules from the rule management table using the bulk actions menu', function () {
filterByElasticRules();
selectAllRules();
bulkExportRules();
cy.wait('@bulk_action').then(({ response }) => {
cy.wrap(response?.body).should(
'eql',
expectedExportedRules([
this.nonCustomizedPrebuiltRuleResponse,
this.customizedPrebuiltRuleResponse,
])
);
cy.get(TOASTER_BODY).should('have.text', 'Successfully exported 2 of 2 rules.');
});
});
});
}
);

View file

@ -0,0 +1,95 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import {
expectToContainModifiedBadge,
expectToNotContainModifiedBadge,
importRulesWithOverwriteAll,
} from '../../../../tasks/alerts_detection_rules';
import { TOASTER } from '../../../../screens/alerts_detection_rules';
import { createRuleAssetSavedObject } from '../../../../helpers/rules';
import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common';
import { createAndInstallMockedPrebuiltRules } from '../../../../tasks/api_calls/prebuilt_rules';
import { login } from '../../../../tasks/login';
import { visitRulesManagementTable } from '../../../../tasks/rules_management';
const RULES_TO_IMPORT_FILENAME = 'cypress/fixtures/8_18_prebuilt_rules.ndjson';
describe(
'Detection rules, Prebuilt Rules Import workflow - With Rule Customization',
{
tags: ['@ess', '@serverless', '@skipInServerlessMKI'],
env: {
ftrConfig: {
kbnServerArgs: [
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'prebuiltRulesCustomizationEnabled',
])}`,
],
},
},
},
() => {
describe('when file is unmodified prebuilt rule with matching rule_id', () => {
const PREBUILT_RULE_1 = createRuleAssetSavedObject({
name: 'rule 1',
rule_id: 'rule_1',
version: 2,
});
beforeEach(() => {
login();
deleteAlertsAndRules();
cy.intercept('POST', '/api/detection_engine/rules/_import*').as('import');
/* Create a new rule and install it */
createAndInstallMockedPrebuiltRules([PREBUILT_RULE_1]);
visitRulesManagementTable();
});
it('can import the rule file', () => {
importRulesWithOverwriteAll(RULES_TO_IMPORT_FILENAME);
cy.wait('@import').then(({ response }) => {
cy.wrap(response?.statusCode).should('eql', 200);
cy.get(TOASTER).should('have.text', 'Successfully imported 1 rule');
expectToNotContainModifiedBadge('rule 1');
});
});
});
describe('when file is modified prebuilt rule with matching rule_id', () => {
const PREBUILT_RULE_1 = createRuleAssetSavedObject({
name: 'original rule 1',
rule_id: 'rule_1',
version: 2,
});
beforeEach(() => {
login();
deleteAlertsAndRules();
cy.intercept('POST', '/api/detection_engine/rules/_import*').as('import');
/* Create a new rule and install it */
createAndInstallMockedPrebuiltRules([PREBUILT_RULE_1]);
visitRulesManagementTable();
});
it('can import the rule file', () => {
importRulesWithOverwriteAll(RULES_TO_IMPORT_FILENAME);
cy.wait('@import').then(({ response }) => {
cy.wrap(response?.statusCode).should('eql', 200);
cy.get(TOASTER).should('have.text', 'Successfully imported 1 rule');
expectToContainModifiedBadge('rule 1');
});
});
});
}
);

View file

@ -0,0 +1,2 @@
{"id":"8ddab7fb-e049-4502-908f-bd040274c1b6","updated_at":"2025-01-16T05:03:09.376Z","updated_by":"system_indices_superuser","created_at":"2025-01-16T05:03:09.376Z","created_by":"system_indices_superuser","name":"rule 1","tags":[],"interval":"5m","enabled":false,"revision":0,"description":"some description","risk_score":55,"severity":"high","license":"Elastic License v2","output_index":"","author":[],"false_positives":[],"from":"now-6m","rule_id":"rule_1","max_signals":100,"risk_score_mapping":[],"severity_mapping":[],"threat":[],"to":"now","references":[],"version":2,"exceptions_list":[],"immutable":true,"rule_source":{"type":"external","is_customized":false},"related_integrations":[],"required_fields":[],"setup":"","type":"query","language":"kuery","query":"user.name: root or user.name: admin","actions":[]}
{"exported_count":1,"exported_rules_count":1,"missing_rules":[],"missing_rules_count":0,"exported_exception_list_count":0,"exported_exception_list_item_count":0,"missing_exception_list_item_count":0,"missing_exception_list_items":[],"missing_exception_lists":[],"missing_exception_lists_count":0,"exported_action_connector_count":0,"missing_action_connection_count":0,"missing_action_connections":[],"excluded_action_connection_count":0,"excluded_action_connections":[]}

View file

@ -523,7 +523,63 @@ export const getEditedRule = (): QueryRuleCreateProps =>
tags: [...(getExistingRule().tags || []), 'edited'],
});
export const expectedExportedRules = (responses: Array<Cypress.Response<RuleResponse>>): string => {
const rules = responses
.map((response) => JSON.stringify(getFormattedRuleResponse(response)))
.join('\n');
// NOTE: Order of the properties in this object matters for the tests to work.
const details = {
exported_count: responses.length,
exported_rules_count: responses.length,
missing_rules: [],
missing_rules_count: 0,
exported_exception_list_count: 0,
exported_exception_list_item_count: 0,
missing_exception_list_item_count: 0,
missing_exception_list_items: [],
missing_exception_lists: [],
missing_exception_lists_count: 0,
exported_action_connector_count: 0,
missing_action_connection_count: 0,
missing_action_connections: [],
excluded_action_connection_count: 0,
excluded_action_connections: [],
};
return `${rules}\n${JSON.stringify(details)}\n`;
};
export const expectedExportedRule = (ruleResponse: Cypress.Response<RuleResponse>): string => {
const rule = getFormattedRuleResponse(ruleResponse);
// NOTE: Order of the properties in this object matters for the tests to work.
const details = {
exported_count: 1,
exported_rules_count: 1,
missing_rules: [],
missing_rules_count: 0,
exported_exception_list_count: 0,
exported_exception_list_item_count: 0,
missing_exception_list_item_count: 0,
missing_exception_list_items: [],
missing_exception_lists: [],
missing_exception_lists_count: 0,
exported_action_connector_count: 0,
missing_action_connection_count: 0,
missing_action_connections: [],
excluded_action_connection_count: 0,
excluded_action_connections: [],
};
return `${JSON.stringify(rule)}\n${JSON.stringify(details)}\n`;
};
// TODO: Follow up https://github.com/elastic/kibana/pull/137628 and add an explicit type to this object
// without using Partial
const getFormattedRuleResponse = (
ruleResponse: Cypress.Response<RuleResponse>
): Partial<RuleResponse> => {
const {
id,
updated_at: updatedAt,
@ -555,6 +611,8 @@ export const expectedExportedRule = (ruleResponse: Cypress.Response<RuleResponse
related_integrations: relatedIntegrations,
setup,
investigation_fields: investigationFields,
license,
revision,
} = ruleResponse.body;
let query: string | undefined;
@ -563,9 +621,7 @@ export const expectedExportedRule = (ruleResponse: Cypress.Response<RuleResponse
}
// NOTE: Order of the properties in this object matters for the tests to work.
// TODO: Follow up https://github.com/elastic/kibana/pull/137628 and add an explicit type to this object
// without using Partial
const rule: Partial<RuleResponse> = {
return {
id,
updated_at: updatedAt,
updated_by: updatedBy,
@ -575,11 +631,12 @@ export const expectedExportedRule = (ruleResponse: Cypress.Response<RuleResponse
tags,
interval,
enabled,
revision: 0,
revision,
description,
risk_score: riskScore,
severity,
note,
license,
output_index: '',
investigation_fields: investigationFields,
author,
@ -605,28 +662,8 @@ export const expectedExportedRule = (ruleResponse: Cypress.Response<RuleResponse
query,
actions: [],
};
// NOTE: Order of the properties in this object matters for the tests to work.
const details = {
exported_count: 1,
exported_rules_count: 1,
missing_rules: [],
missing_rules_count: 0,
exported_exception_list_count: 0,
exported_exception_list_item_count: 0,
missing_exception_list_item_count: 0,
missing_exception_list_items: [],
missing_exception_lists: [],
missing_exception_lists_count: 0,
exported_action_connector_count: 0,
missing_action_connection_count: 0,
missing_action_connections: [],
excluded_action_connection_count: 0,
excluded_action_connections: [],
};
return `${JSON.stringify(rule)}\n${JSON.stringify(details)}\n`;
};
export const getEndpointRule = (): QueryRuleCreateProps => ({
type: 'query',
query: 'event.kind:alert and event.module:(endpoint and not endgame)',

View file

@ -110,6 +110,8 @@ export const ADD_ELASTIC_RULES_TABLE = '[data-test-subj="add-prebuilt-rules-tabl
export const RULES_ROW = '.euiTableRow';
export const RULE_ROW_MODIFIED_BADGE = '[data-test-subj="rulesTableModifiedColumnBadge"]';
export const SEVERITY = '[data-test-subj="severity"]';
export const SELECT_ALL_RULES_BTN = '[data-test-subj="selectAllRules"]';

View file

@ -8,6 +8,8 @@
export const POPOVER_ACTIONS_TRIGGER_BUTTON =
'[data-test-subj="rules-details-popover-button-icon"]';
export const EXPORT_RULE_ACTION_BUTTON = '[data-test-subj="rules-details-export-rule"]';
export const ABOUT_INVESTIGATION_NOTES = '[data-test-subj="stepAboutDetailsNoteContent"]';
export const ABOUT_RULE_DESCRIPTION = '[data-test-subj=stepAboutRuleDetailsToggleDescriptionText]';

View file

@ -56,6 +56,20 @@ export const patchRule = (
);
};
export const findRuleByRuleId = (
ruleId: string
): Cypress.Chainable<Cypress.Response<RuleResponse>> => {
return cy.currentSpace().then((spaceId) =>
rootRequest<RuleResponse>({
method: 'GET',
url: `${
spaceId ? getSpaceUrl(spaceId, DETECTION_ENGINE_RULES_URL) : DETECTION_ENGINE_RULES_URL
}?rule_id=${ruleId}`,
failOnStatusCode: false,
})
);
};
/**
* Snoozes a rule via API
*

View file

@ -46,6 +46,8 @@ import {
RULE_GAPS_STATUS_FILTER,
RULE_GAPS_DATE_FILTER_OPTION,
RULE_GAPS_DATE_PICKER_APPLY_REFRESH,
POPOVER_ACTIONS_TRIGGER_BUTTON,
EXPORT_RULE_ACTION_BUTTON,
} from '../screens/rule_details';
import { RuleDetailsTabs, ruleDetailsUrl } from '../urls/rule_details';
import {
@ -216,6 +218,11 @@ export const filterByRunType = (ruleType: string) => {
cy.get(EXECUTION_RUN_TYPE_FILTER_ITEM).contains(ruleType).click();
};
export const exportRuleFromDetailsPage = () => {
cy.get(POPOVER_ACTIONS_TRIGGER_BUTTON).click();
cy.get(EXPORT_RULE_ACTION_BUTTON).click();
};
export const getBackfillsTableRows = () => {
return cy.get(RULE_BACKFILLS_TABLE).find('tbody tr');
};