mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Security Solution] Skip all Detection & Response Cypress tests in Serverless (#165966)
**Resolves: https://github.com/elastic/kibana/issues/164441** ## Summary Skips all Cypress tests owned by @elastic/security-detection-rule-management and @elastic/security-detection-engine teams in Serverless using the new `@skipInServerless` tag. - Adds a new `@skipInServerless` tag - Updates `x-pack/test/security_solution_cypress/cypress/README.md` to explain when to use what tags - Explicitly adds missing tags to all D&R tests - Adds `// TODO:` comments to tests with links to follow-up tickets - Fixes the `x-pack/plugins/security_solution/scripts/run_cypress/parallel.ts` script (see below) Follow-up work: - https://github.com/elastic/kibana/issues/161540 - https://github.com/elastic/kibana/issues/161539 ## Context > Serverless test failures will soon block PR merge > During the development of the serverless test infrastructure, we decided that serverless tests will only soft-fail. That means you see the test failure in your PR but you're still able to merge. We did that mainly in order to not block delivery of stateful features and bug fixes while serverless tests and pipelines were implemented and stabilized. We now have the major building blocks for the serverless test infrastructure in place and will integrate serverless tests in our regular pipelines. As part of this process, we're skipping failing and flaky serverless tests that came in during the soft-fail phase. Once this is done, a PR with serverless test failures can no longer be merged, similar to how we have it for stateful test failures. > We plan to merge this in the next few days and we'll send out another notification when it's done. ## Fixing `parallel.ts` There were two problems with the `x-pack/plugins/security_solution/scripts/run_cypress/parallel.ts` script we use for running Cypress tests: - The script was broken in https://github.com/elastic/kibana/pull/162673 (here on [this line](https://github.com/elastic/kibana/pull/162673/files#diff-9f40ced6d29c4fc2709af881680400293d8ce1bc9ebb07b9138d6d99c83c09c9R67)) - I think it has never supported situations when all tests matching a spec pattern (such as `./cypress/e2e/!(investigations|explore)/**/*.cy.ts`) end up being skipped via Cypress tags (such as `@skipInServerless`) Both the issues are fixed in this PR. Code owners are added for this script in the CODEOWNERS file to prevent breaking this script in future PRs.
This commit is contained in:
parent
aa6ad19335
commit
1d65e7886e
69 changed files with 1359 additions and 1183 deletions
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -1316,6 +1316,7 @@ x-pack/test/security_solution_cypress/config.ts @elastic/security-engineering-pr
|
|||
x-pack/test/security_solution_cypress/runner.ts @elastic/security-engineering-productivity
|
||||
x-pack/test/security_solution_cypress/serverless_config.ts @elastic/security-engineering-productivity
|
||||
x-pack/test/security_solution_cypress/cypress/tags.ts @elastic/security-engineering-productivity
|
||||
x-pack/plugins/security_solution/scripts/run_cypress @MadameSheema @patrykkopycinski @oatkiller @maximpn @banderror
|
||||
|
||||
## Security Solution sub teams - adaptive-workload-protection
|
||||
x-pack/plugins/security_solution/public/common/components/sessions_viewer @elastic/kibana-cloud-security-posture
|
||||
|
|
|
@ -63,8 +63,14 @@ const retrieveIntegrations = (integrationsPaths: string[]) => {
|
|||
export const cli = () => {
|
||||
run(
|
||||
async () => {
|
||||
const log = new ToolingLog({
|
||||
level: 'info',
|
||||
writeTo: process.stdout,
|
||||
});
|
||||
|
||||
const { argv } = yargs(process.argv.slice(2))
|
||||
.coerce('spec', (arg) => (_.isArray(arg) ? [_.last(arg)] : [arg]))
|
||||
.coerce('configFile', (arg) => (_.isArray(arg) ? _.last(arg) : arg))
|
||||
.coerce('spec', (arg) => (_.isArray(arg) ? _.last(arg) : arg))
|
||||
.coerce('env', (arg: string) =>
|
||||
arg.split(',').reduce((acc, curr) => {
|
||||
const [key, value] = curr.split('=');
|
||||
|
@ -77,22 +83,72 @@ export const cli = () => {
|
|||
}, {} as Record<string, string | number>)
|
||||
);
|
||||
|
||||
log.info(`
|
||||
----------------------------------------------
|
||||
Script arguments:
|
||||
----------------------------------------------
|
||||
|
||||
${JSON.stringify(argv, null, 2)}
|
||||
|
||||
----------------------------------------------
|
||||
`);
|
||||
|
||||
const isOpen = argv._[0] === 'open';
|
||||
const cypressConfigFilePath = require.resolve(
|
||||
`../../${_.isArray(argv.configFile) ? _.last(argv.configFile) : argv.configFile}`
|
||||
) as string;
|
||||
|
||||
const cypressConfigFilePath = require.resolve(`../../${argv.configFile}`) as string;
|
||||
const cypressConfigFile = await import(cypressConfigFilePath);
|
||||
|
||||
log.info(`
|
||||
----------------------------------------------
|
||||
Cypress config for file: ${cypressConfigFilePath}:
|
||||
----------------------------------------------
|
||||
|
||||
${JSON.stringify(cypressConfigFile, null, 2)}
|
||||
|
||||
----------------------------------------------
|
||||
`);
|
||||
|
||||
const specConfig = cypressConfigFile.e2e.specPattern;
|
||||
const specArg = argv.spec;
|
||||
const specPattern = specArg ?? specConfig;
|
||||
|
||||
log.info('Config spec pattern:', specConfig);
|
||||
log.info('Arguments spec pattern:', specArg);
|
||||
log.info('Resulting spec pattern:', specPattern);
|
||||
|
||||
// The grep function will filter Cypress specs by tags: it will include and exclude
|
||||
// spec files according to the tags configuration.
|
||||
const grepSpecPattern = grep({
|
||||
...cypressConfigFile,
|
||||
specPattern: argv.spec ?? cypressConfigFile.e2e.specPattern,
|
||||
specPattern,
|
||||
excludeSpecPattern: [],
|
||||
}).specPattern;
|
||||
|
||||
let files = retrieveIntegrations(
|
||||
_.isArray(grepSpecPattern)
|
||||
? grepSpecPattern
|
||||
: globby.sync(argv.spec ?? cypressConfigFile.e2e.specPattern)
|
||||
);
|
||||
log.info('Resolved spec files or pattern after grep:', grepSpecPattern);
|
||||
|
||||
const isGrepReturnedFilePaths = _.isArray(grepSpecPattern);
|
||||
const isGrepReturnedSpecPattern = !isGrepReturnedFilePaths && grepSpecPattern === specPattern;
|
||||
|
||||
// IMPORTANT!
|
||||
// When grep returns the same spec pattern as it gets in its arguments, we treat it as
|
||||
// it couldn't find any concrete specs to execute (maybe because all of them are skipped).
|
||||
// In this case, we do an early return - it's important to do that.
|
||||
// If we don't return early, these specs will start executing, and Cypress will be skipping
|
||||
// tests at runtime: those that should be excluded according to the tags passed in the config.
|
||||
// This can take so much time that the job can fail by timeout in CI.
|
||||
if (isGrepReturnedSpecPattern) {
|
||||
log.info('No tests found - all tests could have been skipped via Cypress tags');
|
||||
// eslint-disable-next-line no-process-exit
|
||||
return process.exit(0);
|
||||
}
|
||||
|
||||
const concreteFilePaths = isGrepReturnedFilePaths
|
||||
? grepSpecPattern // use the returned concrete file paths
|
||||
: globby.sync(specPattern); // convert the glob pattern to concrete file paths
|
||||
|
||||
let files = retrieveIntegrations(concreteFilePaths);
|
||||
|
||||
log.info('Resolved spec files after retrieveIntegrations:', files);
|
||||
|
||||
if (argv.changedSpecsOnly) {
|
||||
files = (findChangedFiles('main', false) as string[]).reduce((acc, itemPath) => {
|
||||
|
@ -108,11 +164,6 @@ export const cli = () => {
|
|||
files = files.slice(0, 3);
|
||||
}
|
||||
|
||||
const log = new ToolingLog({
|
||||
level: 'info',
|
||||
writeTo: process.stdout,
|
||||
});
|
||||
|
||||
if (!files?.length) {
|
||||
log.info('No tests found');
|
||||
// eslint-disable-next-line no-process-exit
|
||||
|
|
|
@ -40,7 +40,12 @@ of data for your test, [**Running the tests**](#running-the-tests) to know how t
|
|||
|
||||
Please, before opening a PR with the new test, please make sure that the test fails. If you never see your test fail you don’t know if your test is actually testing the right thing, or testing anything at all.
|
||||
|
||||
Note that we use tags in order to select which tests we want to execute: @serverless, @ess and @brokenInServerless
|
||||
Note that we use tags in order to select which tests we want to execute:
|
||||
|
||||
- `@serverless` includes a test in the Serverless test suite. You need to explicitly add this tag to any test you want to run against a Serverless environment.
|
||||
- `@ess` includes a test in the normal, non-Serverless test suite. You need to explicitly add this tag to any test you want to run against a non-Serverless environment.
|
||||
- `@brokenInServerless` excludes a test from the Serverless test suite (even if it's tagged as `@serverless`). Indicates that a test should run in Serverless, but currently is broken.
|
||||
- `@skipInServerless` excludes a test from the Serverless test suite (even if it's tagged as `@serverless`). Could indicate many things, e.g. "the test is flaky in Serverless", "the test is Flaky in any type of environemnt", "the test has been temporarily excluded, see the comment above why".
|
||||
|
||||
Please, before opening a PR with a new test, make sure that the test fails. If you never see your test fail you don’t know if your test is actually testing the right thing, or testing anything at all.
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ export default defineCypressConfig({
|
|||
env: {
|
||||
grepFilterSpecs: true,
|
||||
grepOmitFiltered: true,
|
||||
grepTags: '@serverless --@brokenInServerless',
|
||||
grepTags: '@serverless --@brokenInServerless --@skipInServerless',
|
||||
},
|
||||
execTimeout: 150000,
|
||||
pageLoadTimeout: 150000,
|
||||
|
|
|
@ -23,7 +23,7 @@ export default defineCypressConfig({
|
|||
numTestsKeptInMemory: 10,
|
||||
env: {
|
||||
grepFilterSpecs: true,
|
||||
grepTags: '@serverless --@brokenInServerless',
|
||||
grepTags: '@serverless --@brokenInServerless --@skipInServerless',
|
||||
},
|
||||
e2e: {
|
||||
experimentalRunAllSpecs: true,
|
||||
|
|
|
@ -25,6 +25,7 @@ import { GET_TIMELINE_HEADER } from '../../screens/timeline';
|
|||
const alertRunTimeField = 'field.name.alert.page';
|
||||
const timelineRuntimeField = 'field.name.timeline';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe(
|
||||
'Create DataView runtime field',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
|
|
|
@ -35,12 +35,14 @@ const rolesToCreate = [secReadCasesAll];
|
|||
const siemDataViewTitle = 'Security Default Data View';
|
||||
const dataViews = ['auditbeat-*,fakebeat-*', 'auditbeat-*,*beat*,siem-read*,.kibana*,fakebeat-*'];
|
||||
|
||||
describe('Sourcerer', () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Sourcerer', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
before(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
dataViews.forEach((dataView: string) => postDataView(dataView));
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('permissions', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
createUsersAndRoles(usersToCreate, rolesToCreate);
|
||||
|
@ -52,6 +54,7 @@ describe('Sourcerer', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165766
|
||||
describe('Default scope', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -38,7 +38,8 @@ import { closeTimeline, openTimelineById } from '../../tasks/timeline';
|
|||
const siemDataViewTitle = 'Security Default Data View';
|
||||
const dataViews = ['auditbeat-*,fakebeat-*', 'auditbeat-*,*beat*,siem-read*,.kibana*,fakebeat-*'];
|
||||
|
||||
describe('Timeline scope', { tags: '@brokenInServerless' }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe.skip('Timeline scope', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
cy.clearLocalStorage();
|
||||
login();
|
||||
|
|
|
@ -38,7 +38,8 @@ import { closeTimeline, openTimelineById } from '../../tasks/timeline';
|
|||
const siemDataViewTitle = 'Security Default Data View';
|
||||
const dataViews = ['auditbeat-*,fakebeat-*', 'auditbeat-*,*beat*,siem-read*,.kibana*,fakebeat-*'];
|
||||
|
||||
describe('Timeline scope', { tags: '@brokenInServerless' }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Timeline scope', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
cy.clearLocalStorage();
|
||||
login();
|
||||
|
|
|
@ -24,6 +24,7 @@ import {
|
|||
UNSELECTED_ALERT_TAG,
|
||||
} from '../../screens/alerts';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Alert tagging', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
|
|
|
@ -24,6 +24,7 @@ import {
|
|||
} from '../../screens/search_bar';
|
||||
import { TOASTER } from '../../screens/alerts_detection_rules';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe(
|
||||
'Histogram legend hover actions',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
|
|
|
@ -29,9 +29,10 @@ const waitForPageTitleToBeShown = () => {
|
|||
cy.get(PAGE_TITLE).should('be.visible');
|
||||
};
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539 Does it need to run in Serverless?
|
||||
describe(
|
||||
'Detections > Need Admin Callouts indicating an admin is needed to migrate the alert data set',
|
||||
{ tags: '@ess' },
|
||||
{ tags: ['@ess', '@skipInServerless'] },
|
||||
() => {
|
||||
before(() => {
|
||||
// First, we have to open the app on behalf of a privileged user in order to initialize it.
|
||||
|
|
|
@ -27,6 +27,7 @@ import { openJsonView, openThreatIndicatorDetails } from '../../tasks/alerts_det
|
|||
import { ruleDetailsUrl } from '../../urls/navigation';
|
||||
import { addsFieldsToTimeline } from '../../tasks/rule_details';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('CTI Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
|
@ -50,6 +51,7 @@ describe('CTI Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'
|
|||
);
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// Skipped: https://github.com/elastic/kibana/issues/162818
|
||||
it.skip('Displays enrichment matched.* fields on the timeline', () => {
|
||||
const expectedFields = {
|
||||
|
|
|
@ -30,6 +30,7 @@ import { login, visit } from '../../tasks/login';
|
|||
|
||||
import { ALERTS_URL } from '../../urls/navigation';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Enrichment', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
|
|
|
@ -41,7 +41,8 @@ const waitForPageTitleToBeShown = () => {
|
|||
cy.get(PAGE_TITLE).should('be.visible');
|
||||
};
|
||||
|
||||
describe('Detections > Callouts', { tags: '@ess' }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Detections > Callouts', { tags: ['@ess', '@skipInServerless'] }, () => {
|
||||
before(() => {
|
||||
// First, we have to open the app on behalf of a privileged user in order to initialize it.
|
||||
// Otherwise the app will be disabled and show a "welcome"-like page.
|
||||
|
|
|
@ -14,6 +14,7 @@ import { TIMELINE_QUERY, TIMELINE_VIEW_IN_ANALYZER } from '../../screens/timelin
|
|||
import { selectAlertsHistogram } from '../../tasks/alerts';
|
||||
import { createTimeline } from '../../tasks/timelines';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe(
|
||||
'Ransomware Detection Alerts',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
|
|
|
@ -15,6 +15,7 @@ import { selectAlertsHistogram } from '../../tasks/alerts';
|
|||
import { createTimeline } from '../../tasks/timelines';
|
||||
import { cleanKibana } from '../../tasks/common';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe(
|
||||
'Ransomware Prevention Alerts',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
|
|
|
@ -55,9 +55,11 @@ const loadPageAsReadOnlyUser = (url: string) => {
|
|||
waitForPageWithoutDateRange(url, ROLES.reader);
|
||||
};
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/164451 We should find a way to make this spec work in Serverless
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe(
|
||||
'Detection rules, Prebuilt Rules Installation and Update - Authorization/RBAC',
|
||||
{ tags: '@ess' },
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
|
|
|
@ -22,9 +22,10 @@ import {
|
|||
ruleUpdatesTabClick,
|
||||
} from '../../../tasks/prebuilt_rules';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe(
|
||||
'Detection rules, Prebuilt Rules Installation and Update - Error handling',
|
||||
{ tags: '@ess' },
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
|
|
|
@ -39,9 +39,10 @@ import {
|
|||
ruleUpdatesTabClick,
|
||||
} from '../../../tasks/prebuilt_rules';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe(
|
||||
'Detection rules, Prebuilt Rules Installation and Update workflow',
|
||||
{ tags: ['@ess', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
|
|
|
@ -50,7 +50,8 @@ const rules = Array.from(Array(5)).map((_, i) => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Prebuilt rules', { tags: ['@ess', '@serverless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe('Prebuilt rules', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
|
|
@ -29,9 +29,10 @@ const RULE_1 = createRuleAssetSavedObject({
|
|||
rule_id: 'rule_1',
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe(
|
||||
'Detection rules, Prebuilt Rules Installation and Update Notifications',
|
||||
{ tags: ['@ess', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
|
|
|
@ -27,9 +27,10 @@ import { login, visit } from '../../../tasks/login';
|
|||
|
||||
import { RULE_CREATION } from '../../../urls/navigation';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe(
|
||||
'Rule actions during detection rule creation',
|
||||
{ tags: ['@ess', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
const indexConnector = getIndexConnector();
|
||||
|
||||
|
|
|
@ -115,7 +115,8 @@ import {
|
|||
import { enablesRule, getDetails, waitForTheRuleToBeExecuted } from '../../../tasks/rule_details';
|
||||
import { ruleDetailsUrl, ruleEditUrl, RULE_CREATION } from '../../../urls/navigation';
|
||||
|
||||
describe('Custom query rules', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Custom query rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
deleteAlertsAndRules();
|
||||
});
|
||||
|
|
|
@ -67,7 +67,8 @@ import { getDetails, waitForTheRuleToBeExecuted } from '../../../tasks/rule_deta
|
|||
|
||||
import { RULE_CREATION } from '../../../urls/navigation';
|
||||
|
||||
describe('Custom query rules', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Custom query rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
describe('Custom detection rules creation with data views', () => {
|
||||
const rule = getDataViewRule();
|
||||
const expectedUrls = rule.references?.join('');
|
||||
|
|
|
@ -50,7 +50,8 @@ const savedQueryName = 'custom saved query';
|
|||
const savedQueryQuery = 'process.name: test';
|
||||
const savedQueryFilterKey = 'testAgent.value';
|
||||
|
||||
describe('Custom saved_query rules', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Saved query rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
|
|
@ -56,7 +56,8 @@ import { login, visit } from '../../../tasks/login';
|
|||
|
||||
import { RULE_CREATION } from '../../../urls/navigation';
|
||||
|
||||
describe('EQL rules', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('EQL rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
|
|
@ -116,7 +116,8 @@ import {
|
|||
|
||||
const DEFAULT_THREAT_MATCH_QUERY = '@timestamp >= "now-30d/d"';
|
||||
|
||||
describe('indicator match', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('indicator match', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
describe('Detection rules, Indicator Match', () => {
|
||||
const expectedUrls = getNewThreatIndicatorRule().references?.join('');
|
||||
const expectedFalsePositives = getNewThreatIndicatorRule().false_positives?.join('');
|
||||
|
|
|
@ -53,7 +53,8 @@ import { login, visitWithoutDateRange } from '../../../tasks/login';
|
|||
|
||||
import { RULE_CREATION } from '../../../urls/navigation';
|
||||
|
||||
describe('Detection rules, machine learning', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Machine Learning rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
const expectedUrls = (getMachineLearningRule().references ?? []).join('');
|
||||
const expectedFalsePositives = (getMachineLearningRule().false_positives ?? []).join('');
|
||||
const expectedTags = (getMachineLearningRule().tags ?? []).join('');
|
||||
|
|
|
@ -58,7 +58,8 @@ import { login, visit } from '../../../tasks/login';
|
|||
|
||||
import { RULE_CREATION } from '../../../urls/navigation';
|
||||
|
||||
describe('New Terms rules', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('New Terms rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
login();
|
||||
|
|
|
@ -61,7 +61,8 @@ import { getDetails, waitForTheRuleToBeExecuted } from '../../../tasks/rule_deta
|
|||
|
||||
import { RULE_CREATION } from '../../../urls/navigation';
|
||||
|
||||
describe('Detection rules, override', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Rules override', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
const rule = getNewOverrideRule();
|
||||
const expectedUrls = rule.references?.join('');
|
||||
const expectedFalsePositives = rule.false_positives?.join('');
|
||||
|
|
|
@ -58,7 +58,8 @@ import { login, visitWithoutDateRange } from '../../../tasks/login';
|
|||
|
||||
import { RULE_CREATION } from '../../../urls/navigation';
|
||||
|
||||
describe('Detection rules, threshold', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Threshold rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
const rule = getNewThresholdRule();
|
||||
const expectedUrls = rule.references?.join('');
|
||||
const expectedFalsePositives = rule.false_positives?.join('');
|
||||
|
|
|
@ -24,7 +24,9 @@ import {
|
|||
} from '../../../../tasks/common/callouts';
|
||||
import { login, visitSecurityDetectionRulesPage } from '../../../../tasks/login';
|
||||
|
||||
describe('All rules - read only', { tags: '@ess' }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/164451 We should find a way to make this spec work in Serverless
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe('All rules - read only', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
createRule(getNewRule({ rule_id: '1', enabled: false }));
|
||||
|
|
|
@ -12,47 +12,52 @@ import { cleanKibana } from '../../../../tasks/common';
|
|||
import { login, visit } from '../../../../tasks/login';
|
||||
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation';
|
||||
|
||||
describe('Maintenance window callout on Rule Management page', { tags: ['@ess'] }, () => {
|
||||
let maintenanceWindowId = '';
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe(
|
||||
'Maintenance window callout on Rule Management page',
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
let maintenanceWindowId = '';
|
||||
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
login();
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
login();
|
||||
|
||||
const body: AsApiContract<MaintenanceWindowCreateBody> = {
|
||||
title: 'My maintenance window',
|
||||
duration: 60000, // 1 minute
|
||||
r_rule: {
|
||||
dtstart: new Date().toISOString(),
|
||||
tzid: 'Europe/Amsterdam',
|
||||
freq: 0,
|
||||
count: 1,
|
||||
},
|
||||
};
|
||||
const body: AsApiContract<MaintenanceWindowCreateBody> = {
|
||||
title: 'My maintenance window',
|
||||
duration: 60000, // 1 minute
|
||||
r_rule: {
|
||||
dtstart: new Date().toISOString(),
|
||||
tzid: 'Europe/Amsterdam',
|
||||
freq: 0,
|
||||
count: 1,
|
||||
},
|
||||
};
|
||||
|
||||
// Create a test maintenance window
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
|
||||
headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' },
|
||||
body,
|
||||
}).then((response) => {
|
||||
maintenanceWindowId = response.body.id;
|
||||
// Create a test maintenance window
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH,
|
||||
headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' },
|
||||
body,
|
||||
}).then((response) => {
|
||||
maintenanceWindowId = response.body.id;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
// Delete a test maintenance window
|
||||
cy.request({
|
||||
method: 'DELETE',
|
||||
url: `${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/${maintenanceWindowId}`,
|
||||
headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' },
|
||||
after(() => {
|
||||
// Delete a test maintenance window
|
||||
cy.request({
|
||||
method: 'DELETE',
|
||||
url: `${INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH}/${maintenanceWindowId}`,
|
||||
headers: { 'kbn-xsrf': 'cypress-creds', 'x-elastic-internal-origin': 'security-solution' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Displays the callout when there are running maintenance windows', () => {
|
||||
visit(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
it('Displays the callout when there are running maintenance windows', () => {
|
||||
visit(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
|
||||
cy.contains('Maintenance window is running');
|
||||
});
|
||||
});
|
||||
cy.contains('Maintenance window is running');
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -47,7 +47,8 @@ import {
|
|||
import { ruleDetailsUrl } from '../../../../urls/navigation';
|
||||
import { enablesRule, waitForPageToBeLoaded } from '../../../../tasks/rule_details';
|
||||
|
||||
describe('Related integrations', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe('Related integrations', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
const DATA_STREAM_NAME = 'logs-related-integrations-test';
|
||||
const PREBUILT_RULE_NAME = 'Prebuilt rule with related integrations';
|
||||
const RULE_RELATED_INTEGRATIONS: IntegrationDefinition[] = [
|
||||
|
@ -189,6 +190,7 @@ describe('Related integrations', { tags: ['@ess', '@brokenInServerless'] }, () =
|
|||
});
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
// Flaky in serverless tests
|
||||
// @brokenInServerless tag is not working so a skip was needed
|
||||
describe.skip('rule details', { tags: ['@brokenInServerless'] }, () => {
|
||||
|
|
|
@ -52,10 +52,11 @@ const EXPIRED_EXCEPTION_ITEM_NAME = 'Sample exception item';
|
|||
|
||||
const NON_EXPIRED_EXCEPTION_ITEM_NAME = 'Sample exception item with future expiration';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
// Flaky on serverless
|
||||
describe(
|
||||
'Detection rules, bulk duplicate',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -73,9 +73,10 @@ const ruleNameToAssert = 'Custom rule name with actions';
|
|||
const expectedExistingSlackMessage = 'Existing slack action';
|
||||
const expectedSlackMessage = 'Slack action test message';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe(
|
||||
'Detection rules, bulk edit of rule actions',
|
||||
{ tags: ['@ess', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
cleanKibana();
|
||||
|
|
|
@ -52,9 +52,10 @@ const DATA_VIEW_ID = 'auditbeat';
|
|||
|
||||
const expectedIndexPatterns = ['index-1-*', 'index-2-*'];
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe(
|
||||
'Bulk editing index patterns of rules with a data view only',
|
||||
{ tags: ['@ess', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
const TESTED_CUSTOM_QUERY_RULE_DATA = getNewRule({
|
||||
index: undefined,
|
||||
|
|
|
@ -55,7 +55,8 @@ const prebuiltRules = Array.from(Array(7)).map((_, i) => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Export rules', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe('Export rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
const downloadsFolder = Cypress.config('downloadsFolder');
|
||||
|
||||
before(() => {
|
||||
|
|
|
@ -17,7 +17,8 @@ import { login, visitWithoutDateRange } from '../../../../../tasks/login';
|
|||
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../../urls/navigation';
|
||||
const RULES_TO_IMPORT_FILENAME = 'cypress/fixtures/7_16_rules.ndjson';
|
||||
|
||||
describe('Import rules', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe('Import rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
|
|
@ -47,8 +47,9 @@ import { TOOLTIP } from '../../../../../screens/common';
|
|||
|
||||
const RULES_TO_IMPORT_FILENAME = 'cypress/fixtures/7_16_rules.ndjson';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
// Flaky in serverless tests
|
||||
describe('rule snoozing', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
describe('rule snoozing', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
|
|
@ -33,86 +33,91 @@ import { getNewRule } from '../../../../objects/rule';
|
|||
const DEFAULT_RULE_REFRESH_INTERVAL_VALUE = 60000;
|
||||
const NUM_OF_TEST_RULES = 6;
|
||||
|
||||
describe('Rules table: auto-refresh', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
login();
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe(
|
||||
'Rules table: auto-refresh',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
login();
|
||||
|
||||
for (let i = 1; i <= NUM_OF_TEST_RULES; ++i) {
|
||||
createRule(getNewRule({ name: `Test rule ${i}`, rule_id: `${i}`, enabled: false }));
|
||||
}
|
||||
});
|
||||
for (let i = 1; i <= NUM_OF_TEST_RULES; ++i) {
|
||||
createRule(getNewRule({ name: `Test rule ${i}`, rule_id: `${i}`, enabled: false }));
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
it('Auto refreshes rules', () => {
|
||||
mockGlobalClock();
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
it('Auto refreshes rules', () => {
|
||||
mockGlobalClock();
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
|
||||
expectNumberOfRules(RULES_MANAGEMENT_TABLE, NUM_OF_TEST_RULES);
|
||||
expectNumberOfRules(RULES_MANAGEMENT_TABLE, NUM_OF_TEST_RULES);
|
||||
|
||||
// // mock 1 minute passing to make sure refresh is conducted
|
||||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should('not.exist');
|
||||
cy.tick(DEFAULT_RULE_REFRESH_INTERVAL_VALUE);
|
||||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should('be.visible');
|
||||
// // mock 1 minute passing to make sure refresh is conducted
|
||||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should('not.exist');
|
||||
cy.tick(DEFAULT_RULE_REFRESH_INTERVAL_VALUE);
|
||||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should('be.visible');
|
||||
|
||||
cy.contains(REFRESH_RULES_STATUS, 'Updated now');
|
||||
});
|
||||
cy.contains(REFRESH_RULES_STATUS, 'Updated now');
|
||||
});
|
||||
|
||||
it('should prevent table from rules refetch if any rule selected', () => {
|
||||
mockGlobalClock();
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
it('should prevent table from rules refetch if any rule selected', () => {
|
||||
mockGlobalClock();
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
|
||||
expectNumberOfRules(RULES_MANAGEMENT_TABLE, NUM_OF_TEST_RULES);
|
||||
expectNumberOfRules(RULES_MANAGEMENT_TABLE, NUM_OF_TEST_RULES);
|
||||
|
||||
selectRulesByName(['Test rule 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');
|
||||
cy.tick(DEFAULT_RULE_REFRESH_INTERVAL_VALUE);
|
||||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should('not.exist');
|
||||
// mock 1 minute passing to make sure refresh is not conducted
|
||||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should('not.exist');
|
||||
cy.tick(DEFAULT_RULE_REFRESH_INTERVAL_VALUE);
|
||||
cy.get(RULES_TABLE_AUTOREFRESH_INDICATOR).should('not.exist');
|
||||
|
||||
// ensure rule is still selected
|
||||
getRuleRow('Test rule 1').find(EUI_CHECKBOX).should('be.checked');
|
||||
// ensure rule is still selected
|
||||
getRuleRow('Test rule 1').find(EUI_CHECKBOX).should('be.checked');
|
||||
|
||||
cy.get(REFRESH_RULES_STATUS).should('have.not.text', 'Updated now');
|
||||
});
|
||||
cy.get(REFRESH_RULES_STATUS).should('have.not.text', 'Updated now');
|
||||
});
|
||||
|
||||
it('should disable auto refresh when any rule selected and enable it after rules unselected', () => {
|
||||
visit(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
it('should disable auto refresh when any rule selected and enable it after rules unselected', () => {
|
||||
visit(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
|
||||
expectNumberOfRules(RULES_MANAGEMENT_TABLE, NUM_OF_TEST_RULES);
|
||||
expectNumberOfRules(RULES_MANAGEMENT_TABLE, NUM_OF_TEST_RULES);
|
||||
|
||||
// check refresh settings if it's enabled before selecting
|
||||
expectAutoRefreshIsEnabled();
|
||||
// check refresh settings if it's enabled before selecting
|
||||
expectAutoRefreshIsEnabled();
|
||||
|
||||
selectAllRules();
|
||||
selectAllRules();
|
||||
|
||||
// auto refresh should be deactivated (which means disabled without an ability to enable it) after rules selected
|
||||
expectAutoRefreshIsDeactivated();
|
||||
// auto refresh should be deactivated (which means disabled without an ability to enable it) after rules selected
|
||||
expectAutoRefreshIsDeactivated();
|
||||
|
||||
clearAllRuleSelection();
|
||||
clearAllRuleSelection();
|
||||
|
||||
// after all rules unselected, auto refresh should be reset to its previous state
|
||||
expectAutoRefreshIsEnabled();
|
||||
});
|
||||
// after all rules unselected, auto refresh should be reset to its previous state
|
||||
expectAutoRefreshIsEnabled();
|
||||
});
|
||||
|
||||
it('should not enable auto refresh after rules were unselected if auto refresh was disabled', () => {
|
||||
visit(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
it('should not enable auto refresh after rules were unselected if auto refresh was disabled', () => {
|
||||
visit(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
|
||||
expectNumberOfRules(RULES_MANAGEMENT_TABLE, NUM_OF_TEST_RULES);
|
||||
expectNumberOfRules(RULES_MANAGEMENT_TABLE, NUM_OF_TEST_RULES);
|
||||
|
||||
disableAutoRefresh();
|
||||
disableAutoRefresh();
|
||||
|
||||
selectAllRules();
|
||||
selectAllRules();
|
||||
|
||||
expectAutoRefreshIsDeactivated();
|
||||
expectAutoRefreshIsDeactivated();
|
||||
|
||||
clearAllRuleSelection();
|
||||
clearAllRuleSelection();
|
||||
|
||||
// after all rules unselected, auto refresh should still be disabled
|
||||
expectAutoRefreshIsDisabled();
|
||||
});
|
||||
});
|
||||
// after all rules unselected, auto refresh should still be disabled
|
||||
expectAutoRefreshIsDisabled();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -28,8 +28,9 @@ import {
|
|||
import { disableAutoRefresh } from '../../../../tasks/alerts_detection_rules';
|
||||
import { getNewRule } from '../../../../objects/rule';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
// Flaky in serverless tests
|
||||
describe('Rules table: filtering', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
describe('Rules table: filtering', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
@ -42,6 +43,7 @@ describe('Rules table: filtering', { tags: ['@ess', '@serverless', '@brokenInSer
|
|||
cy.task('esArchiverResetKibana');
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe.skip('Last response filter', () => {
|
||||
// Flaky in serverless tests
|
||||
// @brokenInServerless tag is not working so a skip was needed
|
||||
|
|
|
@ -12,8 +12,9 @@ import { cleanKibana, deleteAlertsAndRules } from '../../../../tasks/common';
|
|||
import { login, visitWithoutDateRange } from '../../../../tasks/login';
|
||||
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
// Flaky in serverless tests
|
||||
describe('Rules table: links', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
describe('Rules table: links', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
|
|
@ -99,124 +99,248 @@ function expectDefaultRulesTableState(): void {
|
|||
expectTablePage(1);
|
||||
}
|
||||
|
||||
describe('Rules table: persistent state', { tags: ['@ess', '@serverless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
createTestRules();
|
||||
});
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe(
|
||||
'Rules table: persistent state',
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
createTestRules();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
resetRulesTableState();
|
||||
});
|
||||
beforeEach(() => {
|
||||
login();
|
||||
resetRulesTableState();
|
||||
});
|
||||
|
||||
// Flaky on serverless
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165740
|
||||
describe(
|
||||
'while on a happy path',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
it('activates management tab by default', () => {
|
||||
visit(SECURITY_DETECTIONS_RULES_URL);
|
||||
// Flaky on serverless
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165740
|
||||
describe(
|
||||
'while on a happy path',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
it('activates management tab by default', () => {
|
||||
visit(SECURITY_DETECTIONS_RULES_URL);
|
||||
|
||||
expectRulesManagementTab();
|
||||
});
|
||||
|
||||
it('leads to displaying a rule according to the specified filters', () => {
|
||||
visitRulesTableWithState({
|
||||
searchTerm: 'rule',
|
||||
tags: ['tag-b'],
|
||||
source: 'custom',
|
||||
enabled: false,
|
||||
field: 'name',
|
||||
order: 'asc',
|
||||
perPage: 5,
|
||||
page: 2,
|
||||
expectRulesManagementTab();
|
||||
});
|
||||
|
||||
expectManagementTableRules(['rule 6']);
|
||||
});
|
||||
it('leads to displaying a rule according to the specified filters', () => {
|
||||
visitRulesTableWithState({
|
||||
searchTerm: 'rule',
|
||||
tags: ['tag-b'],
|
||||
source: 'custom',
|
||||
enabled: false,
|
||||
field: 'name',
|
||||
order: 'asc',
|
||||
perPage: 5,
|
||||
page: 2,
|
||||
});
|
||||
|
||||
it('loads from the url', () => {
|
||||
visitRulesTableWithState({
|
||||
searchTerm: 'rule',
|
||||
tags: ['tag-b'],
|
||||
source: 'custom',
|
||||
enabled: false,
|
||||
field: 'name',
|
||||
order: 'asc',
|
||||
perPage: 5,
|
||||
page: 2,
|
||||
expectManagementTableRules(['rule 6']);
|
||||
});
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectFilterSearchTerm('rule');
|
||||
expectFilterByTags(['tag-b']);
|
||||
expectFilterByCustomRules();
|
||||
expectFilterByDisabledRules();
|
||||
expectTableSorting('Rule', 'asc');
|
||||
expectRowsPerPage(5);
|
||||
expectTablePage(2);
|
||||
});
|
||||
it('loads from the url', () => {
|
||||
visitRulesTableWithState({
|
||||
searchTerm: 'rule',
|
||||
tags: ['tag-b'],
|
||||
source: 'custom',
|
||||
enabled: false,
|
||||
field: 'name',
|
||||
order: 'asc',
|
||||
perPage: 5,
|
||||
page: 2,
|
||||
});
|
||||
|
||||
it('loads from the session storage', () => {
|
||||
setStorageState({
|
||||
searchTerm: 'test',
|
||||
tags: ['tag-a'],
|
||||
source: 'prebuilt',
|
||||
enabled: true,
|
||||
field: 'severity',
|
||||
order: 'desc',
|
||||
perPage: 10,
|
||||
expectRulesManagementTab();
|
||||
expectFilterSearchTerm('rule');
|
||||
expectFilterByTags(['tag-b']);
|
||||
expectFilterByCustomRules();
|
||||
expectFilterByDisabledRules();
|
||||
expectTableSorting('Rule', 'asc');
|
||||
expectRowsPerPage(5);
|
||||
expectTablePage(2);
|
||||
});
|
||||
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
it('loads from the session storage', () => {
|
||||
setStorageState({
|
||||
searchTerm: 'test',
|
||||
tags: ['tag-a'],
|
||||
source: 'prebuilt',
|
||||
enabled: true,
|
||||
field: 'severity',
|
||||
order: 'desc',
|
||||
perPage: 10,
|
||||
});
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectFilterSearchTerm('test');
|
||||
expectFilterByTags(['tag-a']);
|
||||
expectFilterByPrebuiltRules();
|
||||
expectFilterByEnabledRules();
|
||||
expectTableSorting('Severity', 'desc');
|
||||
});
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
|
||||
it('prefers url state over storage state', () => {
|
||||
setStorageState({
|
||||
searchTerm: 'test',
|
||||
tags: ['tag-c'],
|
||||
source: 'prebuilt',
|
||||
enabled: true,
|
||||
field: 'severity',
|
||||
order: 'desc',
|
||||
perPage: 10,
|
||||
expectRulesManagementTab();
|
||||
expectFilterSearchTerm('test');
|
||||
expectFilterByTags(['tag-a']);
|
||||
expectFilterByPrebuiltRules();
|
||||
expectFilterByEnabledRules();
|
||||
expectTableSorting('Severity', 'desc');
|
||||
});
|
||||
|
||||
visitRulesTableWithState({
|
||||
searchTerm: 'rule',
|
||||
tags: ['tag-b'],
|
||||
source: 'custom',
|
||||
enabled: false,
|
||||
field: 'name',
|
||||
order: 'asc',
|
||||
perPage: 5,
|
||||
page: 2,
|
||||
it('prefers url state over storage state', () => {
|
||||
setStorageState({
|
||||
searchTerm: 'test',
|
||||
tags: ['tag-c'],
|
||||
source: 'prebuilt',
|
||||
enabled: true,
|
||||
field: 'severity',
|
||||
order: 'desc',
|
||||
perPage: 10,
|
||||
});
|
||||
|
||||
visitRulesTableWithState({
|
||||
searchTerm: 'rule',
|
||||
tags: ['tag-b'],
|
||||
source: 'custom',
|
||||
enabled: false,
|
||||
field: 'name',
|
||||
order: 'asc',
|
||||
perPage: 5,
|
||||
page: 2,
|
||||
});
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(2);
|
||||
});
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(2);
|
||||
describe('and on the rules management tab', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
});
|
||||
|
||||
it('persists after reloading the page', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
cy.reload();
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(2);
|
||||
});
|
||||
|
||||
it('persists after navigating back from a rule details page', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
goToRuleDetailsOf('rule 6');
|
||||
cy.go('back');
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(2);
|
||||
});
|
||||
|
||||
it('persists after navigating to another page inside Security Solution', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
visit(DASHBOARDS_URL);
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(1);
|
||||
});
|
||||
|
||||
it('persists after navigating to another page outside Security Solution', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
visit(KIBANA_HOME);
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and on the rules monitoring tab', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(SECURITY_DETECTIONS_RULES_MONITORING_URL);
|
||||
});
|
||||
|
||||
it('persists the selected tab', () => {
|
||||
changeRulesTableState();
|
||||
|
||||
cy.reload();
|
||||
|
||||
expectRulesMonitoringTab();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
describe('upon state format upgrade', async () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('and having state in the url', () => {
|
||||
it('ignores unsupported state key', () => {
|
||||
visitRulesTableWithState({
|
||||
someKey: 10,
|
||||
searchTerm: 'rule',
|
||||
tags: ['tag-b'],
|
||||
source: 'custom',
|
||||
enabled: false,
|
||||
field: 'name',
|
||||
order: 'asc',
|
||||
perPage: 5,
|
||||
page: 2,
|
||||
});
|
||||
|
||||
expectRulesTableState();
|
||||
expectTablePage(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and having state in the session storage', () => {
|
||||
it('ignores unsupported state key', () => {
|
||||
setStorageState({
|
||||
someKey: 10,
|
||||
searchTerm: 'rule',
|
||||
tags: ['tag-b'],
|
||||
source: 'custom',
|
||||
enabled: false,
|
||||
field: 'name',
|
||||
order: 'asc',
|
||||
perPage: 5,
|
||||
});
|
||||
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
|
||||
expectRulesTableState();
|
||||
expectTablePage(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when persisted state is partially unavailable', () => {
|
||||
describe('and on the rules management tab', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
});
|
||||
|
||||
it('persists after reloading the page', () => {
|
||||
it('persists after clearing the session storage', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
cy.window().then((win) => {
|
||||
win.sessionStorage.clear();
|
||||
});
|
||||
cy.reload();
|
||||
|
||||
expectRulesManagementTab();
|
||||
|
@ -224,35 +348,10 @@ describe('Rules table: persistent state', { tags: ['@ess', '@serverless'] }, ()
|
|||
expectTablePage(2);
|
||||
});
|
||||
|
||||
it('persists after navigating back from a rule details page', () => {
|
||||
it('persists after clearing the url state', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
goToRuleDetailsOf('rule 6');
|
||||
cy.go('back');
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(2);
|
||||
});
|
||||
|
||||
it('persists after navigating to another page inside Security Solution', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
visit(DASHBOARDS_URL);
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(1);
|
||||
});
|
||||
|
||||
it('persists after navigating to another page outside Security Solution', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
visit(KIBANA_HOME);
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
|
||||
expectRulesManagementTab();
|
||||
|
@ -260,149 +359,55 @@ describe('Rules table: persistent state', { tags: ['@ess', '@serverless'] }, ()
|
|||
expectTablePage(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and on the rules monitoring tab', () => {
|
||||
describe('when corrupted', () => {
|
||||
describe('and on the rules management tab', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(SECURITY_DETECTIONS_RULES_MONITORING_URL);
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
});
|
||||
|
||||
it('persists the selected tab', () => {
|
||||
it('persists after corrupting the session storage data', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
cy.reload();
|
||||
cy.window().then((win) => {
|
||||
win.sessionStorage.setItem('securitySolution.rulesTable', '!invalid');
|
||||
cy.reload();
|
||||
|
||||
expectRulesMonitoringTab();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
describe('upon state format upgrade', async () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('and having state in the url', () => {
|
||||
it('ignores unsupported state key', () => {
|
||||
visitRulesTableWithState({
|
||||
someKey: 10,
|
||||
searchTerm: 'rule',
|
||||
tags: ['tag-b'],
|
||||
source: 'custom',
|
||||
enabled: false,
|
||||
field: 'name',
|
||||
order: 'asc',
|
||||
perPage: 5,
|
||||
page: 2,
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(2);
|
||||
});
|
||||
});
|
||||
|
||||
expectRulesTableState();
|
||||
expectTablePage(2);
|
||||
});
|
||||
});
|
||||
it('persists after corrupting the url param data', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
describe('and having state in the session storage', () => {
|
||||
it('ignores unsupported state key', () => {
|
||||
setStorageState({
|
||||
someKey: 10,
|
||||
searchTerm: 'rule',
|
||||
tags: ['tag-b'],
|
||||
source: 'custom',
|
||||
enabled: false,
|
||||
field: 'name',
|
||||
order: 'asc',
|
||||
perPage: 5,
|
||||
});
|
||||
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
|
||||
expectRulesTableState();
|
||||
expectTablePage(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when persisted state is partially unavailable', () => {
|
||||
describe('and on the rules management tab', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
});
|
||||
|
||||
it('persists after clearing the session storage', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
cy.window().then((win) => {
|
||||
win.sessionStorage.clear();
|
||||
});
|
||||
cy.reload();
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(2);
|
||||
});
|
||||
|
||||
it('persists after clearing the url state', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when corrupted', () => {
|
||||
describe('and on the rules management tab', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL);
|
||||
});
|
||||
|
||||
it('persists after corrupting the session storage data', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
cy.window().then((win) => {
|
||||
win.sessionStorage.setItem('securitySolution.rulesTable', '!invalid');
|
||||
cy.reload();
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL, { qs: { rulesTable: '(!invalid)' } });
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('persists after corrupting the url param data', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL, { qs: { rulesTable: '(!invalid)' } });
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectRulesTableState();
|
||||
expectTablePage(1);
|
||||
});
|
||||
|
||||
it('DOES NOT persist after corrupting the session storage and url param data', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL, {
|
||||
qs: { rulesTable: '(!invalid)' },
|
||||
onBeforeLoad: (win) => {
|
||||
win.sessionStorage.setItem('securitySolution.rulesTable', '!invalid');
|
||||
},
|
||||
expectTablePage(1);
|
||||
});
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectDefaultRulesTableState();
|
||||
it('DOES NOT persist after corrupting the session storage and url param data', () => {
|
||||
changeRulesTableState();
|
||||
goToTablePage(2);
|
||||
|
||||
visit(SECURITY_DETECTIONS_RULES_MANAGEMENT_URL, {
|
||||
qs: { rulesTable: '(!invalid)' },
|
||||
onBeforeLoad: (win) => {
|
||||
win.sessionStorage.setItem('securitySolution.rulesTable', '!invalid');
|
||||
},
|
||||
});
|
||||
|
||||
expectRulesManagementTab();
|
||||
expectDefaultRulesTableState();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -33,69 +33,74 @@ const RULE_2 = createRuleAssetSavedObject({
|
|||
rule_id: 'rule_2',
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165643
|
||||
describe.skip('Rules table: selection', { tags: ['@ess', '@serverless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
/* Create and install two mock rules */
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2] });
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
waitForPrebuiltDetectionRulesToBeLoaded();
|
||||
});
|
||||
|
||||
it('should correctly update the selection label when rules are individually selected and unselected', () => {
|
||||
waitForPrebuiltDetectionRulesToBeLoaded();
|
||||
|
||||
selectRulesByName(['Test rule 1', 'Test rule 2']);
|
||||
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', '2');
|
||||
|
||||
unselectRulesByName(['Test rule 1', 'Test rule 2']);
|
||||
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', '0');
|
||||
});
|
||||
|
||||
it('should correctly update the selection label when rules are bulk selected and then bulk un-selected', () => {
|
||||
waitForPrebuiltDetectionRulesToBeLoaded();
|
||||
|
||||
cy.get(SELECT_ALL_RULES_BTN).click();
|
||||
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', availablePrebuiltRulesCount);
|
||||
describe.skip(
|
||||
'Rules table: selection',
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
});
|
||||
|
||||
// Un-select all rules via the Bulk Selection button from the Utility bar
|
||||
cy.get(SELECT_ALL_RULES_BTN).click();
|
||||
|
||||
// Current selection should be 0 rules
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', '0');
|
||||
// Bulk selection button should be back to displaying all rules
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
cy.get(SELECT_ALL_RULES_BTN).should('contain.text', availablePrebuiltRulesCount);
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly update the selection label when rules are bulk selected and then unselected via the table select all checkbox', () => {
|
||||
waitForPrebuiltDetectionRulesToBeLoaded();
|
||||
|
||||
cy.get(SELECT_ALL_RULES_BTN).click();
|
||||
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', availablePrebuiltRulesCount);
|
||||
beforeEach(() => {
|
||||
login();
|
||||
/* Create and install two mock rules */
|
||||
createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2] });
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
|
||||
waitForPrebuiltDetectionRulesToBeLoaded();
|
||||
});
|
||||
|
||||
// Un-select all rules via the Un-select All checkbox from the table
|
||||
cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click();
|
||||
it('should correctly update the selection label when rules are individually selected and unselected', () => {
|
||||
waitForPrebuiltDetectionRulesToBeLoaded();
|
||||
|
||||
// Current selection should be 0 rules
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', '0');
|
||||
// Bulk selection button should be back to displaying all rules
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
cy.get(SELECT_ALL_RULES_BTN).should('contain.text', availablePrebuiltRulesCount);
|
||||
selectRulesByName(['Test rule 1', 'Test rule 2']);
|
||||
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', '2');
|
||||
|
||||
unselectRulesByName(['Test rule 1', 'Test rule 2']);
|
||||
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', '0');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly update the selection label when rules are bulk selected and then bulk un-selected', () => {
|
||||
waitForPrebuiltDetectionRulesToBeLoaded();
|
||||
|
||||
cy.get(SELECT_ALL_RULES_BTN).click();
|
||||
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', availablePrebuiltRulesCount);
|
||||
});
|
||||
|
||||
// Un-select all rules via the Bulk Selection button from the Utility bar
|
||||
cy.get(SELECT_ALL_RULES_BTN).click();
|
||||
|
||||
// Current selection should be 0 rules
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', '0');
|
||||
// Bulk selection button should be back to displaying all rules
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
cy.get(SELECT_ALL_RULES_BTN).should('contain.text', availablePrebuiltRulesCount);
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly update the selection label when rules are bulk selected and then unselected via the table select all checkbox', () => {
|
||||
waitForPrebuiltDetectionRulesToBeLoaded();
|
||||
|
||||
cy.get(SELECT_ALL_RULES_BTN).click();
|
||||
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', availablePrebuiltRulesCount);
|
||||
});
|
||||
|
||||
// Un-select all rules via the Un-select All checkbox from the table
|
||||
cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click();
|
||||
|
||||
// Current selection should be 0 rules
|
||||
cy.get(SELECTED_RULES_NUMBER_LABEL).should('contain.text', '0');
|
||||
// Bulk selection button should be back to displaying all rules
|
||||
getAvailablePrebuiltRulesCount().then((availablePrebuiltRulesCount) => {
|
||||
cy.get(SELECT_ALL_RULES_BTN).should('contain.text', availablePrebuiltRulesCount);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -36,6 +36,7 @@ import {
|
|||
} from '../../../../tasks/table_pagination';
|
||||
import { TABLE_FIRST_PAGE, TABLE_SECOND_PAGE } from '../../../../screens/table_pagination';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161540
|
||||
describe('Rules table: sorting', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
|
|
|
@ -35,8 +35,10 @@ const TEXT_LIST_FILE_NAME = 'value_list.txt';
|
|||
const IPS_LIST_FILE_NAME = 'ip_list.txt';
|
||||
const CIDRS_LIST_FILE_NAME = 'cidr_list.txt';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165699
|
||||
describe('value lists', () => {
|
||||
describe('value lists', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('management modal', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
|
@ -56,6 +58,7 @@ describe('value lists', () => {
|
|||
closeValueListsModal();
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// Flaky in serverless tests
|
||||
describe('create list types', { tags: ['@brokenInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
|
@ -115,6 +118,7 @@ describe('value lists', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// Flaky in serverless tests
|
||||
describe('delete list types', { tags: ['@brokenInServerless'] }, () => {
|
||||
it('deletes a "keyword" list from an uploaded file', () => {
|
||||
|
@ -162,6 +166,7 @@ describe('value lists', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// Flaky in serverless tests
|
||||
describe('export list types', { tags: ['@brokenInServerless'] }, () => {
|
||||
it('exports a "keyword" list from an uploaded file', () => {
|
||||
|
@ -259,11 +264,17 @@ describe('value lists', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('user with restricted access role', { tags: '@ess' }, () => {
|
||||
it('Does not allow a t1 analyst user to upload a value list', () => {
|
||||
login(ROLES.t1_analyst);
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL, ROLES.t1_analyst);
|
||||
cy.get(VALUE_LISTS_MODAL_ACTIVATOR).should('have.attr', 'disabled');
|
||||
});
|
||||
});
|
||||
// TODO: https://github.com/elastic/kibana/issues/164451 We should find a way to make this spec work in Serverless
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe(
|
||||
'user with restricted access role',
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
it('Does not allow a t1 analyst user to upload a value list', () => {
|
||||
login(ROLES.t1_analyst);
|
||||
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL, ROLES.t1_analyst);
|
||||
cy.get(VALUE_LISTS_MODAL_ACTIVATOR).should('have.attr', 'disabled');
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -39,13 +39,14 @@ import {
|
|||
previewErrorButtonClick,
|
||||
} from '../../tasks/entity_analytics';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe(
|
||||
'Entity analytics management page',
|
||||
{
|
||||
env: {
|
||||
ftrConfig: { enableExperimental: ['riskScoringRoutesEnabled', 'riskScoringPersistence'] },
|
||||
},
|
||||
tags: ['@ess', '@brokenInServerless'],
|
||||
tags: ['@ess', '@serverless', '@brokenInServerless'],
|
||||
},
|
||||
() => {
|
||||
before(() => {
|
||||
|
|
|
@ -36,10 +36,11 @@ import {
|
|||
} from '../../../screens/exceptions';
|
||||
import { goToEndpointExceptionsTab, waitForTheRuleToBeExecuted } from '../../../tasks/rule_details';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// See https://github.com/elastic/kibana/issues/163967
|
||||
describe.skip(
|
||||
'Endpoint Exceptions workflows from Alert',
|
||||
{ tags: ['@ess', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
const ITEM_NAME = 'Sample Exception List Item';
|
||||
const ITEM_NAME_EDIT = 'Sample Exception List Item';
|
||||
|
|
|
@ -37,10 +37,11 @@ import {
|
|||
} from '../../../../screens/exceptions';
|
||||
import { waitForAlertsToPopulate } from '../../../../tasks/create_new_rule';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// See https://github.com/elastic/kibana/issues/163967
|
||||
describe.skip(
|
||||
'Auto populate exception with Alert data',
|
||||
{ tags: ['@ess', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
const ITEM_NAME = 'Sample Exception Item';
|
||||
const ITEM_NAME_EDIT = 'Sample Exception Item Edit';
|
||||
|
|
|
@ -26,8 +26,9 @@ import {
|
|||
submitNewExceptionItem,
|
||||
} from '../../../../tasks/exceptions';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// See https://github.com/elastic/kibana/issues/163967
|
||||
describe('Close matching Alerts ', () => {
|
||||
describe('Close matching Alerts ', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
const ITEM_NAME = 'Sample Exception Item';
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -53,7 +54,8 @@ describe('Close matching Alerts ', () => {
|
|||
cy.task('esArchiverUnload', 'exceptions');
|
||||
});
|
||||
|
||||
it('Should create a Rule exception item from alert actions overflow menu and close all matching alerts', () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
it.skip('Should create a Rule exception item from alert actions overflow menu and close all matching alerts', () => {
|
||||
cy.get(LOADING_INDICATOR).should('not.exist');
|
||||
addExceptionFromFirstAlert();
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ import {
|
|||
} from '../../../tasks/api_calls/exceptions';
|
||||
import { getExceptionList } from '../../../objects/exception';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// Test Skipped until we fix the Flyout rerendering issue
|
||||
// https://github.com/elastic/kibana/issues/154994
|
||||
|
||||
|
@ -64,7 +65,7 @@ import { getExceptionList } from '../../../objects/exception';
|
|||
// to test in enzyme and very small changes can inadvertently add
|
||||
// bugs. As the complexity within the builder grows, these should
|
||||
// ensure the most basic logic holds.
|
||||
describe.skip('Exceptions flyout', { tags: ['@ess', '@serverless'] }, () => {
|
||||
describe.skip('Exceptions flyout', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
before(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
// this is a made-up index that has just the necessary
|
||||
|
|
|
@ -25,12 +25,13 @@ import {
|
|||
import { ruleDetailsUrl } from '../../../urls/navigation';
|
||||
import { deleteAlertsAndRules } from '../../../tasks/common';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165651
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165734
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165652
|
||||
describe(
|
||||
'Add multiple conditions and validate the generated exceptions',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
|
|
|
@ -43,10 +43,11 @@ const goToRulesAndOpenValueListModal = () => {
|
|||
openValueListsModal();
|
||||
};
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// Flaky on serverless
|
||||
describe(
|
||||
'Use Value list in exception entry',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
cleanKibana();
|
||||
|
|
|
@ -46,10 +46,11 @@ import {
|
|||
createEndpointExceptionListItem,
|
||||
} from '../../../tasks/api_calls/exceptions';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165736
|
||||
describe(
|
||||
'Add endpoint exception from rule details',
|
||||
{ tags: ['@ess', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
const ITEM_NAME = 'Sample Exception List Item';
|
||||
const NEW_ITEM_NAME = 'Exception item-EDITED';
|
||||
|
|
|
@ -58,149 +58,227 @@ import {
|
|||
} from '../../../tasks/api_calls/exceptions';
|
||||
import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule';
|
||||
|
||||
describe('Add/edit exception from rule details', { tags: ['@ess', '@brokenInServerless'] }, () => {
|
||||
const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert';
|
||||
const FIELD_DIFFERENT_FROM_EXISTING_ITEM_FIELD = 'agent.name';
|
||||
const ITEM_FIELD = 'unique_value.test';
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe(
|
||||
'Add/edit exception from rule details',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert';
|
||||
const FIELD_DIFFERENT_FROM_EXISTING_ITEM_FIELD = 'agent.name';
|
||||
const ITEM_FIELD = 'unique_value.test';
|
||||
|
||||
before(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
cy.task('esArchiverLoad', { archiveName: 'exceptions' });
|
||||
});
|
||||
before(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
cy.task('esArchiverLoad', { archiveName: 'exceptions' });
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cy.task('esArchiverUnload', 'exceptions');
|
||||
});
|
||||
after(() => {
|
||||
cy.task('esArchiverUnload', 'exceptions');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
deleteAlertsAndRules();
|
||||
|
||||
const exceptionList = getExceptionList();
|
||||
deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type);
|
||||
});
|
||||
|
||||
describe('existing list and items', () => {
|
||||
const exceptionList = getExceptionList();
|
||||
beforeEach(() => {
|
||||
// create rule with exceptions
|
||||
createExceptionList(exceptionList, exceptionList.list_id).then((response) => {
|
||||
createExceptionListItem(exceptionList.list_id, {
|
||||
list_id: exceptionList.list_id,
|
||||
item_id: 'simple_list_item',
|
||||
tags: [],
|
||||
type: 'simple',
|
||||
description: 'Test exception item 2',
|
||||
name: 'Sample Exception List Item 2',
|
||||
namespace_type: 'single',
|
||||
entries: [
|
||||
{
|
||||
field: ITEM_FIELD,
|
||||
operator: 'included',
|
||||
type: 'match_any',
|
||||
value: ['foo'],
|
||||
},
|
||||
],
|
||||
login();
|
||||
deleteAlertsAndRules();
|
||||
|
||||
const exceptionList = getExceptionList();
|
||||
deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type);
|
||||
});
|
||||
|
||||
describe('existing list and items', () => {
|
||||
const exceptionList = getExceptionList();
|
||||
beforeEach(() => {
|
||||
// create rule with exceptions
|
||||
createExceptionList(exceptionList, exceptionList.list_id).then((response) => {
|
||||
createExceptionListItem(exceptionList.list_id, {
|
||||
list_id: exceptionList.list_id,
|
||||
item_id: 'simple_list_item',
|
||||
tags: [],
|
||||
type: 'simple',
|
||||
description: 'Test exception item 2',
|
||||
name: 'Sample Exception List Item 2',
|
||||
namespace_type: 'single',
|
||||
entries: [
|
||||
{
|
||||
field: ITEM_FIELD,
|
||||
operator: 'included',
|
||||
type: 'match_any',
|
||||
value: ['foo'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
createRule(
|
||||
getNewRule({
|
||||
query: 'agent.name:*',
|
||||
index: ['exceptions*'],
|
||||
exceptions_list: [
|
||||
{
|
||||
id: response.body.id,
|
||||
list_id: exceptionList.list_id,
|
||||
type: exceptionList.type,
|
||||
namespace_type: exceptionList.namespace_type,
|
||||
},
|
||||
],
|
||||
rule_id: '2',
|
||||
})
|
||||
).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'rule_exceptions')));
|
||||
});
|
||||
});
|
||||
|
||||
it('Edits an exception item', () => {
|
||||
const NEW_ITEM_NAME = 'Exception item-EDITED';
|
||||
const ITEM_NAME = 'Sample Exception List Item 2';
|
||||
|
||||
// displays existing exception items
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist');
|
||||
cy.get(EXCEPTION_CARD_ITEM_NAME).should('have.text', ITEM_NAME);
|
||||
cy.get(EXCEPTION_CARD_ITEM_CONDITIONS).should(
|
||||
'have.text',
|
||||
' unique_value.testis one of foo'
|
||||
);
|
||||
|
||||
// open edit exception modal
|
||||
openEditException();
|
||||
|
||||
// edit exception item name
|
||||
editExceptionFlyoutItemName(NEW_ITEM_NAME);
|
||||
|
||||
// check that the existing item's field is being populated
|
||||
cy.get(EXCEPTION_ITEM_CONTAINER)
|
||||
.eq(0)
|
||||
.find(FIELD_INPUT_PARENT)
|
||||
.eq(0)
|
||||
.should('have.text', ITEM_FIELD);
|
||||
cy.get(VALUES_MATCH_ANY_INPUT).should('have.text', 'foo');
|
||||
|
||||
// edit conditions
|
||||
editException(FIELD_DIFFERENT_FROM_EXISTING_ITEM_FIELD, 0, 0);
|
||||
|
||||
// submit
|
||||
submitEditedExceptionItem();
|
||||
|
||||
// new exception item displays
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
|
||||
// check that updates stuck
|
||||
cy.get(EXCEPTION_CARD_ITEM_NAME).should('have.text', NEW_ITEM_NAME);
|
||||
cy.get(EXCEPTION_CARD_ITEM_CONDITIONS).should('have.text', ' agent.nameIS foo');
|
||||
});
|
||||
|
||||
describe('rule with existing shared exceptions', () => {
|
||||
it('Creates an exception item to add to shared list', () => {
|
||||
// displays existing exception items
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist');
|
||||
|
||||
// open add exception modal
|
||||
addExceptionFlyoutFromViewerHeader();
|
||||
|
||||
// add exception item conditions
|
||||
addExceptionConditions(getException());
|
||||
|
||||
// Name is required so want to check that submit is still disabled
|
||||
cy.get(CONFIRM_BTN).should('have.attr', 'disabled');
|
||||
|
||||
// add exception item name
|
||||
addExceptionFlyoutItemName('My item name');
|
||||
|
||||
// select to add exception item to a shared list
|
||||
selectSharedListToAddExceptionTo(1);
|
||||
|
||||
// not testing close alert functionality here, just ensuring that the options appear as expected
|
||||
cy.get(CLOSE_ALERTS_CHECKBOX).should('exist');
|
||||
cy.get(CLOSE_ALERTS_CHECKBOX).should('not.have.attr', 'disabled');
|
||||
|
||||
// submit
|
||||
submitNewExceptionItem();
|
||||
|
||||
// new exception item displays
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 2);
|
||||
});
|
||||
|
||||
it('Creates an exception item to add to rule only', () => {
|
||||
// displays existing exception items
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist');
|
||||
|
||||
// open add exception modal
|
||||
addExceptionFlyoutFromViewerHeader();
|
||||
|
||||
// add exception item conditions
|
||||
addExceptionConditions(getException());
|
||||
|
||||
// Name is required so want to check that submit is still disabled
|
||||
cy.get(CONFIRM_BTN).should('have.attr', 'disabled');
|
||||
|
||||
// add exception item name
|
||||
addExceptionFlyoutItemName('My item name');
|
||||
|
||||
// select to add exception item to rule only
|
||||
selectAddToRuleRadio();
|
||||
|
||||
// not testing close alert functionality here, just ensuring that the options appear as expected
|
||||
cy.get(CLOSE_ALERTS_CHECKBOX).should('exist');
|
||||
cy.get(CLOSE_ALERTS_CHECKBOX).should('not.have.attr', 'disabled');
|
||||
|
||||
// submit
|
||||
submitNewExceptionItem();
|
||||
|
||||
// new exception item displays
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 2);
|
||||
});
|
||||
|
||||
// Trying to figure out with EUI why the search won't trigger
|
||||
it('Can search for items', () => {
|
||||
// displays existing exception items
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist');
|
||||
|
||||
// can search for an exception value
|
||||
searchForExceptionItem('foo');
|
||||
|
||||
// new exception item displays
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
|
||||
// displays empty search result view if no matches found
|
||||
searchForExceptionItem('abc');
|
||||
|
||||
// new exception item displays
|
||||
cy.get(NO_EXCEPTIONS_SEARCH_RESULTS_PROMPT).should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('rule without existing exceptions', () => {
|
||||
beforeEach(() => {
|
||||
createRule(
|
||||
getNewRule({
|
||||
query: 'agent.name:*',
|
||||
index: ['exceptions*'],
|
||||
exceptions_list: [
|
||||
{
|
||||
id: response.body.id,
|
||||
list_id: exceptionList.list_id,
|
||||
type: exceptionList.type,
|
||||
namespace_type: exceptionList.namespace_type,
|
||||
},
|
||||
],
|
||||
rule_id: '2',
|
||||
interval: '10s',
|
||||
rule_id: 'rule_testing',
|
||||
})
|
||||
).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'rule_exceptions')));
|
||||
});
|
||||
});
|
||||
|
||||
it('Edits an exception item', () => {
|
||||
const NEW_ITEM_NAME = 'Exception item-EDITED';
|
||||
const ITEM_NAME = 'Sample Exception List Item 2';
|
||||
|
||||
// displays existing exception items
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist');
|
||||
cy.get(EXCEPTION_CARD_ITEM_NAME).should('have.text', ITEM_NAME);
|
||||
cy.get(EXCEPTION_CARD_ITEM_CONDITIONS).should('have.text', ' unique_value.testis one of foo');
|
||||
|
||||
// open edit exception modal
|
||||
openEditException();
|
||||
|
||||
// edit exception item name
|
||||
editExceptionFlyoutItemName(NEW_ITEM_NAME);
|
||||
|
||||
// check that the existing item's field is being populated
|
||||
cy.get(EXCEPTION_ITEM_CONTAINER)
|
||||
.eq(0)
|
||||
.find(FIELD_INPUT_PARENT)
|
||||
.eq(0)
|
||||
.should('have.text', ITEM_FIELD);
|
||||
cy.get(VALUES_MATCH_ANY_INPUT).should('have.text', 'foo');
|
||||
|
||||
// edit conditions
|
||||
editException(FIELD_DIFFERENT_FROM_EXISTING_ITEM_FIELD, 0, 0);
|
||||
|
||||
// submit
|
||||
submitEditedExceptionItem();
|
||||
|
||||
// new exception item displays
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
|
||||
// check that updates stuck
|
||||
cy.get(EXCEPTION_CARD_ITEM_NAME).should('have.text', NEW_ITEM_NAME);
|
||||
cy.get(EXCEPTION_CARD_ITEM_CONDITIONS).should('have.text', ' agent.nameIS foo');
|
||||
});
|
||||
|
||||
describe('rule with existing shared exceptions', () => {
|
||||
it('Creates an exception item to add to shared list', () => {
|
||||
// displays existing exception items
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist');
|
||||
|
||||
// open add exception modal
|
||||
addExceptionFlyoutFromViewerHeader();
|
||||
|
||||
// add exception item conditions
|
||||
addExceptionConditions(getException());
|
||||
|
||||
// Name is required so want to check that submit is still disabled
|
||||
cy.get(CONFIRM_BTN).should('have.attr', 'disabled');
|
||||
|
||||
// add exception item name
|
||||
addExceptionFlyoutItemName('My item name');
|
||||
|
||||
// select to add exception item to a shared list
|
||||
selectSharedListToAddExceptionTo(1);
|
||||
|
||||
// not testing close alert functionality here, just ensuring that the options appear as expected
|
||||
cy.get(CLOSE_ALERTS_CHECKBOX).should('exist');
|
||||
cy.get(CLOSE_ALERTS_CHECKBOX).should('not.have.attr', 'disabled');
|
||||
|
||||
// submit
|
||||
submitNewExceptionItem();
|
||||
|
||||
// new exception item displays
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 2);
|
||||
afterEach(() => {
|
||||
cy.task('esArchiverUnload', 'exceptions_2');
|
||||
});
|
||||
|
||||
it('Creates an exception item to add to rule only', () => {
|
||||
// displays existing exception items
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist');
|
||||
it('Cannot create an item to add to rule but not shared list as rule has no lists attached', () => {
|
||||
// when no exceptions exist, empty component shows with action to add exception
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist');
|
||||
|
||||
// open add exception modal
|
||||
addExceptionFlyoutFromViewerHeader();
|
||||
openExceptionFlyoutFromEmptyViewerPrompt();
|
||||
|
||||
// add exception item conditions
|
||||
addExceptionConditions(getException());
|
||||
addExceptionConditions({
|
||||
field: 'agent.name',
|
||||
operator: 'is',
|
||||
values: ['foo'],
|
||||
});
|
||||
|
||||
// Name is required so want to check that submit is still disabled
|
||||
cy.get(CONFIRM_BTN).should('have.attr', 'disabled');
|
||||
|
@ -211,120 +289,50 @@ describe('Add/edit exception from rule details', { tags: ['@ess', '@brokenInServ
|
|||
// select to add exception item to rule only
|
||||
selectAddToRuleRadio();
|
||||
|
||||
// not testing close alert functionality here, just ensuring that the options appear as expected
|
||||
cy.get(CLOSE_ALERTS_CHECKBOX).should('exist');
|
||||
cy.get(CLOSE_ALERTS_CHECKBOX).should('not.have.attr', 'disabled');
|
||||
// Check that add to shared list is disabled, should be unless
|
||||
// rule has shared lists attached to it already
|
||||
cy.get(ADD_TO_SHARED_LIST_RADIO_INPUT).should('have.attr', 'disabled');
|
||||
|
||||
// Close matching alerts
|
||||
selectBulkCloseAlerts();
|
||||
|
||||
// submit
|
||||
submitNewExceptionItem();
|
||||
|
||||
// new exception item displays
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 2);
|
||||
});
|
||||
|
||||
// Trying to figure out with EUI why the search won't trigger
|
||||
it('Can search for items', () => {
|
||||
// displays existing exception items
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist');
|
||||
|
||||
// can search for an exception value
|
||||
searchForExceptionItem('foo');
|
||||
|
||||
// new exception item displays
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
|
||||
// displays empty search result view if no matches found
|
||||
searchForExceptionItem('abc');
|
||||
// Alerts table should now be empty from having added exception and closed
|
||||
// matching alert
|
||||
goToAlertsTab();
|
||||
cy.get(EMPTY_ALERT_TABLE).should('exist');
|
||||
|
||||
// new exception item displays
|
||||
cy.get(NO_EXCEPTIONS_SEARCH_RESULTS_PROMPT).should('exist');
|
||||
// Closed alert should appear in table
|
||||
goToClosedAlertsOnRuleDetailsPage();
|
||||
cy.get(ALERTS_COUNT).should('exist');
|
||||
cy.get(ALERTS_COUNT).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`);
|
||||
|
||||
// Remove the exception and load an event that would have matched that exception
|
||||
// to show that said exception now starts to show up again
|
||||
goToExceptionsTab();
|
||||
|
||||
// when removing exception and again, no more exist, empty screen shows again
|
||||
removeException();
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist');
|
||||
|
||||
// load more docs
|
||||
cy.task('esArchiverLoad', { archiveName: 'exceptions_2' });
|
||||
|
||||
// now that there are no more exceptions, the docs should match and populate alerts
|
||||
goToAlertsTab();
|
||||
waitForAlertsToPopulate();
|
||||
goToOpenedAlertsOnRuleDetailsPage();
|
||||
waitForTheRuleToBeExecuted();
|
||||
waitForAlertsToPopulate();
|
||||
|
||||
cy.get(ALERTS_COUNT).should('exist');
|
||||
cy.get(ALERTS_COUNT).should('have.text', '2 alerts');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('rule without existing exceptions', () => {
|
||||
beforeEach(() => {
|
||||
createRule(
|
||||
getNewRule({
|
||||
query: 'agent.name:*',
|
||||
index: ['exceptions*'],
|
||||
interval: '10s',
|
||||
rule_id: 'rule_testing',
|
||||
})
|
||||
).then((rule) => visitWithoutDateRange(ruleDetailsUrl(rule.body.id, 'rule_exceptions')));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cy.task('esArchiverUnload', 'exceptions_2');
|
||||
});
|
||||
|
||||
it('Cannot create an item to add to rule but not shared list as rule has no lists attached', () => {
|
||||
// when no exceptions exist, empty component shows with action to add exception
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist');
|
||||
|
||||
// open add exception modal
|
||||
openExceptionFlyoutFromEmptyViewerPrompt();
|
||||
|
||||
// add exception item conditions
|
||||
addExceptionConditions({
|
||||
field: 'agent.name',
|
||||
operator: 'is',
|
||||
values: ['foo'],
|
||||
});
|
||||
|
||||
// Name is required so want to check that submit is still disabled
|
||||
cy.get(CONFIRM_BTN).should('have.attr', 'disabled');
|
||||
|
||||
// add exception item name
|
||||
addExceptionFlyoutItemName('My item name');
|
||||
|
||||
// select to add exception item to rule only
|
||||
selectAddToRuleRadio();
|
||||
|
||||
// Check that add to shared list is disabled, should be unless
|
||||
// rule has shared lists attached to it already
|
||||
cy.get(ADD_TO_SHARED_LIST_RADIO_INPUT).should('have.attr', 'disabled');
|
||||
|
||||
// Close matching alerts
|
||||
selectBulkCloseAlerts();
|
||||
|
||||
// submit
|
||||
submitNewExceptionItem();
|
||||
|
||||
// new exception item displays
|
||||
cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1);
|
||||
|
||||
// Alerts table should now be empty from having added exception and closed
|
||||
// matching alert
|
||||
goToAlertsTab();
|
||||
cy.get(EMPTY_ALERT_TABLE).should('exist');
|
||||
|
||||
// Closed alert should appear in table
|
||||
goToClosedAlertsOnRuleDetailsPage();
|
||||
cy.get(ALERTS_COUNT).should('exist');
|
||||
cy.get(ALERTS_COUNT).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`);
|
||||
|
||||
// Remove the exception and load an event that would have matched that exception
|
||||
// to show that said exception now starts to show up again
|
||||
goToExceptionsTab();
|
||||
|
||||
// when removing exception and again, no more exist, empty screen shows again
|
||||
removeException();
|
||||
cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist');
|
||||
|
||||
// load more docs
|
||||
cy.task('esArchiverLoad', { archiveName: 'exceptions_2' });
|
||||
|
||||
// now that there are no more exceptions, the docs should match and populate alerts
|
||||
goToAlertsTab();
|
||||
waitForAlertsToPopulate();
|
||||
goToOpenedAlertsOnRuleDetailsPage();
|
||||
waitForTheRuleToBeExecuted();
|
||||
waitForAlertsToPopulate();
|
||||
|
||||
cy.get(ALERTS_COUNT).should('exist');
|
||||
cy.get(ALERTS_COUNT).should('have.text', '2 alerts');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -40,9 +40,10 @@ import {
|
|||
} from '../../../screens/exceptions';
|
||||
import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe(
|
||||
'Add exception using data views from rule details',
|
||||
{ tags: ['@ess', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert';
|
||||
const ITEM_NAME = 'Sample Exception List Item';
|
||||
|
|
|
@ -26,7 +26,8 @@ import {
|
|||
deleteExceptionList,
|
||||
} from '../../../tasks/api_calls/exceptions';
|
||||
|
||||
describe('Exceptions viewer read only', { tags: '@ess' }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539 Do we need this to run in Serverless?
|
||||
describe('Exceptions viewer read only', { tags: ['@ess', '@skipInServerless'] }, () => {
|
||||
const exceptionList = getExceptionList();
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -40,10 +40,11 @@ const getExceptionList1 = () => ({
|
|||
|
||||
const EXCEPTION_LIST_NAME = 'Newly created list';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165640
|
||||
describe(
|
||||
'Exception list detail page',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
before(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
|
|
|
@ -37,10 +37,11 @@ import {
|
|||
waitForExceptionsTableToBeLoaded,
|
||||
} from '../../../tasks/exceptions_table';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165795
|
||||
describe(
|
||||
'Add, edit and delete exception',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
|
|
|
@ -40,8 +40,9 @@ const getExceptionList2 = () => ({
|
|||
list_id: 'exception_list_2',
|
||||
});
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// Flaky in serverless tests
|
||||
describe('Duplicate List', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
describe('Duplicate List', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
login();
|
||||
|
|
|
@ -35,7 +35,9 @@ const getExceptionList2 = () => ({
|
|||
name: EXCEPTION_LIST_NAME_TWO,
|
||||
list_id: 'exception_list_2',
|
||||
});
|
||||
describe('Filter Lists', { tags: ['@ess', '@serverless'] }, () => {
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe('Filter Lists', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
login();
|
||||
|
|
|
@ -20,8 +20,9 @@ import {
|
|||
import { login, visitWithoutDateRange } from '../../../../tasks/login';
|
||||
import { EXCEPTIONS_URL } from '../../../../urls/navigation';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// Flaky in serverless
|
||||
describe('Import Lists', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => {
|
||||
describe('Import Lists', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
const LIST_TO_IMPORT_FILENAME = 'cypress/fixtures/7_16_exception_list.ndjson';
|
||||
before(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
|
|
|
@ -47,10 +47,11 @@ const getExceptionList2 = () => ({
|
|||
|
||||
let exceptionListResponse: Cypress.Response<ExceptionListSchema>;
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165690
|
||||
describe(
|
||||
'Manage lists from "Shared Exception Lists" page',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
{ tags: ['@ess', '@serverless', '@skipInServerless'] },
|
||||
() => {
|
||||
describe('Create/Export/Delete List', () => {
|
||||
before(() => {
|
||||
|
|
|
@ -21,7 +21,8 @@ import {
|
|||
import { login, visitWithoutDateRange } from '../../../../tasks/login';
|
||||
import { EXCEPTIONS_URL } from '../../../../urls/navigation';
|
||||
|
||||
describe('Shared exception lists - read only', { tags: '@ess' }, () => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539 Do we need to run it in Serverless?
|
||||
describe('Shared exception lists - read only', { tags: ['@ess', '@skipInServerless'] }, () => {
|
||||
before(() => {
|
||||
cy.task('esArchiverResetKibana');
|
||||
});
|
||||
|
|
|
@ -15,8 +15,9 @@ import {
|
|||
import { login, visit } from '../../tasks/login';
|
||||
import { OVERVIEW_URL } from '../../urls/navigation';
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/165709
|
||||
describe.skip('CTI Link Panel', { tags: ['@ess', '@serverless'] }, () => {
|
||||
describe.skip('CTI Link Panel', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
@ -31,35 +32,40 @@ describe.skip('CTI Link Panel', { tags: ['@ess', '@serverless'] }, () => {
|
|||
.and('match', /app\/integrations\/browse\/threat_intel/);
|
||||
});
|
||||
|
||||
describe('enabled threat intel module', { tags: ['@brokenInServerless'] }, () => {
|
||||
before(() => {
|
||||
// illegal_argument_exception: unknown setting [index.lifecycle.name]
|
||||
cy.task('esArchiverLoad', { archiveName: 'threat_indicator' });
|
||||
});
|
||||
// TODO: https://github.com/elastic/kibana/issues/161539
|
||||
describe(
|
||||
'enabled threat intel module',
|
||||
{ tags: ['@ess', '@serverless', '@brokenInServerless'] },
|
||||
() => {
|
||||
before(() => {
|
||||
// illegal_argument_exception: unknown setting [index.lifecycle.name]
|
||||
cy.task('esArchiverLoad', { archiveName: 'threat_indicator' });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
beforeEach(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cy.task('esArchiverUnload', 'threat_indicator');
|
||||
});
|
||||
after(() => {
|
||||
cy.task('esArchiverUnload', 'threat_indicator');
|
||||
});
|
||||
|
||||
it('renders disabled dashboard module as expected when there are no events in the selected time period', () => {
|
||||
visit(
|
||||
`${OVERVIEW_URL}?sourcerer=(timerange:(from:%272021-07-08T04:00:00.000Z%27,kind:absolute,to:%272021-07-09T03:59:59.999Z%27))`
|
||||
);
|
||||
cy.get(`${OVERVIEW_CTI_LINKS}`).should('exist');
|
||||
cy.get(`${OVERVIEW_CTI_TOTAL_EVENT_COUNT}`).should('have.text', 'Showing: 0 indicators');
|
||||
});
|
||||
it('renders disabled dashboard module as expected when there are no events in the selected time period', () => {
|
||||
visit(
|
||||
`${OVERVIEW_URL}?sourcerer=(timerange:(from:%272021-07-08T04:00:00.000Z%27,kind:absolute,to:%272021-07-09T03:59:59.999Z%27))`
|
||||
);
|
||||
cy.get(`${OVERVIEW_CTI_LINKS}`).should('exist');
|
||||
cy.get(`${OVERVIEW_CTI_TOTAL_EVENT_COUNT}`).should('have.text', 'Showing: 0 indicators');
|
||||
});
|
||||
|
||||
it('renders dashboard module as expected when there are events in the selected time period', () => {
|
||||
visit(OVERVIEW_URL);
|
||||
it('renders dashboard module as expected when there are events in the selected time period', () => {
|
||||
visit(OVERVIEW_URL);
|
||||
|
||||
cy.get(`${OVERVIEW_CTI_LINKS}`).should('exist');
|
||||
cy.get(OVERVIEW_CTI_LINKS).should('not.contain.text', 'Anomali');
|
||||
cy.get(OVERVIEW_CTI_LINKS).should('contain.text', 'AbuseCH malware');
|
||||
cy.get(`${OVERVIEW_CTI_TOTAL_EVENT_COUNT}`).should('have.text', 'Showing: 1 indicator');
|
||||
});
|
||||
});
|
||||
cy.get(`${OVERVIEW_CTI_LINKS}`).should('exist');
|
||||
cy.get(OVERVIEW_CTI_LINKS).should('not.contain.text', 'Anomali');
|
||||
cy.get(OVERVIEW_CTI_LINKS).should('contain.text', 'AbuseCH malware');
|
||||
cy.get(`${OVERVIEW_CTI_TOTAL_EVENT_COUNT}`).should('have.text', 'Showing: 1 indicator');
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
"junit:transform": "node ../../plugins/security_solution/scripts/junit_transformer --pathPattern '../../../target/kibana-security-solution/cypress/results/*.xml' --rootDirectory ../../../ --reportName 'Security Solution Cypress' --writeInPlace",
|
||||
"cypress:serverless": "TZ=UTC node ../../plugins/security_solution/scripts/start_cypress_parallel --config-file ../../test/security_solution_cypress/cypress/cypress_ci_serverless.config.ts --ftr-config-file ../../test/security_solution_cypress/serverless_config",
|
||||
"cypress:open:serverless": "yarn cypress:serverless open --config-file ../../test/security_solution_cypress/cypress/cypress_serverless.config.ts --spec './cypress/e2e/**/*.cy.ts'",
|
||||
"cypress:run:serverless": "yarn cypress:serverless --spec '**/cypress/e2e/!(investigations|explore)/**/*.cy.ts'",
|
||||
"cypress:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/!(investigations|explore)/**/*.cy.ts'",
|
||||
"cypress:investigations:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/investigations/**/*.cy.ts'",
|
||||
"cypress:explore:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/explore/**/*.cy.ts'",
|
||||
"cypress:changed-specs-only:serverless": "yarn cypress:serverless --changed-specs-only --env burn=2",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue