[Security Solution] Removing discontinued Cypress tests and code (#163496)

This commit is contained in:
Gloria Hornero 2023-08-09 20:18:57 +02:00 committed by GitHub
parent 4637b744d8
commit 5b51022303
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 2 additions and 1183 deletions

View file

@ -34,11 +34,8 @@ disabled:
- x-pack/test/osquery_cypress/cli_config.ts
- x-pack/test/osquery_cypress/config.ts
- x-pack/test/osquery_cypress/visual_config.ts
- x-pack/test/security_solution_cypress/ccs_config.ts
- x-pack/test/security_solution_cypress/cli_config.ts
- x-pack/test/security_solution_cypress/config.firefox.ts
- x-pack/test/security_solution_cypress/config.ts
- x-pack/test/security_solution_cypress/upgrade_config.ts
- x-pack/test/threat_intelligence_cypress/cli_config_parallel.ts
- x-pack/test/threat_intelligence_cypress/config.ts
- x-pack/test/functional_enterprise_search/visual_config.ts

View file

@ -1,14 +0,0 @@
#!/usr/bin/env bash
source test/scripts/jenkins_test_setup_xpack.sh
echo " -> Running security solution cypress tests"
cd "$XPACK_DIR"
node scripts/functional_tests \
--debug --bail \
--kibana-install-dir "$KIBANA_INSTALL_DIR" \
--config test/security_solution_cypress/config.firefox.ts
echo ""
echo ""

View file

@ -2,17 +2,12 @@
The `security_solution/cypress` directory contains functional UI tests that execute using [Cypress](https://www.cypress.io/).
Currently with Cypress you can develop `functional` tests and coming soon `CCS` and `Upgrade` functional tests.
Currently with Cypress you can develop `functional` tests.
If you are still having doubts, questions or queries, please feel free to ping our Cypress champions:
- Functional Tests:
- Gloria Hornero and Patryk Kopycinsky
- CCS Tests:
- Technical questions around the https://github.com/elastic/integration-test repo:
- Domenico Andreoli
- Doubts regarding testing CCS and Cypress best practices:
- Gloria Hornero
## Table of Contents
@ -51,246 +46,17 @@ Run the tests with the following yarn scripts:
| Script Name | Description |
| ----------- | ----------- |
| cypress | Runs the default Cypress command |
| cypress:open | Opens the Cypress UI with all tests in the `e2e` directory. This also runs a local kibana and ES instance. The kibana instance will reload when you make code changes. This is the recommended way to debug and develop tests. |
| cypress:open:ccs | Opens the Cypress UI and runs all tests in the `ccs_e2e` directory |
| cypress:open:upgrade | Opens the Cypress UI and runs all tests in the `upgrade_e2e` directory |
| cypress:open | Opens the Cypress UI with all tests in the `e2e` directory. This also runs a local kibana and ES instance. The kibana instance will reload when you make code changes. This is the recommended way to debug and develop tests. |C
| cypress:run | Runs all tests in the `e2e` directory excluding `investigations` and `explore` directories in headless mode |
| cypress:run:cases | Runs all tests under `explore/cases` in the `e2e` directory related to the Cases area team in headless mode |
| cypress:run:reporter | Runs all tests with the specified configuration in headless mode and produces a report using `cypress-multi-reporters` |
| cypress:run:respops | Runs all tests related to the Response Ops area team, specifically tests in `detection_alerts`, `detection_rules`, and `exceptions` directories in headless mode |
| cypress:run:ccs | Runs all tests in the `ccs_e2e` directory in headless mode |
| cypress:run:upgrade | Runs all tests in the `upgrade_e2e` directory in headless mode |
| cypress:investigations:run | Runs all tests in the `e2e/investigations` directory in headless mode |
| cypress:explore:run | Runs all tests in the `e2e/explore` directory in headless mode |
| junit:merge | Merges individual test reports into a single report and moves the report to the `junit` directory |
Please note that all the headless mode commands do not open the Cypress UI and are typically used in CI/CD environments. The scripts that open the Cypress UI are useful for development and debugging.
### Execution modes
There are currently four ways to run the tests, comprised of two execution modes and two target environments, which will be detailed below.
#### Interactive mode
When you run Cypress in interactive mode, an interactive runner is displayed that allows you to see commands as they execute while also viewing the application under test. For more information, please see [cypress documentation](https://docs.cypress.io/guides/core-concepts/test-runner.html#Overview).
#### Headless mode
A headless browser is a browser simulation program that does not have a user interface. These programs operate like any other browser, but do not display any UI. This is why meanwhile you are executing the tests on this mode you are not going to see the application under test. Just the output of the test is displayed on the terminal once the execution is finished.
### Target environments
#### FTR (CI)
This is the configuration used by CI. It uses the FTR to spawn both a Kibana instance (http://localhost:5620) and an Elasticsearch instance (http://localhost:9220) with a preloaded minimum set of data (see preceding "Test data" section), and then executes cypress against this stack. You can find this configuration in `x-pack/test/security_solution_cypress`
Tests run on buildkite PR pipeline is parallelized. It can be configured in [.buildkite/pipelines/pull_request/security_solution.yml](https://github.com/elastic/kibana/blob/main/.buildkite/pipelines/pull_request/security_solution.yml) with property `parallelism`
```yml
...
agents:
queue: n2-4-spot
depends_on: build
timeout_in_minutes: 120
parallelism: 4
...
```
#### Custom Targets
This configuration runs cypress tests against an arbitrary host.
**WARNING**: When using your own instances you need to take into account that if you already have data on it, the tests may fail, as well as, they can put your instances in an undesired state, since our tests uses es_archive to populate data.
#### integration-test (CI)
This configuration is driven by [elastic/integration-test](https://github.com/elastic/integration-test) which, as part of a bigger set of tests, provisions one VM with two instances configured in CCS mode and runs the [CCS Cypress test specs](./ccs_e2e).
The two clusters are named `admin` and `data` and are reachable as follows:
| | Elasticsearch | Kibana |
| ----- | ---------------------- | ---------------------- |
| admin | https://localhost:9200 | https://localhost:5601 |
| data | https://localhost:9210 | https://localhost:5602 |
### Working with integration-test
#### Initial setup and prerequisites
The entry point is [integration-test/jenkins_test.sh](https://github.com/elastic/integration-test/blob/master/jenkins_test.sh), it essentially prepares the VMs and there runs tests. Some snapshots (`phase1` and `phase2`) are taken along the way so that it's possible to short cut the VM preparation when iterating over tests for development or debugging.
The VMs are managed with Vagrant using the VirtualBox provider therefore you need to install both these tools. The host OS can be either Windows, Linux or MacOS.
`jenkins_test.sh` assumes that a `kibana` folder is present alongside the `integration-test` where it's executed from. The `kibana` folder is used only for loading the test suites though, the actual packages for the VMs preparation are downloaded from elastic.co according to the `BUILD` environment variable or the branch which `jenkins_test.sh` is invoked from. It's your responsibility to checkout the matching branches in `kibana` and `integration-test` as needed.
Read [integration-test#readme](https://github.com/elastic/integration-test#readme) for further details.
#### Use cases
There is no way to just set up the test environment without also executing tests at least once. On the other hand it's time consuming to go throught the whole CI procedure to just iterate over the tests therefore the following instructions support the two use cases:
- reproduce e2e the CI execution locally, ie. for debugging a CI failure
- use the CI script to easily setup the environment for tests development/debugging
The missing use case, application TDD, requires a different solution that runs from the checked out repositories instead of the pre-built packages and it's yet to be developed.
#### Run the CI flow
This is the CI flow narrowed down to the execution of CCS Cypress tests:
```shell
cd integration-test
VMS=ubuntu16_tar_ccs_cypress ./jenkins_test.sh
```
It destroys and rebuilds the VM. There installs, provisions and starts the stack according to the configuration in [integration-test/provision/ubuntu16_tar_ccs_cypress.sh](https://github.com/elastic/integration-test/blob/master/provision/ubuntu16_tar_ccs_cypress.sh).
The tests are executed using the FTR runner `SecuritySolutionCypressCcsTestRunner` defined in [x-pack/test/security_solution_cypress/runner.ts](../../../test/security_solution_cypress/runner.ts) as configured in [x-pack/test/security_solution_cypress/ccs_config.ts](../../../test/security_solution_cypress/ccs_config.ts).
#### Re-run the tests
After the first run it's possible to restore the VM at `phase2`, right before tests were executed, and run them again:
```shell
cd integration-test
MODE=retest ./jenkins_test.sh
```
It remembers which VM the first round was executed on, you don't need to specify `VMS` any more.
In case your tests are cleaning after themselves and therefore result idempotent, you can skip the restoration to `phase2` and directly run the Cypress command line. See [CCS Custom Target + Headless](#ccs-custom-target--headless) further below for details but ensure you'll define the `CYPRESS_*` following the correspondence:
| Cypress command line | [integration-test/provision/ubuntu16_tar_ccs_cypress.sh](https://github.com/elastic/integration-test/blob/master/provision/ubuntu16_tar_ccs_cypress.sh) |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| CYPRESS_BASE_URL | TEST_KIBANA_URL |
| CYPRESS_ELASTICSEARCH_URL | TEST_ES_URL |
| CYPRESS_CCS_KIBANA_URL | TEST_KIBANA_URLDATA |
| CYPRESS_CCS_ELASTICSEARCH_URL | TEST_ES_URLDATA |
| CYPRESS_CCS_REMOTE_NAME | TEST_CCS_REMOTE_NAME |
| CYPRESS_ELASTICSEARCH_USERNAME | ELASTICSEARCH_USERNAME |
| CYPRESS_ELASTICSEARCH_PASSWORD | ELASTICSEARCH_PASSWORD |
| TEST_CA_CERT_PATH | integration-test/certs/ca/ca.crt |
Note: `TEST_CA_CERT_PATH` above is truly without `CYPRESS_` prefix.
### Test Execution: Examples
#### FTR + Headless (Chrome)
Since this is how tests are run on CI, this will likely be the configuration you want to reproduce failures locally, etc.
```shell
# bootstrap kibana from the project root
yarn kbn bootstrap
# build the plugins/assets that cypress will execute against
node scripts/build_kibana_platform_plugins
# launch the cypress test runner
cd x-pack/plugins/security_solution
yarn cypress:run-as-ci
```
#### FTR + Headless (Firefox)
Since this is how tests are run on CI, this will likely be the configuration you want to reproduce failures locally, etc.
```shell
# bootstrap kibana from the project root
yarn kbn bootstrap
# build the plugins/assets that cypress will execute against
node scripts/build_kibana_platform_plugins
# launch the cypress test runner
cd x-pack/plugins/security_solution
yarn cypress:run-as-ci:firefox
```
#### FTR + Interactive
This is the preferred mode for developing new tests.
```shell
# bootstrap kibana from the project root
yarn kbn bootstrap
# build the plugins/assets that cypress will execute against
node scripts/build_kibana_platform_plugins
# launch the cypress test runner
cd x-pack/plugins/security_solution
yarn cypress:open-as-ci
```
Note that you can select the browser you want to use on the top right side of the interactive runner.
#### Custom Target + Headless (Chrome)
This mode may be useful for testing a release, e.g. spin up a build candidate
and point cypress at it to catch regressions.
```shell
# bootstrap kibana from the project root
yarn kbn bootstrap
# load auditbeat data needed for test execution (which FTR normally does for us)
cd x-pack/plugins/security_solution
node ../../../scripts/es_archiver load auditbeat --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.base.js --es-url http(s)://<username>:<password>@<elsUrl> --kibana-url http(s)://<userName>:<password>@<kbnUrl>
# launch the cypress test runner with overridden environment variables
cd x-pack/plugins/security_solution
CYPRESS_BASE_URL=http(s)://<username>:<password>@<kbnUrl> CYPRESS_ELASTICSEARCH_URL=http(s)://<username>:<password>@<elsUrl> CYPRESS_ELASTICSEARCH_USERNAME=<username> CYPRESS_ELASTICSEARCH_PASSWORD=<password> yarn cypress:run
```
#### Custom Target + Headless (Firefox)
This mode may be useful for testing a release, e.g. spin up a build candidate
and point cypress at it to catch regressions.
```shell
# bootstrap kibana from the project root
yarn kbn bootstrap
# load auditbeat data needed for test execution (which FTR normally does for us)
cd x-pack/plugins/security_solution
node ../../../scripts/es_archiver load auditbeat --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.base.js --es-url http(s)://<username>:<password>@<elsUrl> --kibana-url http(s)://<userName>:<password>@<kbnUrl>
# launch the cypress test runner with overridden environment variables
cd x-pack/plugins/security_solution
CYPRESS_BASE_URL=http(s)://<username>:<password>@<kbnUrl> CYPRESS_ELASTICSEARCH_URL=http(s)://<username>:<password>@<elsUrl> CYPRESS_ELASTICSEARCH_USERNAME=<username> CYPRESS_ELASTICSEARCH_PASSWORD=<password> yarn cypress:run:firefox
```
#### CCS Custom Target + Headless
This test execution requires two clusters configured for CCS. See [Search across clusters](https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-cross-cluster-search.html) for instructions on how to prepare such setup.
The instructions below assume:
- Search cluster is on server1
- Remote cluster is on server2
- Remote cluster is accessible from the search cluster with name `remote`
- Security and TLS are enabled
```shell
# bootstrap Kibana from the project root
yarn kbn bootstrap
# launch the Cypress test runner with overridden environment variables
cd x-pack/plugins/security_solution
CYPRESS_ELASTICSEARCH_USERNAME="user" \
CYPRESS_ELASTICSEARCH_PASSWORD="pass" \
CYPRESS_BASE_URL="https://user:pass@server1:5601" \
CYPRESS_ELASTICSEARCH_URL="https://user:pass@server1:9200" \
CYPRESS_CCS_KIBANA_URL="https://user:pass@server2:5601" \
CYPRESS_CCS_ELASTICSEARCH_URL="https://user:pass@server2:9200" \
CYPRESS_CCS_REMOTE_NAME="remote" \
yarn cypress:run:ccs
```
Similar sequence, just ending with `yarn cypress:open:ccs`, can be used for interactive test running via Cypress UI.
Appending `--browser firefox` to the `yarn cypress:run:ccs` command above will run the tests on Firefox instead of Chrome.
## Debugging your test
In order to be able to debug any Cypress test you need to open Cypress on visual mode. [Here](https://docs.cypress.io/guides/guides/debugging)
@ -302,10 +68,6 @@ If you are debugging a flaky test, a good tip is to insert a `cy.wait(<some long
Below you can find the folder structure used on our Cypress tests.
### ccs_e2e/
Contains the specs that are executed in a Cross Cluster Search configuration.
### e2e/
Cypress convention starting version 10 (previously known as integration). Contains the specs that are going to be executed.
@ -404,44 +166,6 @@ Note that the command will create the folder if it does not exist.
Task [cypress/support/es_archiver.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/cypress/support/es_archiver.ts) provides helpers such as `esArchiverLoad` and `esArchiverUnload` by means of `es_archiver`'s CLI.
### CCS
Tests running in CCS configuration need to care about two aspects:
1. data (eg. to trigger alerts) is generated/loaded on the remote cluster
2. queries (eg. detection rules) refer to remote indices
Incorrect handling of the above points might result in false positives, in that the remote cluster is not involved but the test passes anyway.
#### Remote data loading
Helpers `esArchiverCCSLoad` and `esArchiverCCSUnload` are provided by [cypress/support/es_archiver.ts](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/cypress/support/es_archiver.ts):
```javascript
cy.task('esArchiverCCSLoad', '<archive_name>');
```
They will use the `CYPRESS_CCS_*_URL` environment variables for accessing the remote cluster. Complex tests involving local and remote data can interleave them with `esArchiverLoad` and `esArchiverUnload` as needed.
#### Remote indices queries
Queries accessing remote indices follow the usual `<remote_name>:<remote_index>` notation but should not hard-code the remote name in the test itself.
For such reason the environemnt variable `CYPRESS_CCS_REMOTE_NAME` is defined and, in the case of detection rules, used as shown below:
```javascript
const ccsRemoteName: string = Cypress.env('CCS_REMOTE_NAME');
export const unmappedCCSRule: CustomRule = {
customQuery: '*:*',
index: [`${ccsRemoteName}:unmapped*`],
...
};
```
Similar approach should be used in defining all index patterns, rules, and queries to be applied on remote data.
## Development Best Practices
Below you will a set of best practices that should be followed when writing Cypress tests.
@ -478,12 +202,6 @@ taken into consideration until another solution is implemented:
Remember that minimizing the number of times the web page is loaded, we minimize as well the execution time.
### CCS test specific
When testing CCS we want to put our focus in making sure that our `Source` instance is receiving properly the data that comes from the `Remote` instances, as well as the data is displayed as we expect on the `Source`.
For that reason and in order to make our test more stable, use the API to execute all the actions needed before the assertions, and use Cypress to assert that the UI is displaying all the expected things.
## Test Artifacts
When Cypress tests are run headless on the command line, artifacts

View file

@ -1,41 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { JSON_TEXT } from '../../screens/alerts_details';
import { expandFirstAlert, waitForAlerts } from '../../tasks/alerts';
import { openJsonView } from '../../tasks/alerts_details';
import { createRule } from '../../tasks/api_calls/rules';
import { cleanKibana } from '../../tasks/common';
import { login, visitWithoutDateRange } from '../../tasks/login';
import { getUnmappedCCSRule } from '../../objects/rule';
import { ALERTS_URL } from '../../urls/navigation';
describe('Alert details with unmapped fields', () => {
beforeEach(() => {
login();
cleanKibana();
cy.task('esArchiverCCSLoad', 'unmapped_fields');
createRule(getUnmappedCCSRule());
visitWithoutDateRange(ALERTS_URL);
waitForAlerts();
expandFirstAlert();
});
it('Displays the unmapped field on the JSON view', () => {
const expectedUnmappedValue = 'This is the unmapped field';
openJsonView();
cy.get(JSON_TEXT).then((x) => {
const parsed = JSON.parse(x.text());
expect(parsed.fields.unmapped[0]).to.equal(expectedUnmappedValue);
});
});
});

View file

@ -1,53 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { getCCSEqlRule } from '../../objects/rule';
import { ALERTS_COUNT, ALERT_DATA_GRID } from '../../screens/alerts';
import {
filterByCustomRules,
goToRuleDetails,
waitForRulesTableToBeLoaded,
} from '../../tasks/alerts_detection_rules';
import { createRule } from '../../tasks/api_calls/rules';
import { cleanKibana } from '../../tasks/common';
import { waitForAlertsToPopulate, waitForTheRuleToBeExecuted } from '../../tasks/create_new_rule';
import { login, visitWithoutDateRange } from '../../tasks/login';
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation';
describe('Detection rules', function () {
const expectedNumberOfAlerts = '1 alert';
beforeEach('Reset signals index', function () {
cleanKibana();
});
it('EQL rule on remote indices generates alerts', function () {
cy.task('esArchiverCCSLoad', 'linux_process');
const rule = getCCSEqlRule();
login();
createRule(rule);
visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL);
waitForRulesTableToBeLoaded();
filterByCustomRules();
goToRuleDetails();
waitForTheRuleToBeExecuted();
waitForAlertsToPopulate();
cy.get(ALERTS_COUNT).should('have.text', expectedNumberOfAlerts);
cy.get(ALERT_DATA_GRID)
.invoke('text')
.then((text) => {
cy.log('ALERT_DATA_GRID', text);
expect(text).contains(rule.name);
expect(text).contains(rule.severity);
expect(text).contains(rule.risk_score);
});
});
});

View file

@ -1,141 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import semver from 'semver';
import {
ALERT_GRID_CELL,
DESTINATION_IP,
HOST_NAME,
PROCESS_NAME_COLUMN,
PROCESS_NAME,
REASON,
RISK_SCORE,
RULE_NAME,
SEVERITY,
SOURCE_IP,
USER_NAME,
} from '../../../screens/alerts';
import { SERVER_SIDE_EVENT_COUNT } from '../../../screens/alerts_detection_rules';
import {
ADDITIONAL_LOOK_BACK_DETAILS,
ABOUT_DETAILS,
ABOUT_RULE_DESCRIPTION,
CUSTOM_QUERY_DETAILS,
DEFINITION_DETAILS,
INDEX_PATTERNS_DETAILS,
RISK_SCORE_DETAILS,
RULE_NAME_HEADER,
RULE_TYPE_DETAILS,
RUNS_EVERY_DETAILS,
SCHEDULE_DETAILS,
SEVERITY_DETAILS,
TIMELINE_TEMPLATE_DETAILS,
} from '../../../screens/rule_details';
import { getDetails } from '../../../tasks/rule_details';
import { waitForPageToBeLoaded } from '../../../tasks/common';
import {
waitForRulesTableToBeLoaded,
goToTheRuleDetailsOf,
} from '../../../tasks/alerts_detection_rules';
import { login, visit } from '../../../tasks/login';
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation';
const EXPECTED_NUMBER_OF_ALERTS = '1';
const alert = {
rule: 'Custom query rule for upgrade',
severity: 'low',
riskScore: '7',
reason:
'file event with process test, file The file to test, by Security Solution on security-solution.local created low alert Custom query rule for upgrade.',
reasonAlt: '—',
hostName: 'security-solution.local',
username: 'Security Solution',
processName: 'test',
fileName: 'The file to test',
sourceIp: '127.0.0.1',
destinationIp: '127.0.0.2',
};
const rule = {
customQuery: '*:*',
name: 'Custom query rule for upgrade',
description: 'My description',
index: ['auditbeat-custom*'],
severity: 'Low',
riskScore: '7',
timelineTemplate: 'none',
runsEvery: '24h',
lookBack: '49976h',
timeline: 'None',
};
describe('After an upgrade, the custom query rule', () => {
before(() => {
login();
visit(DETECTIONS_RULE_MANAGEMENT_URL);
waitForRulesTableToBeLoaded();
goToTheRuleDetailsOf(rule.name);
waitForPageToBeLoaded();
// Possible bug on first attempt sometimes redirects page back to alerts
// Going to retry the block once
cy.url().then((url) => {
const currentUrl = url;
cy.log(`Current URL is : ${currentUrl}`);
if (!currentUrl.includes(DETECTIONS_RULE_MANAGEMENT_URL)) {
cy.log('Retrying not on correct page!');
visit(DETECTIONS_RULE_MANAGEMENT_URL);
waitForRulesTableToBeLoaded();
goToTheRuleDetailsOf(rule.name);
waitForPageToBeLoaded();
}
});
cy.url().should('include', DETECTIONS_RULE_MANAGEMENT_URL);
});
it('Has the expected alerts number', () => {
cy.get(SERVER_SIDE_EVENT_COUNT).contains(EXPECTED_NUMBER_OF_ALERTS);
});
it('Displays the rule details', () => {
cy.get(RULE_NAME_HEADER).should('contain', `${rule.name}`);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description);
cy.get(ABOUT_DETAILS).within(() => {
getDetails(SEVERITY_DETAILS).should('have.text', rule.severity);
getDetails(RISK_SCORE_DETAILS).should('have.text', rule.riskScore);
});
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should('have.text', rule.index.join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', rule.customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', rule.timeline);
});
cy.get(SCHEDULE_DETAILS).within(() => {
getDetails(RUNS_EVERY_DETAILS).should('have.text', rule.runsEvery);
getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should('have.text', rule.lookBack);
});
});
it('Displays the alert details at the tgrid', () => {
let expectedReason = alert.reason;
if (semver.lt(Cypress.env('ORIGINAL_VERSION'), '7.15.0')) {
expectedReason = alert.reasonAlt;
}
cy.get(ALERT_GRID_CELL).first().focus();
cy.get(RULE_NAME).should('have.text', alert.rule);
cy.get(SEVERITY).should('have.text', alert.severity);
cy.get(RISK_SCORE).should('have.text', alert.riskScore);
cy.get(REASON).contains(expectedReason);
cy.get(HOST_NAME).should('have.text', alert.hostName);
cy.get(USER_NAME).should('have.text', alert.username);
cy.get(PROCESS_NAME_COLUMN).eq(0).scrollIntoView();
cy.get(PROCESS_NAME).should('have.text', alert.processName);
cy.get(SOURCE_IP).should('have.text', alert.sourceIp);
cy.get(DESTINATION_IP).should('have.text', alert.destinationIp);
});
});

View file

@ -1,138 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import semver from 'semver';
import { REASON, RISK_SCORE, RULE_NAME, SEVERITY } from '../../../screens/alerts';
import { SERVER_SIDE_EVENT_COUNT } from '../../../screens/alerts_detection_rules';
import {
ADDITIONAL_LOOK_BACK_DETAILS,
ABOUT_DETAILS,
ABOUT_RULE_DESCRIPTION,
CUSTOM_QUERY_DETAILS,
DEFINITION_DETAILS,
INDEX_PATTERNS_DETAILS,
RISK_SCORE_DETAILS,
RULE_NAME_HEADER,
RULE_TYPE_DETAILS,
RUNS_EVERY_DETAILS,
SCHEDULE_DETAILS,
SEVERITY_DETAILS,
THRESHOLD_DETAILS,
TIMELINE_TEMPLATE_DETAILS,
} from '../../../screens/rule_details';
import { getDetails } from '../../../tasks/rule_details';
import { expandFirstAlert } from '../../../tasks/alerts';
import { waitForPageToBeLoaded } from '../../../tasks/common';
import {
goToTheRuleDetailsOf,
waitForRulesTableToBeLoaded,
} from '../../../tasks/alerts_detection_rules';
import { login, visit } from '../../../tasks/login';
import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation';
import {
OVERVIEW_RISK_SCORE,
OVERVIEW_RULE,
OVERVIEW_SEVERITY,
OVERVIEW_STATUS,
OVERVIEW_RULE_TYPE,
} from '../../../screens/alerts_details';
const EXPECTED_NUMBER_OF_ALERTS = '1';
const alert = {
rule: 'Threshold rule',
severity: 'medium',
riskScore: '17',
reason: 'event created medium alert Threshold rule.',
reasonAlt: '—',
hostName: 'security-solution.local',
thresholdCount: '2',
};
const rule = {
customQuery: '*:*',
name: 'Threshold rule',
description: 'Threshold rule for testing upgrade',
index: ['auditbeat-threshold*'],
severity: 'Medium',
riskScore: '17',
timelineTemplate: 'none',
runsEvery: '24h',
lookBack: '49976h',
timeline: 'None',
ruleType: 'threshold',
thresholdField: 'host.name',
thresholdValue: '1',
};
describe('After an upgrade, the threshold rule', () => {
before(() => {
login();
visit(DETECTIONS_RULE_MANAGEMENT_URL);
waitForRulesTableToBeLoaded();
goToTheRuleDetailsOf(rule.name);
waitForPageToBeLoaded();
});
it('Has the expected alerts number', () => {
cy.get(SERVER_SIDE_EVENT_COUNT).contains(EXPECTED_NUMBER_OF_ALERTS);
});
it('Displays the rule details', () => {
cy.get(RULE_NAME_HEADER).should('contain', rule.name);
cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description);
cy.get(ABOUT_DETAILS).within(() => {
getDetails(SEVERITY_DETAILS).should('have.text', rule.severity);
getDetails(RISK_SCORE_DETAILS).should('have.text', rule.riskScore);
});
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should('have.text', rule.index.join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', rule.customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Threshold');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', rule.timeline);
getDetails(THRESHOLD_DETAILS).should(
'have.text',
`Results aggregated by ${rule.thresholdField} >= ${rule.thresholdValue}`
);
});
cy.get(SCHEDULE_DETAILS).within(() => {
getDetails(RUNS_EVERY_DETAILS).should('have.text', rule.runsEvery);
getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should('have.text', rule.lookBack);
});
});
it('Displays the alert details in the TGrid', () => {
let expectedReason = alert.reason;
if (semver.lt(Cypress.env('ORIGINAL_VERSION'), '7.15.0')) {
expectedReason = alert.reasonAlt;
}
cy.scrollTo('bottom');
cy.get(RULE_NAME).should('have.text', alert.rule);
cy.get(SEVERITY).should('have.text', alert.severity);
cy.get(RISK_SCORE).should('have.text', alert.riskScore);
cy.get(REASON).contains(expectedReason);
// TODO: Needs data-test-subj
// cy.get(HOST_NAME).should('have.text', alert.hostName);
});
it('Displays the Overview alert details in the alert flyout', () => {
expandFirstAlert();
cy.get(OVERVIEW_STATUS).should('have.text', 'open');
cy.get(OVERVIEW_RULE).should('have.text', alert.rule);
cy.get(OVERVIEW_SEVERITY).contains(alert.severity, { matchCase: false });
cy.get(OVERVIEW_RISK_SCORE).should('have.text', alert.riskScore);
// TODO: Find out what this is
// cy.get(OVERVIEW_HOST_NAME).should('have.text', alert.hostName);
// TODO: Needs data-test-subj
// cy.get(OVERVIEW_THRESHOLD_COUNT).should('have.text', alert.thresholdCount);
cy.get(OVERVIEW_RULE_TYPE).should('have.text', rule.ruleType);
// TODO: Needs data-test-subj
// cy.get(OVERVIEW_THRESHOLD_VALUE).should('have.text', rule.thresholdValue);
});
});

View file

@ -1,153 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import {
ALL_CASES_CLOSED_CASES_STATS,
ALL_CASES_COMMENTS_COUNT,
ALL_CASES_IN_PROGRESS_CASES_STATS,
ALL_CASES_NAME,
ALL_CASES_NOT_PUSHED,
ALL_CASES_NUMBER_OF_ALERTS,
ALL_CASES_OPEN_CASES_STATS,
ALL_CASES_IN_PROGRESS_STATUS,
} from '../../../screens/all_cases';
import {
CASES_TAGS,
CASE_CONNECTOR,
CASE_DETAILS_PAGE_TITLE,
CASE_DETAILS_USERNAMES,
CASE_EVENT_UPDATE,
CASE_IN_PROGRESS_STATUS,
CASE_SWITCH,
CASE_USER_ACTION,
} from '../../../screens/case_details';
import { CASES_PAGE } from '../../../screens/kibana_navigation';
import { goToCaseDetails } from '../../../tasks/all_cases';
import { deleteCase } from '../../../tasks/case_details';
import {
navigateFromKibanaCollapsibleTo,
openKibanaNavigation,
} from '../../../tasks/kibana_navigation';
import { login, visitWithoutDateRange } from '../../../tasks/login';
import { importCase } from '../../../tasks/saved_objects';
import { KIBANA_SAVED_OBJECTS } from '../../../urls/navigation';
const CASE_NDJSON = '7_16_case.ndjson';
const importedCase = {
title: '7.16 case to export',
user: 'glo',
initial: 'g',
reporter: 'glo@test.co',
tags: 'export case',
numberOfAlerts: '1',
numberOfComments: '2',
description:
"This is the description of the 7.16 case that I'm going to import in future versions.",
timeline: 'This is just a timeline',
status: 'In progress',
ruleName: 'This is a test',
participants: ['test', 'elastic'],
connector: 'Jira test',
};
const updateStatusRegex = new RegExp(
`\\S${importedCase.user}marked case as${importedCase.status}\\S*\\s?(\\S*)?\\s?(\\S*)?`
);
const alertUpdateRegex = new RegExp(
`\\S${importedCase.user}added an alert from Unknown\\S*\\s?(\\S*)?\\s?(\\S*)?`
);
const incidentManagementSystemRegex = new RegExp(
`\\S${importedCase.participants[0]}selected ${importedCase.connector} as incident management system\\S*\\s?(\\S*)?\\s?(\\S*)?`
);
const DESCRIPTION = 0;
const TIMELINE = 1;
const LENS = 2;
const STATUS_UPDATE = 0;
const FIRST_ALERT_UPDATE = 1;
const SECOND_ALERT_UPDATE = 2;
const INCIDENT_MANAGEMENT_SYSTEM_UPDATE = 3;
const EXPECTED_NUMBER_OF_UPDATES = 4;
const REPORTER = 0;
describe('Import case after upgrade', () => {
before(() => {
login();
visitWithoutDateRange(KIBANA_SAVED_OBJECTS);
importCase(CASE_NDJSON);
openKibanaNavigation();
navigateFromKibanaCollapsibleTo(CASES_PAGE);
});
after(() => {
deleteCase();
});
it('Displays the correct number of opened cases on the cases page', () => {
const EXPECTED_NUMBER_OF_OPENED_CASES = '0';
cy.get(ALL_CASES_OPEN_CASES_STATS).should('have.text', EXPECTED_NUMBER_OF_OPENED_CASES);
});
it('Displays the correct number of in progress cases on the cases page', () => {
const EXPECTED_NUMBER_OF_IN_PROGRESS_CASES = '1';
cy.get(ALL_CASES_IN_PROGRESS_CASES_STATS).should(
'have.text',
EXPECTED_NUMBER_OF_IN_PROGRESS_CASES
);
});
it('Displays the correct number of closed cases on the cases page', () => {
const EXPECTED_NUMBER_OF_CLOSED_CASES = '0';
cy.get(ALL_CASES_CLOSED_CASES_STATS).should('have.text', EXPECTED_NUMBER_OF_CLOSED_CASES);
});
it('Displays the correct case details on the cases page', () => {
cy.get(ALL_CASES_NAME).should('have.text', importedCase.title);
cy.get(ALL_CASES_NUMBER_OF_ALERTS).should('have.text', importedCase.numberOfAlerts);
cy.get(ALL_CASES_COMMENTS_COUNT).should('have.text', importedCase.numberOfComments);
cy.get(ALL_CASES_NOT_PUSHED).should('be.visible');
cy.get(ALL_CASES_IN_PROGRESS_STATUS).should('be.visible');
});
it('Displays the correct case details on the case details page', () => {
goToCaseDetails();
cy.get(CASE_DETAILS_PAGE_TITLE).should('have.text', importedCase.title);
cy.get(CASE_IN_PROGRESS_STATUS).should('exist');
cy.get(CASE_SWITCH).should('have.attr', 'aria-checked', 'false');
cy.get(CASE_USER_ACTION).eq(DESCRIPTION).should('have.text', importedCase.description);
cy.get(CASE_USER_ACTION).eq(TIMELINE).should('have.text', importedCase.timeline);
cy.get(CASE_USER_ACTION).eq(LENS).should('have.text', '');
cy.get(CASE_EVENT_UPDATE).should('have.length', EXPECTED_NUMBER_OF_UPDATES);
cy.get(CASE_EVENT_UPDATE).eq(STATUS_UPDATE).invoke('text').should('match', updateStatusRegex);
cy.get(CASE_EVENT_UPDATE)
.eq(FIRST_ALERT_UPDATE)
.invoke('text')
.should('match', alertUpdateRegex);
cy.get(CASE_EVENT_UPDATE)
.eq(SECOND_ALERT_UPDATE)
.invoke('text')
.should('match', alertUpdateRegex);
cy.get(CASE_EVENT_UPDATE)
.eq(INCIDENT_MANAGEMENT_SYSTEM_UPDATE)
.invoke('text')
.should('match', incidentManagementSystemRegex);
// TODO: Needs data-test-subj
// cy.get(CASE_DETAILS_USERNAMES).should('have.length', EXPECTED_NUMBER_OF_PARTICIPANTS);
// TODO: Investigate why this changes, not reliable to verify
// cy.get(CASE_DETAILS_USERNAMES).eq(FIRST_PARTICIPANT).should('have.text', importedCase.user);
// cy.get(CASE_DETAILS_USERNAMES)
// .eq(SECOND_PARTICIPANT)
// .should('have.text', importedCase.participants[0]);
// cy.get(CASE_DETAILS_USERNAMES)
// .eq(THIRD_PARTICIPANT)
// .should('have.text', importedCase.participants[1]);
cy.get(CASE_DETAILS_USERNAMES).eq(REPORTER).should('have.text', importedCase.user);
cy.get(CASES_TAGS(importedCase.tags)).should('exist');
cy.get(CASE_CONNECTOR).should('have.text', importedCase.connector);
});
});

View file

@ -1,201 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import semver from 'semver';
import {
CORRELATION_EVENT_TABLE_CELL,
DATA_PROVIDERS,
DATE_PICKER_END,
DATE_PICKER_START,
DESTINATION_IP_KPI,
GRAPH_TAB_BUTTON,
HOST_KPI,
QUERY_TAB_BUTTON,
NOTE_DESCRIPTION,
NOTE_PREVIEW,
NOTES_TAB_BUTTON,
PINNED_TAB_BUTTON,
PROCESS_KPI,
QUERY_EVENT_TABLE_CELL,
SOURCE_IP_KPI,
TIMELINE_CORRELATION_TAB,
TIMELINE_CORRELATION_INPUT,
TIMELINE_DESCRIPTION,
TIMELINE_QUERY,
TIMELINE_TITLE,
USER_KPI,
} from '../../../screens/timeline';
import {
NOTE,
TIMELINES_USERNAME,
TIMELINE_NAME,
TIMELINES_DESCRIPTION,
TIMELINES_NOTES_COUNT,
TIMELINES_PINNED_EVENT_COUNT,
} from '../../../screens/timelines';
import { login, visitWithoutDateRange } from '../../../tasks/login';
import {
closeTimeline,
deleteTimeline,
goToCorrelationTab,
goToNotesTab,
setKibanaTimezoneToUTC,
} from '../../../tasks/timeline';
import { expandNotes, importTimeline, openTimeline } from '../../../tasks/timelines';
import { TIMELINES_URL } from '../../../urls/navigation';
const timeline = '7_15_timeline.ndjson';
const username = 'elastic';
const timelineDetails = {
dateStart: 'Oct 10, 2020 @ 22:00:00.000',
dateEnd: 'Oct 11, 2030 @ 15:13:15.851',
queryTab: 'Query4',
queryTabAlt: 'Query2',
correlationTab: 'Correlation',
analyzerTab: 'Analyzer',
notesTab: 'Notes2',
pinnedTab: 'Pinned1',
};
const detectionAlert = {
message: '—',
eventCategory: 'file',
eventAction: 'initial_scan',
hostName: 'security-solution.local',
sourceIp: '127.0.0.1',
destinationIp: '127.0.0.2',
userName: 'Security Solution',
};
const event = {
timestamp: 'Nov 4, 2021 @ 10:09:29.438',
message: '—',
eventCategory: 'file',
eventAction: 'initial_scan',
hostName: 'security-solution.local',
sourceIp: '127.0.0.1',
destinationIp: '127.0.0.2',
userName: 'Security Solution',
};
describe('Import timeline after upgrade', () => {
before(() => {
login();
visitWithoutDateRange(TIMELINES_URL);
importTimeline(timeline);
setKibanaTimezoneToUTC();
});
after(() => {
closeTimeline();
deleteTimeline();
});
it('Displays the correct timeline details on the timelines page', () => {
cy.readFile(`cypress/fixtures/${timeline}`).then((file) => {
const timelineJson = JSON.parse(file);
const regex = new RegExp(
`\\S${timelineJson.globalNotes[0].createdBy}added a note\\S*\\s?(\\S*)?\\s?(\\S*)?${timelineJson.globalNotes[0].createdBy} added a note${timelineJson.globalNotes[0].note}`
);
cy.get(TIMELINE_NAME).should('have.text', timelineJson.title);
cy.get(TIMELINES_DESCRIPTION).should('have.text', timelineJson.description);
cy.get(TIMELINES_USERNAME).should('have.text', username);
cy.get(TIMELINES_NOTES_COUNT).should('have.text', timelineJson.globalNotes.length.toString());
cy.get(TIMELINES_PINNED_EVENT_COUNT).should(
'have.text',
timelineJson.pinnedEventIds.length.toString()
);
expandNotes();
cy.get(NOTE).invoke('text').should('match', regex);
});
});
it('Displays the correct timeline details inside the query tab', () => {
let expectedQueryTab = timelineDetails.queryTab;
if (semver.lt(Cypress.env('ORIGINAL_VERSION'), '7.10.0')) {
expectedQueryTab = timelineDetails.queryTabAlt;
}
openTimeline();
cy.readFile(`cypress/fixtures/${timeline}`).then((file) => {
const timelineJson = JSON.parse(file);
cy.get(TIMELINE_TITLE).should('have.text', timelineJson.title);
cy.get(TIMELINE_DESCRIPTION).should('have.text', timelineJson.description);
cy.get(DATA_PROVIDERS).should('have.length', timelineJson.dataProviders.length.toString());
cy.get(DATA_PROVIDERS)
.invoke('text')
.then((value) => {
expect(value.replace(/"/g, '')).to.eq(timelineJson.dataProviders[0].name);
});
cy.get(PROCESS_KPI).should('contain', '0');
cy.get(USER_KPI).should('contain', '0');
cy.get(HOST_KPI).should('contain', '1');
cy.get(SOURCE_IP_KPI).should('contain', '1');
cy.get(DESTINATION_IP_KPI).should('contain', '1');
cy.get(DATE_PICKER_START).should('contain', timelineDetails.dateStart);
cy.get(DATE_PICKER_END).should('contain', timelineDetails.dateEnd);
cy.get(TIMELINE_QUERY).should(
'have.text',
timelineJson.kqlQuery.filterQuery.kuery.expression
);
cy.get(QUERY_TAB_BUTTON).should('have.text', expectedQueryTab);
cy.get(TIMELINE_CORRELATION_TAB).should('have.text', timelineDetails.correlationTab);
cy.get(GRAPH_TAB_BUTTON).should('have.text', timelineDetails.analyzerTab).and('be.disabled');
cy.get(NOTES_TAB_BUTTON).should('have.text', timelineDetails.notesTab);
cy.get(PINNED_TAB_BUTTON).should('have.text', timelineDetails.pinnedTab);
cy.get(QUERY_EVENT_TABLE_CELL).eq(1).should('contain', detectionAlert.message);
cy.get(QUERY_EVENT_TABLE_CELL).eq(2).should('contain', detectionAlert.eventCategory);
cy.get(QUERY_EVENT_TABLE_CELL).eq(3).should('contain', detectionAlert.eventAction);
cy.get(QUERY_EVENT_TABLE_CELL).eq(4).should('contain', detectionAlert.hostName);
cy.get(QUERY_EVENT_TABLE_CELL).eq(5).should('contain', detectionAlert.sourceIp);
cy.get(QUERY_EVENT_TABLE_CELL).eq(6).should('contain', detectionAlert.destinationIp);
cy.get(QUERY_EVENT_TABLE_CELL).eq(7).should('contain', detectionAlert.userName);
cy.get(QUERY_EVENT_TABLE_CELL).eq(8).should('contain', event.timestamp);
cy.get(QUERY_EVENT_TABLE_CELL).eq(9).should('contain', event.message);
cy.get(QUERY_EVENT_TABLE_CELL).eq(10).should('contain', event.eventCategory);
cy.get(QUERY_EVENT_TABLE_CELL).eq(11).should('contain', event.eventAction);
cy.get(QUERY_EVENT_TABLE_CELL).eq(12).should('contain', event.hostName);
cy.get(QUERY_EVENT_TABLE_CELL).eq(13).should('contain', event.sourceIp);
cy.get(QUERY_EVENT_TABLE_CELL).eq(14).should('contain', event.destinationIp);
cy.get(QUERY_EVENT_TABLE_CELL).eq(15).should('contain', event.userName);
});
});
it('Displays the correct timeline details inside the correlation tab', () => {
goToCorrelationTab();
cy.get(TIMELINE_CORRELATION_INPUT).should('be.empty');
cy.get(CORRELATION_EVENT_TABLE_CELL).should('not.exist');
});
it('Displays the correct timeline details inside the notes tab', () => {
goToNotesTab();
cy.readFile(`cypress/fixtures/${timeline}`).then((file) => {
const timelineJson = JSON.parse(file);
const descriptionRegex = new RegExp(
`\\S${username}added description\\S*\\s?(\\S*)?\\s?(\\S*)?${timelineJson.description}`
);
const noteRegex = new RegExp(
`\\S${timelineJson.globalNotes[0].createdBy}added a note\\S*\\s?(\\S*)?\\s?(\\S*)?${timelineJson.globalNotes[0].createdBy} added a note${timelineJson.globalNotes[0].note}`
);
cy.get(NOTE_DESCRIPTION).invoke('text').should('match', descriptionRegex);
cy.get(NOTE_PREVIEW).last().invoke('text').should('match', noteRegex);
});
});
});

View file

@ -9,16 +9,10 @@
"build-beat-doc": "node scripts/beat_docs/build.js && node ../../../scripts/eslint ../timelines/server/utils/beat_schema/fields.ts --fix",
"cypress": "../../../node_modules/.bin/cypress",
"cypress:open": "TZ=UTC node ./scripts/start_cypress_parallel open --spec './cypress/e2e/**/*.cy.ts' --config-file ./cypress/cypress.config.ts --ftr-config-file ../../../../../../x-pack/test/security_solution_cypress/cli_config",
"cypress:open:ccs": "yarn cypress:open --config specPattern=./cypress/ccs_e2e/**/*.cy.ts",
"cypress:open:upgrade": "yarn cypress:open --config specPattern=./cypress/upgrade_e2e/**/*.cy.ts",
"cypress:run": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/{,!(investigations,explore)/**/}*.cy.ts'; status=$?; yarn junit:merge && exit $status",
"cypress:run:cases": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/explore/cases/*.cy.ts' --ftr-config-file ../../../../../../x-pack/test/security_solution_cypress/cli_config; status=$?; yarn junit:merge && exit $status",
"cypress:run:firefox": "yarn cypress:run:reporter --browser firefox --spec './cypress/e2e/**/*.cy.ts'; status=$?; yarn junit:merge && exit $status",
"cypress:run:reporter": "TZ=UTC node ./scripts/start_cypress_parallel run --config-file ./cypress/cypress_ci.config.ts --ftr-config-file ../../../../../../x-pack/test/security_solution_cypress/cli_config --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json",
"cypress:run:respops": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/(detection_alerts|detection_rules|exceptions)/*.cy.ts' --ftr-config-file ../../../../../../x-pack/test/security_solution_cypress/cli_config; status=$?; yarn junit:merge && exit $status",
"cypress:run:ccs": "yarn cypress:run:reporter --browser chrome --config specPattern=./cypress/ccs_e2e/**/*.cy.ts; status=$?; yarn junit:merge && exit $status",
"cypress:run-as-ci:firefox": "node --max-old-space-size=2048 ../../../scripts/functional_tests --config ../../test/security_solution_cypress/config.firefox.ts",
"cypress:run:upgrade": "yarn cypress:run:reporter --browser chrome --config specPattern=./cypress/upgrade_e2e/**/*.cy.ts",
"cypress:dw:open": "node ./scripts/start_cypress_parallel open --config-file ./public/management/cypress.config.ts ts --ftr-config-file ../../../../../../x-pack/test/defend_workflows_cypress/cli_config",
"cypress:dw:run": "node ./scripts/start_cypress_parallel run --config-file ./public/management/cypress.config.ts --ftr-config-file ../../../../../../x-pack/test/defend_workflows_cypress/cli_config --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json; status=$?; yarn junit:merge && exit $status",
"cypress:dw:endpoint:run": "node ./scripts/start_cypress_parallel run --config-file ./public/management/cypress_endpoint.config.ts --ftr-config-file ../../../../../../x-pack/test/defend_workflows_cypress/endpoint_config --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json --concurrency 1; status=$?; yarn junit:merge && exit $status",

View file

@ -1,19 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrConfigProviderContext } from '@kbn/test';
import { SecuritySolutionCypressCcsTestRunner } from './runner';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const securitySolutionCypressConfig = await readConfigFile(require.resolve('./config.ts'));
return {
...securitySolutionCypressConfig.getAll(),
testRunner: SecuritySolutionCypressCcsTestRunner,
};
}

View file

@ -1,50 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrConfigProviderContext } from '@kbn/test';
import { CA_CERT_PATH } from '@kbn/dev-utils';
import { SecuritySolutionConfigurableCypressTestRunner } from './runner';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const kibanaCommonTestsConfig = await readConfigFile(
require.resolve('../../../test/common/config.js')
);
const xpackFunctionalTestsConfig = await readConfigFile(
require.resolve('../functional/config.base.js')
);
return {
...kibanaCommonTestsConfig.getAll(),
browser: {
type: 'firefox',
acceptInsecureCerts: true,
},
esTestCluster: {
...xpackFunctionalTestsConfig.get('esTestCluster'),
serverArgs: [
...xpackFunctionalTestsConfig.get('esTestCluster.serverArgs'),
// define custom es server here
// API Keys is enabled at the top level
'xpack.security.enabled=true',
],
},
kbnTestServer: {
...xpackFunctionalTestsConfig.get('kbnTestServer'),
serverArgs: [
...xpackFunctionalTestsConfig.get('kbnTestServer.serverArgs'),
'--csp.strict=false',
// define custom kibana server args here
`--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`,
],
},
testRunner: SecuritySolutionConfigurableCypressTestRunner,
};
}

View file

@ -5,12 +5,8 @@
* 2.0.
*/
import { resolve } from 'path';
import Url from 'url';
import { withProcRunner } from '@kbn/dev-proc-runner';
import semver from 'semver';
import { FtrProviderContext } from '../common/ftr_provider_context';
export type { FtrProviderContext } from '../common/ftr_provider_context';
@ -36,58 +32,3 @@ export async function SecuritySolutionConfigurableCypressTestRunner({
ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'),
};
}
export async function SecuritySolutionCypressCcsTestRunner({ getService }: FtrProviderContext) {
const log = getService('log');
await withProcRunner(log, async (procs) => {
await procs.run('cypress', {
cmd: 'yarn',
args: ['cypress:run:ccs'],
cwd: resolve(__dirname, '../../plugins/security_solution'),
env: {
FORCE_COLOR: '1',
CYPRESS_BASE_URL: process.env.TEST_KIBANA_URL,
CYPRESS_ELASTICSEARCH_URL: process.env.TEST_ES_URL,
CYPRESS_ELASTICSEARCH_USERNAME: process.env.ELASTICSEARCH_USERNAME,
CYPRESS_ELASTICSEARCH_PASSWORD: process.env.ELASTICSEARCH_PASSWORD,
CYPRESS_CCS_KIBANA_URL: process.env.TEST_KIBANA_URLDATA,
CYPRESS_CCS_ELASTICSEARCH_URL: process.env.TEST_ES_URLDATA,
CYPRESS_CCS_REMOTE_NAME: process.env.TEST_CCS_REMOTE_NAME,
...process.env,
},
wait: true,
});
});
}
export async function SecuritySolutionCypressUpgradeCliTestRunner({
getService,
}: FtrProviderContext) {
const log = getService('log');
let command = '';
if (semver.gt(process.env.ORIGINAL_VERSION!, '7.10.0')) {
command = 'cypress:run:upgrade';
} else {
command = 'cypress:run:upgrade:old';
}
await withProcRunner(log, async (procs) => {
await procs.run('cypress', {
cmd: 'yarn',
args: [command],
cwd: resolve(__dirname, '../../plugins/security_solution'),
env: {
FORCE_COLOR: '1',
CYPRESS_BASE_URL: process.env.TEST_KIBANA_URL,
CYPRESS_ELASTICSEARCH_URL: process.env.TEST_ES_URL,
CYPRESS_ELASTICSEARCH_USERNAME: process.env.TEST_ES_USER,
CYPRESS_ELASTICSEARCH_PASSWORD: process.env.TEST_ES_PASS,
CYPRESS_ORIGINAL_VERSION: process.env.ORIGINAL_VERSION,
...process.env,
},
wait: true,
});
});
}

View file

@ -1,21 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrConfigProviderContext } from '@kbn/test';
import { SecuritySolutionCypressUpgradeCliTestRunner } from './runner';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const kibanaCommonTestsConfig = await readConfigFile(
require.resolve('../../../test/common/config.js')
);
return {
...kibanaCommonTestsConfig.getAll(),
testRunner: SecuritySolutionCypressUpgradeCliTestRunner,
};
}