mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[Threat Intelligence] Switch to parallel cypress (#158801)
This pull request introduces parallel functionality to the TI Cypress tests, which was recently implemented in the Security Solution. In essence, this allows us to run multiple test files simultaneously, each within its own Kibana/ES environment. The PR is here https://github.com/elastic/kibana/pull/157387 The changes in the scope of the TI Cypress e2es include: - Modified `package.json` scripts; `:run` is now being used both locally and in CI. Note that Firefox is currently not supported. - Removed all `{testIsolation: false}` flags, as no test should depend on non-pure state. - All actions required to set up the test environment (archiver, login) have been moved to beforeEach blocks to ensure that each test starts with a fresh state. - Introduced ESLint configuration to help us keep up with the best practices when writing tests. TODO: - The `timeline.cy.ts` test is flaky and requires refactoring. There are too many actions being fired against elements that are not visible to the user (`{force: true}`). I've added some waits to address race conditions in the UI, but this should be considered a temporary solution. --------- Co-authored-by: Patryk Kopyciński <contact@patrykkopycinski.com> Co-authored-by: PhilippeOberti <philippe.oberti@elastic.co> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
3aa1b34394
commit
627b3547a1
30 changed files with 398 additions and 660 deletions
|
@ -43,7 +43,6 @@ disabled:
|
|||
- x-pack/test/security_solution_cypress/config.ts
|
||||
- x-pack/test/security_solution_cypress/response_ops_cli_config.ts
|
||||
- x-pack/test/security_solution_cypress/upgrade_config.ts
|
||||
- x-pack/test/threat_intelligence_cypress/visual_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
|
||||
|
|
|
@ -5,7 +5,7 @@ steps:
|
|||
queue: n2-4-spot
|
||||
depends_on: build
|
||||
timeout_in_minutes: 120
|
||||
parallelism: 4
|
||||
parallelism: 2
|
||||
retry:
|
||||
automatic:
|
||||
- exit_status: '-1'
|
||||
|
|
|
@ -5,12 +5,12 @@ set -euo pipefail
|
|||
source .buildkite/scripts/steps/functional/common.sh
|
||||
|
||||
export JOB=kibana-threat-intelligence-chrome
|
||||
export CLI_NUMBER=${CLI_NUMBER:-$((BUILDKITE_PARALLEL_JOB+1))}
|
||||
export CLI_COUNT=${CLI_COUNT:-$BUILDKITE_PARALLEL_JOB_COUNT}
|
||||
export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION}
|
||||
|
||||
Xvfb :99 -screen 0 1600x1200x24 &
|
||||
|
||||
export DISPLAY=:99
|
||||
|
||||
echo "--- Threat Intelligence tests (Chrome)"
|
||||
|
||||
node scripts/functional_tests \
|
||||
--debug --bail \
|
||||
--kibana-install-dir "$KIBANA_BUILD_LOCATION" \
|
||||
--config x-pack/test/threat_intelligence_cypress/cli_config_parallel.ts
|
||||
yarn --cwd x-pack/plugins/threat_intelligence cypress:run
|
||||
|
|
13
x-pack/plugins/threat_intelligence/cypress/.eslintrc.json
Normal file
13
x-pack/plugins/threat_intelligence/cypress/.eslintrc.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"plugins": ["cypress"],
|
||||
"extends": [
|
||||
"plugin:cypress/recommended"
|
||||
],
|
||||
"env": {
|
||||
"cypress/globals": true
|
||||
},
|
||||
"rules": {
|
||||
"cypress/no-force": "warn",
|
||||
"import/no-extraneous-dependencies": "off"
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ export default defineCypressConfig({
|
|||
execTimeout: 120000,
|
||||
pageLoadTimeout: 120000,
|
||||
retries: {
|
||||
runMode: 2,
|
||||
runMode: 1,
|
||||
},
|
||||
screenshotsFolder: '../../../target/kibana-threat-intelligence/cypress/screenshots',
|
||||
trashAssetsBeforeRuns: false,
|
||||
|
@ -44,5 +44,7 @@ export default defineCypressConfig({
|
|||
},
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:5601',
|
||||
experimentalMemoryManagement: true,
|
||||
specPattern: './cypress/e2e/**/*.cy.ts',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -7,20 +7,19 @@
|
|||
|
||||
import {
|
||||
closeFlyout,
|
||||
navigateToThreatIntelligence,
|
||||
openFlyout,
|
||||
openFlyoutTakeAction,
|
||||
openIndicatorsTableMoreActions,
|
||||
} from '../tasks/common';
|
||||
import {
|
||||
deleteBlocklistEntry,
|
||||
fillBlocklistForm,
|
||||
openAddToBlockListFlyoutFromTable,
|
||||
openAddToBlocklistFromFlyout,
|
||||
} from '../tasks/blocklist';
|
||||
import { navigateToBlocklist, navigateToThreatIntelligence } from '../tasks/common';
|
||||
import { login } from '../tasks/login';
|
||||
import { navigateToBlocklist } from '../tasks/common';
|
||||
import { login, visit } from '../tasks/login';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
import { selectRange } from '../tasks/select_range';
|
||||
import {
|
||||
BLOCK_LIST_VALUE_INPUT,
|
||||
FLYOUT_ADD_TO_BLOCK_LIST_ITEM,
|
||||
|
@ -31,88 +30,76 @@ import {
|
|||
|
||||
const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators';
|
||||
|
||||
const BLOCK_LIST_NEW_NAME = 'new blocklist entry';
|
||||
const BLOCK_LIST_NEW_DESCRIPTION = 'the best description';
|
||||
const FIRST_BLOCK_LIST_NEW_NAME = 'first blocklist entry';
|
||||
const FIRST_BLOCK_LIST_NEW_DESCRIPTION = 'the first description';
|
||||
const SECOND_BLOCK_LIST_NEW_NAME = 'second blocklist entry';
|
||||
const SECOND_BLOCK_LIST_NEW_DESCRIPTION = 'the second description';
|
||||
|
||||
describe('Block list with invalid indicators', { testIsolation: false }, () => {
|
||||
before(() => {
|
||||
describe('Block list with invalid indicators', () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/invalid_indicators_data');
|
||||
login();
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/invalid_indicators_data');
|
||||
});
|
||||
|
||||
it('should disabled the indicators table context menu item if invalid indicator', () => {
|
||||
it('should disabled blocklist in the indicators table context menu item and flyout context menu items', () => {
|
||||
openIndicatorsTableMoreActions(3);
|
||||
cy.get(INDICATORS_TABLE_ADD_TO_BLOCK_LIST_BUTTON_ICON).should('be.disabled');
|
||||
});
|
||||
|
||||
it('should disable the flyout context menu items if invalid indicator', () => {
|
||||
openFlyout(3);
|
||||
openFlyoutTakeAction();
|
||||
cy.get(FLYOUT_ADD_TO_BLOCK_LIST_ITEM).should('be.disabled');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Block list interactions', { testIsolation: false }, () => {
|
||||
before(() => {
|
||||
describe('Block list interactions', () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/indicators_data');
|
||||
login();
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/indicators_data');
|
||||
});
|
||||
|
||||
it('should add to block list from the indicators table', () => {
|
||||
openIndicatorsTableMoreActions(0);
|
||||
openAddToBlockListFlyoutFromTable();
|
||||
fillBlocklistForm(BLOCK_LIST_NEW_NAME, BLOCK_LIST_NEW_DESCRIPTION);
|
||||
navigateToBlocklist();
|
||||
|
||||
cy.get(SAVED_BLOCK_LIST_NAME).should('have.text', BLOCK_LIST_NEW_NAME);
|
||||
cy.get(SAVED_BLOCK_LIST_DESCRIPTION).should('have.text', BLOCK_LIST_NEW_DESCRIPTION);
|
||||
|
||||
deleteBlocklistEntry();
|
||||
navigateToThreatIntelligence();
|
||||
});
|
||||
|
||||
it('should add to block list from the indicator flyout', () => {
|
||||
openFlyout(0);
|
||||
openFlyoutTakeAction();
|
||||
openAddToBlocklistFromFlyout();
|
||||
fillBlocklistForm(BLOCK_LIST_NEW_NAME, BLOCK_LIST_NEW_DESCRIPTION);
|
||||
closeFlyout();
|
||||
navigateToBlocklist();
|
||||
|
||||
cy.get(SAVED_BLOCK_LIST_NAME).should('have.text', BLOCK_LIST_NEW_NAME);
|
||||
cy.get(SAVED_BLOCK_LIST_DESCRIPTION).should('have.text', BLOCK_LIST_NEW_DESCRIPTION);
|
||||
|
||||
deleteBlocklistEntry();
|
||||
navigateToThreatIntelligence();
|
||||
});
|
||||
|
||||
it('add to blocklist flyout should have the correct IoC id', () => {
|
||||
it('should add to block list from the indicators table and from flyout', () => {
|
||||
// first indicator is a valid indicator for add to blocklist feature
|
||||
const firstIndicatorId = 'd86e656455f985357df3063dff6637f7f3b95bb27d1769a6b88c7adecaf7763f';
|
||||
openIndicatorsTableMoreActions(0);
|
||||
openAddToBlockListFlyoutFromTable();
|
||||
|
||||
cy.get(BLOCK_LIST_VALUE_INPUT(firstIndicatorId)).should('exist');
|
||||
cy.get(BLOCK_LIST_VALUE_INPUT(firstIndicatorId));
|
||||
|
||||
closeFlyout();
|
||||
fillBlocklistForm(FIRST_BLOCK_LIST_NEW_NAME, FIRST_BLOCK_LIST_NEW_DESCRIPTION);
|
||||
navigateToBlocklist();
|
||||
|
||||
cy.get(SAVED_BLOCK_LIST_NAME).eq(0).should('have.text', FIRST_BLOCK_LIST_NEW_NAME);
|
||||
cy.get(SAVED_BLOCK_LIST_DESCRIPTION)
|
||||
.eq(0)
|
||||
.should('have.text', FIRST_BLOCK_LIST_NEW_DESCRIPTION);
|
||||
|
||||
navigateToThreatIntelligence();
|
||||
|
||||
// second indicator is a valid indicator for add to blocklist feature
|
||||
const secondIndicatorId = 'd3e2cf87eabf84ef929aaf8dad1431b3387f5a26de8ffb7a0c3c2a13f973c0ab';
|
||||
openIndicatorsTableMoreActions(1);
|
||||
openAddToBlockListFlyoutFromTable();
|
||||
openFlyout(1);
|
||||
openFlyoutTakeAction();
|
||||
openAddToBlocklistFromFlyout();
|
||||
|
||||
cy.get(BLOCK_LIST_VALUE_INPUT(secondIndicatorId)).should('exist');
|
||||
cy.get(BLOCK_LIST_VALUE_INPUT(secondIndicatorId));
|
||||
|
||||
fillBlocklistForm(SECOND_BLOCK_LIST_NEW_NAME, SECOND_BLOCK_LIST_NEW_DESCRIPTION);
|
||||
closeFlyout();
|
||||
navigateToBlocklist();
|
||||
|
||||
cy.get(SAVED_BLOCK_LIST_NAME).eq(0).should('have.text', SECOND_BLOCK_LIST_NEW_NAME);
|
||||
cy.get(SAVED_BLOCK_LIST_DESCRIPTION)
|
||||
.eq(0)
|
||||
.should('have.text', SECOND_BLOCK_LIST_NEW_DESCRIPTION);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,16 +6,13 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
navigateToCases,
|
||||
navigateToThreatIntelligence,
|
||||
openFlyout,
|
||||
openFlyoutTakeAction,
|
||||
openIndicatorsTableMoreActions,
|
||||
} from '../tasks/common';
|
||||
import {
|
||||
createNewCaseFromCases,
|
||||
createNewCaseFromTI,
|
||||
deleteCase,
|
||||
navigateToCaseViaToaster,
|
||||
openAddToExistingCaseFlyoutFromTable,
|
||||
openAddToExistingCaseFromFlyout,
|
||||
|
@ -30,34 +27,29 @@ import {
|
|||
INDICATORS_TABLE_ADD_TO_EXISTING_CASE_BUTTON_ICON,
|
||||
INDICATORS_TABLE_ADD_TO_NEW_CASE_BUTTON_ICON,
|
||||
} from '../screens/cases';
|
||||
import { login } from '../tasks/login';
|
||||
import { login, visit } from '../tasks/login';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
import { selectRange } from '../tasks/select_range';
|
||||
|
||||
const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators';
|
||||
|
||||
describe('Cases with invalid indicators', { testIsolation: false }, () => {
|
||||
before(() => {
|
||||
describe('Cases with invalid indicators', () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/invalid_indicators_data');
|
||||
login();
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/invalid_indicators_data');
|
||||
});
|
||||
|
||||
it('should disable the indicators table context menu items if invalid indicator', () => {
|
||||
it('should disable the indicators table context menu items and flyout context menu items', () => {
|
||||
const documentsNumber = 22;
|
||||
openIndicatorsTableMoreActions(documentsNumber - 1);
|
||||
|
||||
cy.get(INDICATORS_TABLE_ADD_TO_EXISTING_CASE_BUTTON_ICON).should('be.disabled');
|
||||
cy.get(INDICATORS_TABLE_ADD_TO_NEW_CASE_BUTTON_ICON).should('be.disabled');
|
||||
});
|
||||
|
||||
it('should disable the flyout context menu items if invalid indicator', () => {
|
||||
const documentsNumber = 22;
|
||||
openFlyout(documentsNumber - 1);
|
||||
openFlyoutTakeAction();
|
||||
|
||||
|
@ -66,24 +58,36 @@ describe('Cases with invalid indicators', { testIsolation: false }, () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Cases interactions', { testIsolation: false }, () => {
|
||||
before(() => {
|
||||
describe('Cases interactions', () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/indicators_data');
|
||||
login();
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/indicators_data');
|
||||
});
|
||||
|
||||
it('should add to existing case when clicking on the button in the indicators table', () => {
|
||||
navigateToCases();
|
||||
createNewCaseFromCases();
|
||||
it('should add to new case and to existing case from the indicators table and the flyout', () => {
|
||||
cy.log('should add to new case when clicking on the button in the indicators table');
|
||||
|
||||
openIndicatorsTableMoreActions(0);
|
||||
openAddToNewCaseFlyoutFromTable();
|
||||
createNewCaseFromTI();
|
||||
navigateToCaseViaToaster();
|
||||
|
||||
cy.get(CASE_COMMENT_EXTERNAL_REFERENCE)
|
||||
.should('exist')
|
||||
.and('contain.text', 'added an indicator of compromise')
|
||||
.and('contain.text', 'Indicator name')
|
||||
.and('contain.text', 'Indicator type')
|
||||
.and('contain.text', 'Feed name');
|
||||
|
||||
navigateToThreatIntelligence();
|
||||
|
||||
cy.log('should add to existing case when clicking on the button in the indicators table');
|
||||
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
openIndicatorsTableMoreActions(0);
|
||||
openAddToExistingCaseFlyoutFromTable();
|
||||
selectExistingCase();
|
||||
|
@ -96,51 +100,10 @@ describe('Cases interactions', { testIsolation: false }, () => {
|
|||
.and('contain.text', 'Indicator type')
|
||||
.and('contain.text', 'Feed name');
|
||||
|
||||
deleteCase();
|
||||
navigateToThreatIntelligence();
|
||||
});
|
||||
|
||||
it('should add to new case when clicking on the button in the indicators table', () => {
|
||||
openIndicatorsTableMoreActions(0);
|
||||
openAddToNewCaseFlyoutFromTable();
|
||||
createNewCaseFromTI();
|
||||
cy.log('should add to new case when clicking on the button in the indicators flyout');
|
||||
|
||||
navigateToCaseViaToaster();
|
||||
cy.get(CASE_COMMENT_EXTERNAL_REFERENCE)
|
||||
.should('exist')
|
||||
.and('contain.text', 'added an indicator of compromise')
|
||||
.and('contain.text', 'Indicator name')
|
||||
.and('contain.text', 'Indicator type')
|
||||
.and('contain.text', 'Feed name');
|
||||
|
||||
deleteCase();
|
||||
navigateToThreatIntelligence();
|
||||
});
|
||||
|
||||
it('should add to existing case when clicking on the button in the indicators flyout', () => {
|
||||
navigateToCases();
|
||||
createNewCaseFromCases();
|
||||
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
openFlyout(0);
|
||||
openFlyoutTakeAction();
|
||||
openAddToExistingCaseFromFlyout();
|
||||
selectExistingCase();
|
||||
|
||||
navigateToCaseViaToaster();
|
||||
cy.get(CASE_COMMENT_EXTERNAL_REFERENCE)
|
||||
.should('exist')
|
||||
.and('contain.text', 'added an indicator of compromise')
|
||||
.and('contain.text', 'Indicator name')
|
||||
.and('contain.text', 'Indicator type')
|
||||
.and('contain.text', 'Feed name');
|
||||
|
||||
deleteCase();
|
||||
navigateToThreatIntelligence();
|
||||
});
|
||||
|
||||
it('should add to new case when clicking on the button in the indicators flyout', () => {
|
||||
openFlyout(0);
|
||||
openFlyoutTakeAction();
|
||||
openAddToNewCaseFromFlyout();
|
||||
|
@ -154,7 +117,21 @@ describe('Cases interactions', { testIsolation: false }, () => {
|
|||
.and('contain.text', 'Indicator type')
|
||||
.and('contain.text', 'Feed name');
|
||||
|
||||
deleteCase();
|
||||
navigateToThreatIntelligence();
|
||||
|
||||
cy.log('should add to existing case when clicking on the button in the indicators flyout');
|
||||
|
||||
openFlyout(0);
|
||||
openFlyoutTakeAction();
|
||||
openAddToExistingCaseFromFlyout();
|
||||
selectExistingCase();
|
||||
|
||||
navigateToCaseViaToaster();
|
||||
cy.get(CASE_COMMENT_EXTERNAL_REFERENCE)
|
||||
.should('exist')
|
||||
.and('contain.text', 'added an indicator of compromise')
|
||||
.and('contain.text', 'Indicator name')
|
||||
.and('contain.text', 'Indicator type')
|
||||
.and('contain.text', 'Feed name');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { login } from '../tasks/login';
|
||||
import { login, visit } from '../tasks/login';
|
||||
import {
|
||||
EMPTY_PAGE_BODY,
|
||||
EMPTY_PAGE_DOCS_LINK,
|
||||
|
@ -14,19 +14,17 @@ import {
|
|||
|
||||
const THREAT_INTEL_PATH = '/app/security/threat_intelligence/';
|
||||
|
||||
describe('Empty Page', { testIsolation: false }, () => {
|
||||
before(() => {
|
||||
describe('Empty Page', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
cy.visit(THREAT_INTEL_PATH);
|
||||
visit(THREAT_INTEL_PATH);
|
||||
});
|
||||
|
||||
it('should render the empty page with link to docs and integrations', () => {
|
||||
it('should render the empty page with link to docs and integrations, and navigate to integrations page', () => {
|
||||
cy.get(EMPTY_PAGE_BODY).should('be.visible');
|
||||
cy.get(EMPTY_PAGE_DOCS_LINK).should('be.visible');
|
||||
cy.get(EMPTY_PAGE_INTEGRATIONS_LINK).should('be.visible');
|
||||
});
|
||||
|
||||
it('should navigate to the integrations page', () => {
|
||||
cy.get(EMPTY_PAGE_INTEGRATIONS_LINK).click();
|
||||
cy.url().should('include', '/app/integrations/browse/threat_intel');
|
||||
cy.get('h1').first().should('contain', 'Integrations');
|
||||
|
|
|
@ -41,9 +41,8 @@ import {
|
|||
TIME_RANGE_PICKER,
|
||||
REFRESH_BUTTON,
|
||||
} from '../screens/indicators';
|
||||
import { login } from '../tasks/login';
|
||||
import { login, visit, waitForPageToBeLoaded } from '../tasks/login';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
import { selectRange } from '../tasks/select_range';
|
||||
import {
|
||||
closeFlyout,
|
||||
navigateToFlyoutJsonTab,
|
||||
|
@ -58,15 +57,11 @@ const URL_WITH_CONTRADICTORY_FILTERS =
|
|||
'/app/security/threat_intelligence/indicators?indicators=(filterQuery:(language:kuery,query:%27%27),filters:!((%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,index:%27%27,key:threat.indicator.type,negate:!f,params:(query:file),type:phrase),query:(match_phrase:(threat.indicator.type:file))),(%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,index:%27%27,key:threat.indicator.type,negate:!f,params:(query:url),type:phrase),query:(match_phrase:(threat.indicator.type:url)))),timeRange:(from:now/d,to:now/d))';
|
||||
|
||||
describe('Invalid Indicators', () => {
|
||||
before(() => {
|
||||
login();
|
||||
});
|
||||
|
||||
describe('verify the grid loads even with missing fields', () => {
|
||||
before(() => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/invalid_indicators_data');
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
|
@ -114,10 +109,10 @@ describe('Invalid Indicators', () => {
|
|||
});
|
||||
|
||||
describe('verify the grid loads even with missing mappings and missing fields', () => {
|
||||
before(() => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/missing_mappings_indicators_data');
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
|
@ -140,7 +135,6 @@ describe('Invalid Indicators', () => {
|
|||
describe('Indicators', () => {
|
||||
before(() => {
|
||||
esArchiverLoad('threat_intelligence/indicators_data');
|
||||
login();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
|
@ -148,6 +142,11 @@ describe('Indicators', () => {
|
|||
});
|
||||
|
||||
describe('Indicators page loading', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
it('verify the fleet plugin integrations endpoint exists', () => {
|
||||
cy.request({
|
||||
method: 'GET',
|
||||
|
@ -156,10 +155,10 @@ describe('Indicators', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Indicators page basics', { testIsolation: false }, () => {
|
||||
before(() => {
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
describe('Indicators page basics', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
it('should render the basic page elements', () => {
|
||||
|
@ -184,11 +183,8 @@ describe('Indicators', () => {
|
|||
cy.get(`${FILTERS_GLOBAL_CONTAINER} ${TIME_RANGE_PICKER}`).should('exist');
|
||||
|
||||
cy.get(`${FIELD_SELECTOR}`).should('exist');
|
||||
});
|
||||
|
||||
it('should show the indicator flyout on ioc click', () => {
|
||||
// Just to know that the data is loaded. This will be replaced with some better mechanism.
|
||||
cy.get(TABLE_CONTROLS).should('contain.text', 'Showing 1-25 of');
|
||||
cy.log('should show the indicator flyout on ioc click');
|
||||
|
||||
openFlyout(1);
|
||||
|
||||
|
@ -208,13 +204,15 @@ describe('Indicators', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Indicator page search', { testIsolation: false }, () => {
|
||||
before(() => {
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
describe('Indicator page search', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
it('should narrow the results to url indicators when respective KQL search is executed', () => {
|
||||
it('should handle all search actions', () => {
|
||||
cy.log('should narrow the results to url indicators when respective KQL search is executed');
|
||||
|
||||
enterQuery('threat.indicator.type: "url"{enter}');
|
||||
|
||||
// Check if query results are narrowed after search
|
||||
|
@ -226,47 +224,45 @@ describe('Indicators', () => {
|
|||
cy.get(INDICATOR_TYPE_CELL).should('not.contain.text', 'url');
|
||||
|
||||
clearQuery();
|
||||
});
|
||||
|
||||
it('should go to the 2nd page', () => {
|
||||
cy.log('should go to the 2nd page');
|
||||
|
||||
navigateToIndicatorsTablePage(1);
|
||||
|
||||
cy.get(TABLE_CONTROLS).should('contain.text', 'Showing 26-50 of');
|
||||
});
|
||||
|
||||
it('should go to page 1 when search input is cleared', () => {
|
||||
cy.get(QUERY_INPUT).should('exist').focus().clear().type('{enter}');
|
||||
cy.log('should go to page 1 when search input is cleared');
|
||||
cy.get(QUERY_INPUT).should('exist').focus();
|
||||
cy.get(QUERY_INPUT).clear();
|
||||
cy.get(QUERY_INPUT).type('{enter}');
|
||||
|
||||
cy.get(TABLE_CONTROLS).should('contain.text', 'Showing 1-25 of');
|
||||
});
|
||||
|
||||
it('should reload the data when refresh button is pressed', () => {
|
||||
cy.log('should reload the data when refresh button is pressed');
|
||||
cy.intercept(/bsearch/).as('search');
|
||||
|
||||
cy.get(REFRESH_BUTTON).should('exist').click();
|
||||
|
||||
cy.wait('@search');
|
||||
});
|
||||
});
|
||||
|
||||
cy.get(REFRESH_BUTTON).should('exist').click();
|
||||
|
||||
cy.wait('@search');
|
||||
describe('No items match search criteria', () => {
|
||||
beforeEach(() => {
|
||||
login();
|
||||
cy.visit(URL_WITH_CONTRADICTORY_FILTERS);
|
||||
waitForPageToBeLoaded();
|
||||
});
|
||||
|
||||
describe('No items match search criteria', () => {
|
||||
before(() => {
|
||||
// Contradictory filter set
|
||||
cy.visit(URL_WITH_CONTRADICTORY_FILTERS);
|
||||
selectRange();
|
||||
});
|
||||
it('should handle no match search criterie', () => {
|
||||
cy.log('not display the table when contradictory filters are set');
|
||||
|
||||
it('should not display the table when contradictory filters are set', () => {
|
||||
cy.get(FLYOUT_TABLE).should('not.exist');
|
||||
cy.get(FLYOUT_TABLE).should('not.exist');
|
||||
|
||||
cy.get(EMPTY_STATE).should('exist').and('contain.text', 'No results');
|
||||
});
|
||||
});
|
||||
cy.get(EMPTY_STATE).should('exist').and('contain.text', 'No results');
|
||||
|
||||
cy.log('have the default selected field, then update when user selects');
|
||||
|
||||
it('should have the default selected field, then update when user selects', () => {
|
||||
const threatFeedName = 'threat.feed.name';
|
||||
cy.get(`${FIELD_SELECTOR_INPUT}`).eq(0).should('have.text', threatFeedName);
|
||||
|
||||
|
@ -279,14 +275,15 @@ describe('Indicators', () => {
|
|||
});
|
||||
|
||||
describe('Field browser', () => {
|
||||
before(() => {
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
describe('when field browser is triggered', () => {
|
||||
it('should render proper modal window', () => {
|
||||
cy.get(FIELD_BROWSER).last().click({ force: true });
|
||||
cy.get('[data-test-subj="tiIndicatorsTable"]').within(() => {
|
||||
cy.get(FIELD_BROWSER).last().click();
|
||||
});
|
||||
|
||||
cy.get(FIELD_BROWSER_MODAL).should('be.visible');
|
||||
});
|
||||
|
@ -294,32 +291,28 @@ describe('Indicators', () => {
|
|||
});
|
||||
|
||||
describe('Request inspector', () => {
|
||||
before(() => {
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
describe('when inspector button is clicked', () => {
|
||||
it('should render the inspector flyout', () => {
|
||||
cy.get(INSPECTOR_BUTTON).last().click({ force: true });
|
||||
it('when inspector button is clicked it should render the inspector flyout', () => {
|
||||
cy.get(INSPECTOR_BUTTON).last().click();
|
||||
|
||||
cy.get(INSPECTOR_PANEL).contains('Indicators search requests');
|
||||
});
|
||||
cy.get(INSPECTOR_PANEL).contains('Indicators search requests');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Add integrations', () => {
|
||||
before(() => {
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
beforeEach(() => {
|
||||
login();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
describe('when the global header add integrations button is clicked', () => {
|
||||
it('should navigate to the Integrations page with Threat Intelligence category selected', () => {
|
||||
cy.get(ADD_INTEGRATIONS_BUTTON).click();
|
||||
it('when the global header add integrations button is clicked it should navigate to the Integrations page with Threat Intelligence category selected', () => {
|
||||
cy.get(ADD_INTEGRATIONS_BUTTON).click();
|
||||
|
||||
cy.url().should('include', 'threat_intel');
|
||||
});
|
||||
cy.url().should('include', 'threat_intel');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import {
|
||||
closeFlyout,
|
||||
navigateToFlyoutTableTab,
|
||||
openBarchartPopoverMenu,
|
||||
openFlyout,
|
||||
waitForViewToBeUpdated,
|
||||
} from '../tasks/common';
|
||||
|
@ -27,152 +26,163 @@ import {
|
|||
} from '../tasks/query_bar';
|
||||
import { INDICATOR_TYPE_CELL } from '../screens/indicators';
|
||||
import { KQL_FILTER } from '../screens/query_bar';
|
||||
import { selectRange } from '../tasks/select_range';
|
||||
import { login } from '../tasks/login';
|
||||
import { login, visit } from '../tasks/login';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
|
||||
const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators';
|
||||
|
||||
describe('Indicators query bar interaction', { testIsolation: false }, () => {
|
||||
before(() => {
|
||||
describe('Indicators query bar interaction', () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/indicators_data');
|
||||
login();
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
after(() => {
|
||||
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/indicators_data');
|
||||
});
|
||||
|
||||
it('should add filter to kql and filter in values when clicking in the barchart legend', () => {
|
||||
it('should add filter to kql', () => {
|
||||
cy.log('filter in values when clicking in the barchart legend');
|
||||
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openBarchartPopoverMenu();
|
||||
filterInFromBarChartLegend();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
});
|
||||
|
||||
it('should add negated filter to kql and filter out values when clicking in the barchart legend', () => {
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter out values when clicking in the barchart legend');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openBarchartPopoverMenu();
|
||||
filterOutFromBarChartLegend();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
});
|
||||
|
||||
it('should add filter to kql and filter in and out values when clicking in an indicators table cell', () => {
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter in values when clicking in an indicators table cell');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
filterInFromTableCell();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
});
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter out and out values when clicking in an indicators table cell');
|
||||
|
||||
it('should add negated filter and filter out and out values when clicking in an indicators table cell', () => {
|
||||
waitForViewToBeUpdated();
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
filterOutFromTableCell();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
});
|
||||
|
||||
it('should add filter to kql and filter in values when clicking in an indicators flyout overview tab block', () => {
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter in values when clicking in an indicators flyout overview tab block');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
filterInFromFlyoutBlockItem();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
});
|
||||
|
||||
it('should add negated filter to kql filter out values when clicking in an indicators flyout overview block', () => {
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter out values when clicking in an indicators flyout overview block');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
filterOutFromFlyoutBlockItem();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
});
|
||||
|
||||
it('should add filter to kql and filter in values when clicking in an indicators flyout overview tab table row', () => {
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter in values when clicking in an indicators flyout overview tab table row');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
filterInFromFlyoutOverviewTable();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
});
|
||||
|
||||
it('should add negated filter to kql filter out values when clicking in an indicators flyout overview tab row', () => {
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter out values when clicking in an indicators flyout overview tab row');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
filterOutFromFlyoutOverviewTable();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
});
|
||||
|
||||
it('should add filter to kql and filter in values when clicking in an indicators flyout table tab action column', () => {
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter in values when clicking in an indicators flyout table tab action column');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
navigateToFlyoutTableTab();
|
||||
filterInFromFlyoutTableTab();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
clearKQLBar();
|
||||
});
|
||||
|
||||
it('should add negated filter to kql filter out values when clicking in an indicators flyout table tab action column', () => {
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.log('filter out values when clicking in an indicators flyout table tab action column');
|
||||
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
||||
openFlyout(0);
|
||||
navigateToFlyoutTableTab();
|
||||
filterOutFromFlyoutTableTab();
|
||||
closeFlyout();
|
||||
waitForViewToBeUpdated();
|
||||
|
||||
cy.get(KQL_FILTER).should('exist');
|
||||
cy.get(INDICATOR_TYPE_CELL).its('length').should('be.gte', 0);
|
||||
|
|
|
@ -15,87 +15,101 @@ import {
|
|||
investigateInTimelineFromTable,
|
||||
openTimeline,
|
||||
} from '../tasks/timeline';
|
||||
import { closeFlyout, openFlyout, openFlyoutTakeAction } from '../tasks/common';
|
||||
import {
|
||||
closeFlyout,
|
||||
openBarchartPopoverMenu,
|
||||
openFlyout,
|
||||
openFlyoutTakeAction,
|
||||
} from '../tasks/common';
|
||||
import { TIMELINE_DRAGGABLE_ITEM } from '../screens/timeline';
|
||||
TIMELINE_AND_OR_BADGE,
|
||||
TIMELINE_DATA_PROVIDERS_WRAPPER,
|
||||
TIMELINE_DRAGGABLE_ITEM,
|
||||
} from '../screens/timeline';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
import { login } from '../tasks/login';
|
||||
import { selectRange } from '../tasks/select_range';
|
||||
import { login, visit } from '../tasks/login';
|
||||
|
||||
const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators';
|
||||
|
||||
describe('Timeline', { testIsolation: false }, () => {
|
||||
before(() => {
|
||||
describe('Timeline', () => {
|
||||
beforeEach(() => {
|
||||
esArchiverLoad('threat_intelligence/indicators_data');
|
||||
login();
|
||||
cy.visit(THREAT_INTELLIGENCE);
|
||||
selectRange();
|
||||
visit(THREAT_INTELLIGENCE);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
afterEach(() => {
|
||||
esArchiverUnload('threat_intelligence/indicators_data');
|
||||
});
|
||||
|
||||
it('should add entry in timeline when clicking in the barchart legend', () => {
|
||||
openBarchartPopoverMenu();
|
||||
it('should verify add to timeline and investigate in timeline work from various places', () => {
|
||||
cy.log('add to timeline when clicking in the barchart legend');
|
||||
|
||||
addToTimelineFromBarchartLegend();
|
||||
openTimeline();
|
||||
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 3);
|
||||
});
|
||||
|
||||
closeTimeline();
|
||||
});
|
||||
|
||||
it('should add entry in timeline when clicking in an indicator table cell', () => {
|
||||
addToTimelineFromTableCell();
|
||||
openTimeline();
|
||||
cy.log('add to timeline when clicking in an indicator flyout overview tab table row');
|
||||
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
|
||||
closeTimeline();
|
||||
});
|
||||
|
||||
it('should add entry in timeline when clicking in an indicator flyout overview tab table row', () => {
|
||||
openFlyout(0);
|
||||
addToTimelineFromFlyoutOverviewTabTable();
|
||||
closeFlyout();
|
||||
openTimeline();
|
||||
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 5);
|
||||
});
|
||||
|
||||
closeTimeline();
|
||||
});
|
||||
|
||||
it('should add entry in timeline when clicking in an indicator flyout overview block', () => {
|
||||
cy.log('add to timeline when clicking in an indicator flyout overview block');
|
||||
|
||||
openFlyout(0);
|
||||
addToTimelineFromFlyoutOverviewTabBlock();
|
||||
closeFlyout();
|
||||
openTimeline();
|
||||
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 7);
|
||||
});
|
||||
|
||||
closeTimeline();
|
||||
});
|
||||
|
||||
it('should investigate in timeline when clicking in an indicator table action row', () => {
|
||||
cy.log('add to timeline when clicking in an indicator table cell');
|
||||
|
||||
addToTimelineFromTableCell();
|
||||
openTimeline();
|
||||
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 9);
|
||||
});
|
||||
|
||||
closeTimeline();
|
||||
|
||||
cy.log('investigate in timeline when clicking in an indicator table action row');
|
||||
|
||||
investigateInTimelineFromTable();
|
||||
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 5);
|
||||
});
|
||||
|
||||
closeTimeline();
|
||||
});
|
||||
|
||||
it('should investigate in timeline when clicking in an indicator flyout', () => {
|
||||
cy.log('investigate in timeline when clicking in an indicator flyout');
|
||||
|
||||
openFlyout(0);
|
||||
openFlyoutTakeAction();
|
||||
investigateInTimelineFromFlyout();
|
||||
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
|
||||
closeTimeline();
|
||||
cy.get(TIMELINE_DATA_PROVIDERS_WRAPPER).within(() => {
|
||||
cy.get(TIMELINE_DRAGGABLE_ITEM).should('exist');
|
||||
cy.get(TIMELINE_AND_OR_BADGE).should('be.visible').and('have.length', 5);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,6 +18,3 @@ export const BLOCK_LIST_VALUE_INPUT = (iocId: string) =>
|
|||
`[data-test-subj="blocklist-form-values-input-${iocId}"]`;
|
||||
export const SAVED_BLOCK_LIST_NAME = `[data-test-subj="blocklistPage-card-header-title"]`;
|
||||
export const SAVED_BLOCK_LIST_DESCRIPTION = `[data-test-subj="blocklistPage-card-description"]`;
|
||||
export const SAVED_BLOCK_LIST_ACTION_MENU = `[data-test-subj="blocklistPage-card-header-actions-button"]`;
|
||||
export const SAVED_BLOCK_LIST_DELETE_BUTTON = `[data-test-subj="blocklistPage-card-cardDeleteAction"]`;
|
||||
export const SAVED_BLOCK_LIST_CONFIRM_DELETE_BUTTON = `[data-test-subj="blocklistPage-deleteModal-submitButton"]`;
|
||||
|
|
|
@ -18,14 +18,9 @@ export const INDICATORS_TABLE_ADD_TO_NEW_CASE_BUTTON_ICON = `[data-test-subj="${
|
|||
export const INDICATORS_TABLE_ADD_TO_EXISTING_CASE_BUTTON_ICON = `[data-test-subj="${INDICATORS_TABLE_ADD_TO_EXISTING_TEST_ID}"]`;
|
||||
export const FLYOUT_ADD_TO_EXISTING_CASE_ITEM = `[data-test-subj="${INDICATOR_FLYOUT_TAKE_ACTION_ADD_TO_EXISTING_CASE_TEST_ID}"]`;
|
||||
export const FLYOUT_ADD_TO_NEW_CASE_ITEM = `[data-test-subj="${INDICATOR_FLYOUT_TAKE_ACTION_ADD_TO_NEW_CASE_TEST_ID}"]`;
|
||||
export const CREATE_CASE_BUTTON = `[data-test-subj="createNewCaseBtn"]`;
|
||||
export const SELECT_EXISTING_CASE = `[class="eui-textTruncate"]`;
|
||||
export const VIEW_CASE_TOASTER_LINK = `[data-test-subj="toaster-content-case-view-link"]`;
|
||||
export const CASE_COMMENT_EXTERNAL_REFERENCE = `[data-test-subj="comment-externalReference-indicator"]`;
|
||||
export const CASE_ACTION_WRAPPER = `[data-test-subj="case-action-bar-wrapper"]`;
|
||||
export const CASE_ELLIPSE_BUTTON = `[data-test-subj="property-actions-case-ellipses"]`;
|
||||
export const CASE_ELLIPSE_DELETE_CASE_OPTION = `[data-test-subj="property-actions-case-trash"]`;
|
||||
export const CASE_ELLIPSE_DELETE_CASE_CONFIRMATION_BUTTON = `[data-test-subj="confirmModalConfirmButton"]`;
|
||||
export const NEW_CASE_NAME_INPUT = `[data-test-subj="input"][aria-describedby="caseTitle"]`;
|
||||
export const NEW_CASE_DESCRIPTION_INPUT = `[data-test-subj="euiMarkdownEditorTextArea"]`;
|
||||
export const NEW_CASE_CREATE_BUTTON = `[data-test-subj="create-case-submit"]`;
|
||||
|
|
|
@ -8,5 +8,4 @@
|
|||
export const UPDATE_STATUS = `[data-test-subj="updateStatus"]`;
|
||||
export const SECURITY_SOLUTION_NAVBAR_MANAGE_ITEM = `[data-test-subj="solutionSideNavItemLink-administration"]`;
|
||||
export const SECURITY_SOLUTION_NAVBAR_THREAT_INTELLIGENCE_ITEM = `[data-test-subj="solutionSideNavItemLink-threat_intelligence-indicators"]`;
|
||||
export const SECURITY_SOLUTION_NAVBAR_CASES_ITEM = `[data-test-subj="solutionSideNavItemLink-cases"]`;
|
||||
export const MANAGE_NAVIGATION_ITEMS = `.euiLink`;
|
||||
|
|
|
@ -105,3 +105,4 @@ export const INSPECTOR_BUTTON = `[data-test-subj="${INSPECT_BUTTON_TEST_ID}"]`;
|
|||
export const INSPECTOR_PANEL = `[data-test-subj="inspectorPanel"]`;
|
||||
export const ADD_INTEGRATIONS_BUTTON = `[data-test-subj="add-data"]`;
|
||||
export const REFRESH_BUTTON = `[data-test-subj="querySubmitButton"]`;
|
||||
export const ADDED_TO_TIMELINE_TOAST = `[data-test-subj="add-to-timeline-toast-success"]`;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
FLYOUT_TABLE_TEST_ID,
|
||||
INDICATORS_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS,
|
||||
INDICATORS_FLYOUT_OVERVIEW_TABLE,
|
||||
INVESTIGATE_IN_TIMELINE_TEST_ID as INDICATOR_FLYOUT_TAKE_ACTION_INVESTIGATE_IN_TIMELINE_TEST_ID,
|
||||
|
@ -20,10 +19,10 @@ import {
|
|||
export const INDICATORS_TABLE_INVESTIGATE_IN_TIMELINE_BUTTON_ICON = `[data-test-subj="${CELL_INVESTIGATE_IN_TIMELINE_TEST_ID}"]`;
|
||||
export const UNTITLED_TIMELINE_BUTTON = `[data-test-subj="flyoutOverlay"]`;
|
||||
export const INDICATORS_TABLE_CELL_TIMELINE_BUTTON = `[data-test-subj="${CELL_TIMELINE_BUTTON_TEST_ID}"] button`;
|
||||
export const TIMELINE_DATA_PROVIDERS_WRAPPER = `[data-test-subj="dataProviders"]`;
|
||||
export const TIMELINE_DRAGGABLE_ITEM = `[data-test-subj="providerContainer"]`;
|
||||
export const TIMELINE_AND_OR_BADGE = `[data-test-subj="and-or-badge"]`;
|
||||
export const CLOSE_TIMELINE_BTN = '[data-test-subj="close-timeline"]';
|
||||
export const QUERY_TAB_BUTTON = '[data-test-subj="timelineTabs-query"]';
|
||||
export const FLYOUT_OVERVIEW_TAB_TABLE_ROW_TIMELINE_BUTTON = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_TABLE}${VALUE_ACTION_TIMELINE_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_OVERVIEW_TAB_BLOCKS_TIMELINE_BUTTON = `[data-test-subj="${INDICATORS_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS}${VALUE_ACTION_TIMELINE_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_TABLE_TAB_ROW_TIMELINE_BUTTON = `[data-test-subj="${FLYOUT_TABLE_TEST_ID}${VALUE_ACTION_TIMELINE_BUTTON_TEST_ID}"]`;
|
||||
export const FLYOUT_INVESTIGATE_IN_TIMELINE_ITEM = `[data-test-subj="${INDICATOR_FLYOUT_TAKE_ACTION_INVESTIGATE_IN_TIMELINE_TEST_ID}"]`;
|
||||
|
|
|
@ -1,8 +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.
|
||||
*/
|
||||
|
||||
export const INDICATORS_URL = '/app/security/indicators';
|
|
@ -9,10 +9,7 @@ import {
|
|||
BLOCK_LIST_ADD_BUTTON,
|
||||
BLOCK_LIST_DESCRIPTION,
|
||||
BLOCK_LIST_NAME,
|
||||
SAVED_BLOCK_LIST_ACTION_MENU,
|
||||
BLOCK_LIST_TOAST_LIST,
|
||||
SAVED_BLOCK_LIST_CONFIRM_DELETE_BUTTON,
|
||||
SAVED_BLOCK_LIST_DELETE_BUTTON,
|
||||
FLYOUT_ADD_TO_BLOCK_LIST_ITEM,
|
||||
INDICATORS_TABLE_ADD_TO_BLOCK_LIST_BUTTON_ICON,
|
||||
} from '../screens/blocklist';
|
||||
|
@ -42,12 +39,3 @@ export const fillBlocklistForm = (title: string, description: string) => {
|
|||
const text: string = `"${title}" has been added`;
|
||||
cy.get(BLOCK_LIST_TOAST_LIST).should('exist').and('contain.text', text);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the blocklist entry
|
||||
*/
|
||||
export const deleteBlocklistEntry = () => {
|
||||
cy.get(SAVED_BLOCK_LIST_ACTION_MENU).click();
|
||||
cy.get(SAVED_BLOCK_LIST_DELETE_BUTTON).click();
|
||||
cy.get(SAVED_BLOCK_LIST_CONFIRM_DELETE_BUTTON).click();
|
||||
};
|
||||
|
|
|
@ -10,11 +10,6 @@ import {
|
|||
FLYOUT_ADD_TO_NEW_CASE_ITEM,
|
||||
INDICATORS_TABLE_ADD_TO_EXISTING_CASE_BUTTON_ICON,
|
||||
INDICATORS_TABLE_ADD_TO_NEW_CASE_BUTTON_ICON,
|
||||
CASE_ACTION_WRAPPER,
|
||||
CASE_ELLIPSE_BUTTON,
|
||||
CASE_ELLIPSE_DELETE_CASE_CONFIRMATION_BUTTON,
|
||||
CASE_ELLIPSE_DELETE_CASE_OPTION,
|
||||
CREATE_CASE_BUTTON,
|
||||
NEW_CASE_CREATE_BUTTON,
|
||||
NEW_CASE_DESCRIPTION_INPUT,
|
||||
NEW_CASE_NAME_INPUT,
|
||||
|
@ -52,16 +47,6 @@ export const openAddToExistingCaseFromFlyout = () => {
|
|||
cy.get(FLYOUT_ADD_TO_EXISTING_CASE_ITEM).first().click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new case by filling out the form from the Cases page
|
||||
*/
|
||||
export const createNewCaseFromCases = () => {
|
||||
cy.get(CREATE_CASE_BUTTON).click();
|
||||
cy.get(NEW_CASE_NAME_INPUT).click().type('case');
|
||||
cy.get(NEW_CASE_DESCRIPTION_INPUT).click().type('case description');
|
||||
cy.get(NEW_CASE_CREATE_BUTTON).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new case from the Threat Intelligence page
|
||||
*/
|
||||
|
@ -78,15 +63,6 @@ export const navigateToCaseViaToaster = () => {
|
|||
cy.get(VIEW_CASE_TOASTER_LINK).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete case from the Cases page
|
||||
*/
|
||||
export const deleteCase = () => {
|
||||
cy.get(CASE_ACTION_WRAPPER).find(CASE_ELLIPSE_BUTTON).click();
|
||||
cy.get(CASE_ELLIPSE_DELETE_CASE_OPTION).click();
|
||||
cy.get(CASE_ELLIPSE_DELETE_CASE_CONFIRMATION_BUTTON).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Select existing case from cases modal
|
||||
*/
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import {
|
||||
MANAGE_NAVIGATION_ITEMS,
|
||||
SECURITY_SOLUTION_NAVBAR_CASES_ITEM,
|
||||
SECURITY_SOLUTION_NAVBAR_MANAGE_ITEM,
|
||||
SECURITY_SOLUTION_NAVBAR_THREAT_INTELLIGENCE_ITEM,
|
||||
UPDATE_STATUS,
|
||||
|
@ -26,7 +25,8 @@ import {
|
|||
* Navigate to Blocklist screen via the Security Solution navbar and Manage menu item
|
||||
*/
|
||||
export const navigateToBlocklist = () => {
|
||||
cy.get(SECURITY_SOLUTION_NAVBAR_MANAGE_ITEM).scrollIntoView().click();
|
||||
cy.get(SECURITY_SOLUTION_NAVBAR_MANAGE_ITEM).scrollIntoView();
|
||||
cy.get(SECURITY_SOLUTION_NAVBAR_MANAGE_ITEM).click();
|
||||
cy.get(MANAGE_NAVIGATION_ITEMS).contains('Blocklist').click();
|
||||
};
|
||||
|
||||
|
@ -37,13 +37,6 @@ export const navigateToThreatIntelligence = () => {
|
|||
cy.get(SECURITY_SOLUTION_NAVBAR_THREAT_INTELLIGENCE_ITEM).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigate to Cases screen via the Security Solution navbar
|
||||
*/
|
||||
export const navigateToCases = () => {
|
||||
cy.get(SECURITY_SOLUTION_NAVBAR_CASES_ITEM).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the opened flyout
|
||||
*/
|
||||
|
@ -87,12 +80,14 @@ export const navigateToFlyoutJsonTab = () => {
|
|||
};
|
||||
|
||||
export const waitForViewToBeUpdated = () => {
|
||||
cy.get(UPDATE_STATUS).scrollIntoView().should('contain.text', 'Updated');
|
||||
cy.get(UPDATE_STATUS).scrollIntoView();
|
||||
cy.get(UPDATE_STATUS).should('contain.text', 'Updated');
|
||||
};
|
||||
|
||||
/**
|
||||
* Open barchart 3-dot popover menu
|
||||
*/
|
||||
export const openBarchartPopoverMenu = () => {
|
||||
cy.get(BARCHART_POPOVER_BUTTON).first().scrollIntoView();
|
||||
cy.get(BARCHART_POPOVER_BUTTON).should('exist').first().click();
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { QUERY_INPUT } from '../screens/indicators';
|
||||
|
||||
/**
|
||||
* Nvigate to specific page in indicators table
|
||||
* Navigate to specific page in indicators table
|
||||
*/
|
||||
export const navigateToIndicatorsTablePage = (index: number) => {
|
||||
cy.get(`[data-test-subj="pagination-button-${index}"]`).click();
|
||||
|
@ -18,12 +18,14 @@ export const navigateToIndicatorsTablePage = (index: number) => {
|
|||
* Clears text in KQL bar
|
||||
*/
|
||||
export const enterQuery = (text: string) => {
|
||||
cy.get(QUERY_INPUT).should('exist').focus().type(text);
|
||||
cy.get(QUERY_INPUT).should('exist').focus();
|
||||
cy.get(QUERY_INPUT).should('exist').type(text);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears text in KQL bar
|
||||
*/
|
||||
export const clearQuery = () => {
|
||||
cy.get(QUERY_INPUT).should('exist').focus().clear();
|
||||
cy.get(QUERY_INPUT).should('exist').focus();
|
||||
cy.get(QUERY_INPUT).should('exist').clear();
|
||||
};
|
||||
|
|
|
@ -10,13 +10,15 @@ import Url from 'url';
|
|||
|
||||
import * as yaml from 'js-yaml';
|
||||
|
||||
import {
|
||||
LOADING_INDICATOR,
|
||||
LOADING_INDICATOR_HIDDEN,
|
||||
} from '@kbn/security-solution-plugin/cypress/screens/security_header';
|
||||
import { encode } from '@kbn/rison';
|
||||
import { NEW_FEATURES_TOUR_STORAGE_KEYS } from '@kbn/security-solution-plugin/common/constants';
|
||||
import type { ROLES } from './privileges';
|
||||
|
||||
const LOGIN_API_ENDPOINT = '/internal/security/login';
|
||||
const LOGOUT_URL = '/logout';
|
||||
|
||||
export const hostDetailsUrl = (hostName: string) =>
|
||||
`/app/security/hosts/${hostName}/authentications`;
|
||||
|
||||
/**
|
||||
* Credentials in the `kibana.dev.yml` config file will be used to authenticate
|
||||
|
@ -124,33 +126,6 @@ export const postRoleAndUser = (role: ROLES) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const deleteRoleAndUser = (role: ROLES) => {
|
||||
const env = getCurlScriptEnvVars();
|
||||
const detectionsUserDeleteScriptPath = `./server/lib/detection_engine/scripts/roles_users/${role}/delete_detections_user.sh`;
|
||||
|
||||
// delete the role
|
||||
cy.exec(`bash ${detectionsUserDeleteScriptPath}`, {
|
||||
env,
|
||||
});
|
||||
};
|
||||
|
||||
export const loginWithUser = (user: User) => {
|
||||
cy.request({
|
||||
body: {
|
||||
providerType: 'basic',
|
||||
providerName: 'basic',
|
||||
currentURL: '/',
|
||||
params: {
|
||||
username: user.username,
|
||||
password: user.password,
|
||||
},
|
||||
},
|
||||
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
|
||||
method: 'POST',
|
||||
url: constructUrlWithUser(user, LOGIN_API_ENDPOINT),
|
||||
});
|
||||
};
|
||||
|
||||
export const loginWithRole = async (role: ROLES) => {
|
||||
postRoleAndUser(role);
|
||||
const theUrl = Url.format({
|
||||
|
@ -297,57 +272,53 @@ export const getEnvAuth = (): User => {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Authenticates with Kibana, visits the specified `url`, and waits for the
|
||||
* Kibana global nav to be displayed before continuing
|
||||
*/
|
||||
export const loginAndWaitForPage = (
|
||||
url: string,
|
||||
role?: ROLES,
|
||||
onBeforeLoadCallback?: (win: Cypress.AUTWindow) => void
|
||||
) => {
|
||||
login(role);
|
||||
cy.visit(
|
||||
`${url}?timerange=(global:(linkTo:!(timeline),timerange:(from:1547914976217,fromStr:'2019-01-19T16:22:56.217Z',kind:relative,to:1579537385745,toStr:now)),timeline:(linkTo:!(global),timerange:(from:1547914976217,fromStr:'2019-01-19T16:22:56.217Z',kind:relative,to:1579537385745,toStr:now)))`,
|
||||
{
|
||||
onBeforeLoad(win) {
|
||||
if (onBeforeLoadCallback) {
|
||||
onBeforeLoadCallback(win);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
cy.get('[data-test-subj="headerGlobalNav"]');
|
||||
};
|
||||
export const waitForPage = (url: string) => {
|
||||
cy.visit(
|
||||
`${url}?timerange=(global:(linkTo:!(timeline),timerange:(from:1547914976217,fromStr:'2019-01-19T16:22:56.217Z',kind:relative,to:1579537385745,toStr:now)),timeline:(linkTo:!(global),timerange:(from:1547914976217,fromStr:'2019-01-19T16:22:56.217Z',kind:relative,to:1579537385745,toStr:now)))`
|
||||
);
|
||||
cy.get('[data-test-subj="headerGlobalNav"]');
|
||||
export const visit = (url: string, options: Partial<Cypress.VisitOptions> = {}, role?: ROLES) => {
|
||||
const timerangeConfig = {
|
||||
from: 1547914976217,
|
||||
fromStr: '2019-01-19T16:22:56.217Z',
|
||||
kind: 'relative',
|
||||
to: 1579537385745,
|
||||
toStr: 'now',
|
||||
};
|
||||
|
||||
const timerange = encode({
|
||||
global: {
|
||||
linkTo: ['timeline'],
|
||||
timerange: timerangeConfig,
|
||||
},
|
||||
timeline: {
|
||||
linkTo: ['global'],
|
||||
timerange: timerangeConfig,
|
||||
},
|
||||
});
|
||||
|
||||
cy.visit(role ? getUrlWithRoute(role, url) : url, {
|
||||
...options,
|
||||
qs: {
|
||||
...options.qs,
|
||||
timerange,
|
||||
},
|
||||
onBeforeLoad: (win) => {
|
||||
options.onBeforeLoad?.(win);
|
||||
|
||||
disableNewFeaturesTours(win);
|
||||
},
|
||||
});
|
||||
waitForPageToBeLoaded();
|
||||
};
|
||||
|
||||
export const loginAndWaitForPageWithoutDateRange = (url: string, role?: ROLES) => {
|
||||
login(role);
|
||||
cy.visit(role ? getUrlWithRoute(role, url) : url);
|
||||
cy.get('[data-test-subj="headerGlobalNav"]', { timeout: 120000 });
|
||||
const disableNewFeaturesTours = (window: Window) => {
|
||||
const tourStorageKeys = Object.values(NEW_FEATURES_TOUR_STORAGE_KEYS);
|
||||
const tourConfig = {
|
||||
isTourActive: false,
|
||||
};
|
||||
|
||||
tourStorageKeys.forEach((key) => {
|
||||
window.localStorage.setItem(key, JSON.stringify(tourConfig));
|
||||
});
|
||||
};
|
||||
|
||||
export const loginWithUserAndWaitForPage = (url: string, user: User) => {
|
||||
loginWithUser(user);
|
||||
cy.visit(constructUrlWithUser(user, url));
|
||||
cy.get('[data-test-subj="headerGlobalNav"]', { timeout: 120000 });
|
||||
};
|
||||
|
||||
export const loginAndWaitForHostDetailsPage = (hostName = 'suricata-iowa') => {
|
||||
loginAndWaitForPage(hostDetailsUrl(hostName));
|
||||
cy.get('[data-test-subj="loading-spinner"]', { timeout: 12000 }).should('not.exist');
|
||||
};
|
||||
|
||||
export const waitForPageWithoutDateRange = (url: string, role?: ROLES) => {
|
||||
cy.visit(role ? getUrlWithRoute(role, url) : url);
|
||||
cy.get('[data-test-subj="headerGlobalNav"]', { timeout: 120000 });
|
||||
};
|
||||
|
||||
export const logout = () => {
|
||||
cy.visit(LOGOUT_URL);
|
||||
export const waitForPageToBeLoaded = () => {
|
||||
cy.get(LOADING_INDICATOR_HIDDEN).should('exist');
|
||||
cy.get(LOADING_INDICATOR).should('not.exist');
|
||||
};
|
||||
|
|
|
@ -48,118 +48,6 @@ interface Role {
|
|||
};
|
||||
}
|
||||
|
||||
// Create roles with allowed combinations of Fleet and Integrations
|
||||
export const FleetAllIntegrAllRole: Role = {
|
||||
name: 'fleet_all_int_all_role',
|
||||
privileges: {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
names: ['*'],
|
||||
privileges: ['all'],
|
||||
},
|
||||
],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
fleetv2: ['all'],
|
||||
fleet: ['all'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const FleetAllIntegrAllUser: User = {
|
||||
username: 'fleet_all_int_all_user',
|
||||
password: 'password',
|
||||
roles: [FleetAllIntegrAllRole.name],
|
||||
};
|
||||
|
||||
export const FleetAllIntegrReadRole: Role = {
|
||||
name: 'fleet_all_int_read_user',
|
||||
privileges: {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
names: ['*'],
|
||||
privileges: ['all'],
|
||||
},
|
||||
],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
fleetv2: ['all'],
|
||||
fleet: ['read'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
export const FleetAllIntegrReadUser: User = {
|
||||
username: 'fleet_all_int_read_user',
|
||||
password: 'password',
|
||||
roles: [FleetAllIntegrReadRole.name],
|
||||
};
|
||||
export const FleetAllIntegrNoneRole: Role = {
|
||||
name: 'fleet_all_int_none_role',
|
||||
privileges: {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
names: ['*'],
|
||||
privileges: ['all'],
|
||||
},
|
||||
],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
fleetv2: ['all'],
|
||||
fleet: ['none'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
export const FleetAllIntegrNoneUser: User = {
|
||||
username: 'fleet_all_int_none_user',
|
||||
password: 'password',
|
||||
roles: [FleetAllIntegrNoneRole.name],
|
||||
};
|
||||
export const FleetNoneIntegrAllRole: Role = {
|
||||
name: 'fleet_none_int_all_role',
|
||||
privileges: {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
names: ['*'],
|
||||
privileges: ['all'],
|
||||
},
|
||||
],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
fleetv2: ['none'],
|
||||
fleet: ['all'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
export const FleetNoneIntegrAllUser: User = {
|
||||
username: 'fleet_none_int_all_user',
|
||||
password: 'password',
|
||||
roles: [FleetNoneIntegrAllRole.name],
|
||||
};
|
||||
|
||||
const getUserInfo = (user: User): UserInfo => ({
|
||||
username: user.username,
|
||||
full_name: user.username.replace('_', ' '),
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { openBarchartPopoverMenu } from './common';
|
||||
import {
|
||||
QUERY_BAR,
|
||||
QUERY_BAR_MENU_REMOVE_ALL_FILTERS_BUTTON,
|
||||
|
@ -29,6 +30,7 @@ import {
|
|||
* Filter in value by clicking on the menu item within barchart popover
|
||||
*/
|
||||
export const filterInFromBarChartLegend = () => {
|
||||
openBarchartPopoverMenu();
|
||||
cy.get(BARCHART_FILTER_IN_BUTTON).should('exist').click();
|
||||
};
|
||||
|
||||
|
@ -36,6 +38,7 @@ export const filterInFromBarChartLegend = () => {
|
|||
* Filter out value by clicking on the menu item within barchart popover
|
||||
*/
|
||||
export const filterOutFromBarChartLegend = () => {
|
||||
openBarchartPopoverMenu();
|
||||
cy.get(BARCHART_FILTER_OUT_BUTTON).should('exist').click();
|
||||
};
|
||||
|
||||
|
@ -43,10 +46,10 @@ export const filterOutFromBarChartLegend = () => {
|
|||
* Filter in value by clicking on the menu item within an indicators table cell
|
||||
*/
|
||||
export const filterInFromTableCell = () => {
|
||||
cy.get(INDICATOR_TYPE_CELL).first().should('be.visible');
|
||||
cy.get(INDICATOR_TYPE_CELL).first().trigger('mouseover');
|
||||
cy.get(INDICATOR_TYPE_CELL)
|
||||
.first()
|
||||
.should('be.visible')
|
||||
.trigger('mouseover')
|
||||
.within((_cell) => {
|
||||
cy.get(INDICATORS_TABLE_CELL_FILTER_IN_BUTTON).should('exist').click({
|
||||
force: true,
|
||||
|
@ -58,9 +61,9 @@ export const filterInFromTableCell = () => {
|
|||
* Filter out value by clicking on the menu item within an indicators table cell
|
||||
*/
|
||||
export const filterOutFromTableCell = () => {
|
||||
cy.get(INDICATOR_TYPE_CELL).first().trigger('mouseover');
|
||||
cy.get(INDICATOR_TYPE_CELL)
|
||||
.first()
|
||||
.trigger('mouseover')
|
||||
.within((_cell) => {
|
||||
cy.get(INDICATORS_TABLE_CELL_FILTER_OUT_BUTTON).should('exist').click({ force: true });
|
||||
});
|
||||
|
@ -70,7 +73,10 @@ export const filterOutFromTableCell = () => {
|
|||
* Clears all filters within KQL bar
|
||||
*/
|
||||
export const clearKQLBar = () => {
|
||||
cy.get(QUERY_BAR).scrollIntoView();
|
||||
cy.get(QUERY_BAR).within(() => cy.get(QUERY_BAR_MENU).click());
|
||||
|
||||
cy.get(QUERY_BAR_MENU_REMOVE_ALL_FILTERS_BUTTON).scrollIntoView();
|
||||
cy.get(QUERY_BAR_MENU_REMOVE_ALL_FILTERS_BUTTON).click();
|
||||
};
|
||||
|
||||
|
|
|
@ -1,18 +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 { EMPTY_STATE, TIME_RANGE_PICKER } from '../screens/indicators';
|
||||
|
||||
export const selectRange = () => {
|
||||
cy.get(EMPTY_STATE);
|
||||
|
||||
cy.get(TIME_RANGE_PICKER).first().click({ force: true });
|
||||
cy.get('[aria-label="Time unit"]').select('y');
|
||||
cy.get('[data-test-subj="superDatePickerQuickMenu"] .euiQuickSelect__applyButton').click({
|
||||
force: true,
|
||||
});
|
||||
};
|
|
@ -5,6 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { recurse } from 'cypress-recurse';
|
||||
import { openBarchartPopoverMenu } from './common';
|
||||
import {
|
||||
CLOSE_TIMELINE_BTN,
|
||||
FLYOUT_INVESTIGATE_IN_TIMELINE_ITEM,
|
||||
|
@ -15,6 +17,7 @@ import {
|
|||
UNTITLED_TIMELINE_BUTTON,
|
||||
} from '../screens/timeline';
|
||||
import {
|
||||
ADDED_TO_TIMELINE_TOAST,
|
||||
BARCHART_TIMELINE_BUTTON,
|
||||
FLYOUT_BLOCK_MORE_ACTIONS_BUTTON,
|
||||
FLYOUT_TABLE_MORE_ACTIONS_BUTTON,
|
||||
|
@ -25,7 +28,15 @@ import {
|
|||
* Add data to timeline from barchart legend menu item
|
||||
*/
|
||||
export const addToTimelineFromBarchartLegend = () => {
|
||||
cy.get(BARCHART_TIMELINE_BUTTON).should('exist').first().click();
|
||||
recurse(
|
||||
() => {
|
||||
openBarchartPopoverMenu();
|
||||
cy.get(BARCHART_TIMELINE_BUTTON).first().click();
|
||||
openBarchartPopoverMenu();
|
||||
return cy.get(ADDED_TO_TIMELINE_TOAST).should(Cypress._.noop);
|
||||
},
|
||||
($el) => !!$el.length
|
||||
);
|
||||
};
|
||||
/**
|
||||
* Add data to timeline from indicators table cell menu
|
||||
|
@ -53,16 +64,33 @@ export const closeTimeline = () => {
|
|||
* Add data to timeline from flyout overview tab table
|
||||
*/
|
||||
export const addToTimelineFromFlyoutOverviewTabTable = () => {
|
||||
cy.get(FLYOUT_TABLE_MORE_ACTIONS_BUTTON).first().click({ force: true });
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_TABLE_ROW_TIMELINE_BUTTON).should('exist').first().click();
|
||||
recurse(
|
||||
() => {
|
||||
cy.get(FLYOUT_TABLE_MORE_ACTIONS_BUTTON).first().click({ force: true });
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_TABLE_ROW_TIMELINE_BUTTON).first().click();
|
||||
cy.get(FLYOUT_TABLE_MORE_ACTIONS_BUTTON).first().click({ force: true });
|
||||
|
||||
return cy.get(ADDED_TO_TIMELINE_TOAST).should(Cypress._.noop);
|
||||
},
|
||||
($el) => !!$el.length
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add data to timeline from flyout overview tab block
|
||||
*/
|
||||
export const addToTimelineFromFlyoutOverviewTabBlock = () => {
|
||||
cy.get(FLYOUT_BLOCK_MORE_ACTIONS_BUTTON).first().click({ force: true });
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_BLOCKS_TIMELINE_BUTTON).should('exist').first().click();
|
||||
recurse(
|
||||
() => {
|
||||
cy.get(FLYOUT_BLOCK_MORE_ACTIONS_BUTTON).first().click({ force: true });
|
||||
|
||||
cy.get(FLYOUT_OVERVIEW_TAB_BLOCKS_TIMELINE_BUTTON).first().click();
|
||||
cy.get(FLYOUT_BLOCK_MORE_ACTIONS_BUTTON).first().click({ force: true });
|
||||
|
||||
return cy.get(ADDED_TO_TIMELINE_TOAST).should(Cypress._.noop);
|
||||
},
|
||||
($el) => !!$el.length
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,16 +5,12 @@
|
|||
"license": "Elastic License 2.0",
|
||||
"scripts": {
|
||||
"cypress": "../../../node_modules/.bin/cypress",
|
||||
"cypress:open": "yarn cypress open --config-file ./cypress/cypress.config.ts",
|
||||
"cypress:open-as-ci": "node ../../../scripts/functional_tests --config ../../test/threat_intelligence_cypress/visual_config.ts",
|
||||
"cypress:open": "TZ=UTC node ../security_solution/scripts/start_cypress_parallel open --spec './cypress/e2e/**/*.cy.ts' --config-file ./cypress/cypress.config.ts --ftr-config-file ../../../../../../x-pack/test/threat_intelligence_cypress/cli_config_parallel",
|
||||
"cypress:run": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/**/*.cy.ts'; status=$?; yarn junit:merge && exit $status",
|
||||
"cypress:run:spec": "yarn cypress:run:reporter --browser chrome --spec ${SPEC_LIST:-'./cypress/e2e/**/*.cy.ts'}; status=$?; yarn junit:merge && exit $status",
|
||||
"cypress:run:cases": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/cases/*.cy.ts'; 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": "yarn cypress run --config-file ./cypress/cypress.config.ts --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/*.cy.ts,./cypress/e2e/detection_rules/*.cy.ts,./cypress/e2e/exceptions/*.cy.ts; status=$?; yarn junit:merge && exit $status",
|
||||
"cypress:run-as-ci": "node --max-old-space-size=2048 ../../../scripts/functional_tests --config ../../test/threat_intelligence_cypress/cli_config_parallel.ts",
|
||||
"cypress:run-as-ci:firefox": "node --max-old-space-size=2048 ../../../scripts/functional_tests --config ../../test/threat_intelligence_cypress/config.firefox.ts",
|
||||
"cypress:run:cases": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/cases/*.cy.ts' --ftr-config-file ../../../../../../x-pack/test/security_solution_cypress/cases_cli_config; status=$?; yarn junit:merge && exit $status",
|
||||
"cypress:run:reporter": "TZ=UTC node ../security_solution/scripts/start_cypress_parallel run --config-file ./cypress/cypress.config.ts --ftr-config-file ../../../../../../x-pack/test/threat_intelligence_cypress/cli_config_parallel --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/*.cy.ts,./cypress/e2e/detection_rules/*.cy.ts,./cypress/e2e/exceptions/*.cy.ts --ftr-config-file ../../../../../../x-pack/test/security_solution_cypress/response_ops_cli_config; status=$?; yarn junit:merge && exit $status",
|
||||
"junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-threat-intelligence/cypress/results/mochawesome*.json > ../../../target/kibana-threat-intelligence/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-threat-intelligence/cypress/results/output.json --reportDir ../../../target/kibana-threat-intelligence/cypress/results && mkdir -p ../../../target/junit && cp ../../../target/kibana-threat-intelligence/cypress/results/*.xml ../../../target/junit/"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,7 @@
|
|||
import { FtrConfigProviderContext } from '@kbn/test';
|
||||
import { FtrProviderContext } from './ftr_provider_context';
|
||||
|
||||
import { ThreatIntelligenceCypressCliTestRunnerCI } from './runner';
|
||||
|
||||
const cliNumber = parseInt(process.env.CLI_NUMBER ?? '1', 10);
|
||||
const cliCount = parseInt(process.env.CLI_COUNT ?? '1', 10);
|
||||
import { ThreatIntelligenceConfigurableCypressTestRunner } from './runner';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
|
@ -20,6 +17,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
...securitySolutionCypressConfig.getAll(),
|
||||
|
||||
testRunner: (context: FtrProviderContext) =>
|
||||
ThreatIntelligenceCypressCliTestRunnerCI(context, cliCount, cliNumber),
|
||||
ThreatIntelligenceConfigurableCypressTestRunner(context),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { chunk } from 'lodash';
|
||||
import { resolve } from 'path';
|
||||
import globby from 'globby';
|
||||
|
||||
import Url from 'url';
|
||||
|
||||
|
@ -21,17 +19,8 @@ import { tiAbusechMalware } from './pipelines/ti_abusech_malware';
|
|||
import { tiAbusechMalwareBazaar } from './pipelines/ti_abusech_malware_bazaar';
|
||||
import { tiAbusechUrl } from './pipelines/ti_abusech_url';
|
||||
|
||||
const retrieveIntegrations = (chunksTotal: number, chunkIndex: number) => {
|
||||
const pattern = resolve(__dirname, '../../plugins/threat_intelligence/cypress/e2e/**/*.cy.ts');
|
||||
const integrationsPaths = globby.sync(pattern);
|
||||
const chunkSize = Math.ceil(integrationsPaths.length / chunksTotal);
|
||||
|
||||
return chunk(integrationsPaths, chunkSize)[chunkIndex - 1] || [];
|
||||
};
|
||||
|
||||
export async function ThreatIntelligenceConfigurableCypressTestRunner(
|
||||
{ getService }: FtrProviderContext,
|
||||
command: string,
|
||||
envVars?: Record<string, string>
|
||||
) {
|
||||
const log = getService('log');
|
||||
|
@ -55,56 +44,19 @@ export async function ThreatIntelligenceConfigurableCypressTestRunner(
|
|||
log.info(`PUT pipeline ${pipeline.name}: ${res.statusCode}`);
|
||||
}
|
||||
|
||||
await withProcRunner(log, async (procs) => {
|
||||
await procs.run('cypress', {
|
||||
cmd: 'yarn',
|
||||
args: [command],
|
||||
cwd: resolve(__dirname, '../../plugins/threat_intelligence'),
|
||||
env: {
|
||||
FORCE_COLOR: '1',
|
||||
CYPRESS_BASE_URL: Url.format(config.get('servers.kibana')),
|
||||
CYPRESS_ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')),
|
||||
CYPRESS_ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'),
|
||||
CYPRESS_ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'),
|
||||
...process.env,
|
||||
...envVars,
|
||||
},
|
||||
wait: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function ThreatIntelligenceCypressCliTestRunnerCI(
|
||||
context: FtrProviderContext,
|
||||
totalCiJobs: number,
|
||||
ciJobNumber: number
|
||||
) {
|
||||
const integrations = retrieveIntegrations(totalCiJobs, ciJobNumber);
|
||||
return ThreatIntelligenceConfigurableCypressTestRunner(context, 'cypress:run:spec', {
|
||||
SPEC_LIST: integrations.join(','),
|
||||
});
|
||||
}
|
||||
|
||||
export async function ThreatIntelligenceCypressCliResponseOpsTestRunner(
|
||||
context: FtrProviderContext
|
||||
) {
|
||||
return ThreatIntelligenceConfigurableCypressTestRunner(context, 'cypress:run:respops');
|
||||
}
|
||||
|
||||
export async function ThreatIntelligenceCypressCliCasesTestRunner(context: FtrProviderContext) {
|
||||
return ThreatIntelligenceConfigurableCypressTestRunner(context, 'cypress:run:cases');
|
||||
}
|
||||
|
||||
export async function ThreatIntelligenceCypressCliTestRunner(context: FtrProviderContext) {
|
||||
return ThreatIntelligenceConfigurableCypressTestRunner(context, 'cypress:run');
|
||||
}
|
||||
|
||||
export async function ThreatIntelligenceCypressCliFirefoxTestRunner(context: FtrProviderContext) {
|
||||
return ThreatIntelligenceConfigurableCypressTestRunner(context, 'cypress:run:firefox');
|
||||
}
|
||||
|
||||
export async function ThreatIntelligenceCypressVisualTestRunner(context: FtrProviderContext) {
|
||||
return ThreatIntelligenceConfigurableCypressTestRunner(context, 'cypress:open');
|
||||
return {
|
||||
FORCE_COLOR: '1',
|
||||
CYPRESS_BASE_URL: Url.format(config.get('servers.kibana')),
|
||||
CYPRESS_ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')),
|
||||
CYPRESS_ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'),
|
||||
CYPRESS_ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'),
|
||||
...envVars,
|
||||
baseUrl: Url.format(config.get('servers.kibana')),
|
||||
BASE_URL: Url.format(config.get('servers.kibana')),
|
||||
ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')),
|
||||
ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'),
|
||||
ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'),
|
||||
};
|
||||
}
|
||||
|
||||
export async function ThreatIntelligenceCypressCcsTestRunner({ getService }: FtrProviderContext) {
|
||||
|
|
|
@ -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 { ThreatIntelligenceCypressVisualTestRunner } from './runner';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const tiCypressConfig = await readConfigFile(require.resolve('./config.ts'));
|
||||
return {
|
||||
...tiCypressConfig.getAll(),
|
||||
|
||||
testRunner: ThreatIntelligenceCypressVisualTestRunner,
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue