mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Security solution] [Explore] Alerts/cases guided onboarding cypress tests (#145312)
This commit is contained in:
parent
c5239d3c4e
commit
39bacae9bc
9 changed files with 212 additions and 79 deletions
|
@ -40,7 +40,14 @@ export const getPluginState = async (savedObjectsClient: SavedObjectsClient) =>
|
|||
return pluginState;
|
||||
} else {
|
||||
// create a SO to keep track of the correct creation date
|
||||
await updatePluginStatus(savedObjectsClient, 'not_started');
|
||||
try {
|
||||
await updatePluginStatus(savedObjectsClient, 'not_started');
|
||||
// @yulia, we need to add a user permissions
|
||||
// check here instead of swallowing this error
|
||||
// see issue: https://github.com/elastic/kibana/issues/145434
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
|
||||
return {
|
||||
status: 'not_started',
|
||||
isActivePeriod: true,
|
||||
|
|
|
@ -5,58 +5,100 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { login, visit } from '../../tasks/login';
|
||||
import { completeTour, goToNextStep, skipTour } from '../../tasks/guided_onboarding';
|
||||
import { OVERVIEW_URL } from '../../urls/navigation';
|
||||
import { navigateFromHeaderTo } from '../../tasks/security_header';
|
||||
import { ALERTS, TIMELINES } from '../../screens/security_header';
|
||||
import { closeAlertFlyout, expandFirstAlert } from '../../tasks/alerts';
|
||||
import {
|
||||
WELCOME_STEP,
|
||||
MANAGE_STEP,
|
||||
ALERTS_STEP,
|
||||
CASES_STEP,
|
||||
DATA_STEP,
|
||||
} from '../../screens/guided_onboarding';
|
||||
assertTourStepExist,
|
||||
assertTourStepNotExist,
|
||||
closeCreateCaseFlyout,
|
||||
completeTourWithActions,
|
||||
completeTourWithNextButton,
|
||||
addToCase,
|
||||
finishTour,
|
||||
goToStep,
|
||||
startTour,
|
||||
} from '../../tasks/guided_onboarding';
|
||||
import { cleanKibana } from '../../tasks/common';
|
||||
import { createCustomRuleEnabled } from '../../tasks/api_calls/rules';
|
||||
import { getNewRule } from '../../objects/rule';
|
||||
import { ALERTS_URL, DASHBOARDS_URL } from '../../urls/navigation';
|
||||
import { waitForAlertsToPopulate } from '../../tasks/create_new_rule';
|
||||
import { login, visit } from '../../tasks/login';
|
||||
import { quitGlobalTour, startAlertsCasesTour } from '../../tasks/api_calls/tour';
|
||||
import { AlertsCasesTourSteps } from '../../../public/common/components/guided_onboarding_tour/tour_config';
|
||||
|
||||
before(() => {
|
||||
login();
|
||||
});
|
||||
describe('Guided onboarding tour', () => {
|
||||
before(() => {
|
||||
cleanKibana();
|
||||
login();
|
||||
createCustomRuleEnabled({ ...getNewRule(), customQuery: 'user.name:*' });
|
||||
});
|
||||
beforeEach(() => {
|
||||
startAlertsCasesTour();
|
||||
visit(ALERTS_URL);
|
||||
waitForAlertsToPopulate();
|
||||
});
|
||||
after(() => {
|
||||
quitGlobalTour();
|
||||
});
|
||||
it('Completes the tour with next button clicks', () => {
|
||||
startTour();
|
||||
completeTourWithNextButton();
|
||||
finishTour();
|
||||
cy.url().should('include', DASHBOARDS_URL);
|
||||
});
|
||||
|
||||
// need to redo these tests for new implementation
|
||||
describe.skip('Guided onboarding tour', () => {
|
||||
describe('Tour is enabled', () => {
|
||||
beforeEach(() => {
|
||||
visit(OVERVIEW_URL);
|
||||
it('Completes the tour with action clicks', () => {
|
||||
startTour();
|
||||
completeTourWithActions();
|
||||
finishTour();
|
||||
cy.url().should('include', DASHBOARDS_URL);
|
||||
});
|
||||
|
||||
// unhappy paths
|
||||
it('Resets the tour to step 1 when we navigate away', () => {
|
||||
startTour();
|
||||
goToStep(AlertsCasesTourSteps.expandEvent);
|
||||
assertTourStepExist(AlertsCasesTourSteps.expandEvent);
|
||||
assertTourStepNotExist(AlertsCasesTourSteps.pointToAlertName);
|
||||
navigateFromHeaderTo(TIMELINES);
|
||||
navigateFromHeaderTo(ALERTS);
|
||||
assertTourStepNotExist(AlertsCasesTourSteps.expandEvent);
|
||||
assertTourStepExist(AlertsCasesTourSteps.pointToAlertName);
|
||||
});
|
||||
|
||||
describe('persists tour steps in flyout on flyout toggle', () => {
|
||||
const stepsInAlertsFlyout = [
|
||||
AlertsCasesTourSteps.reviewAlertDetailsFlyout,
|
||||
AlertsCasesTourSteps.addAlertToCase,
|
||||
AlertsCasesTourSteps.viewCase,
|
||||
];
|
||||
|
||||
const stepsInCasesFlyout = [AlertsCasesTourSteps.createCase, AlertsCasesTourSteps.submitCase];
|
||||
|
||||
stepsInAlertsFlyout.forEach((step) => {
|
||||
it(`step: ${step}, resets to ${step}`, () => {
|
||||
startTour();
|
||||
goToStep(step);
|
||||
assertTourStepExist(step);
|
||||
closeAlertFlyout();
|
||||
assertTourStepNotExist(step);
|
||||
expandFirstAlert();
|
||||
assertTourStepExist(step);
|
||||
});
|
||||
});
|
||||
|
||||
it('can be completed', () => {
|
||||
// Step 1: Overview
|
||||
cy.get(WELCOME_STEP).should('be.visible');
|
||||
goToNextStep(WELCOME_STEP);
|
||||
|
||||
// Step 2: Manage
|
||||
cy.get(MANAGE_STEP).should('be.visible');
|
||||
goToNextStep(MANAGE_STEP);
|
||||
|
||||
// Step 3: Alerts
|
||||
cy.get(ALERTS_STEP).should('be.visible');
|
||||
goToNextStep(ALERTS_STEP);
|
||||
|
||||
// Step 4: Cases
|
||||
cy.get(CASES_STEP).should('be.visible');
|
||||
goToNextStep(CASES_STEP);
|
||||
|
||||
// Step 5: Add data
|
||||
cy.get(DATA_STEP).should('be.visible');
|
||||
completeTour();
|
||||
});
|
||||
|
||||
it('can be skipped', () => {
|
||||
cy.get(WELCOME_STEP).should('be.visible');
|
||||
|
||||
skipTour();
|
||||
// step 1 is not displayed
|
||||
cy.get(WELCOME_STEP).should('not.exist');
|
||||
// step 2 is not displayed
|
||||
cy.get(MANAGE_STEP).should('not.exist');
|
||||
stepsInCasesFlyout.forEach((step) => {
|
||||
it(`step: ${step}, resets to ${AlertsCasesTourSteps.createCase}`, () => {
|
||||
startTour();
|
||||
goToStep(step);
|
||||
assertTourStepExist(step);
|
||||
closeCreateCaseFlyout();
|
||||
assertTourStepNotExist(step);
|
||||
addToCase();
|
||||
assertTourStepExist(AlertsCasesTourSteps.createCase);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export const WELCOME_STEP = '[data-test-subj="welcomeStep"]';
|
||||
export const MANAGE_STEP = '[data-test-subj="manageStep"]';
|
||||
export const ALERTS_STEP = '[data-test-subj="alertsStep"]';
|
||||
export const CASES_STEP = '[data-test-subj="casesStep"]';
|
||||
export const DATA_STEP = '[data-test-subj="dataStep"]';
|
||||
export const ALERTS_STEP_GUIDE_BUTTON = '[data-test-subj="onboarding--stepButton--siem--step3"]';
|
||||
export const COMPLETE_SIEM_GUIDE_BUTTON =
|
||||
'[data-test-subj="onboarding--completeGuideButton--siem"]';
|
||||
|
||||
export const NEXT_STEP_BUTTON = '[data-test-subj="onboarding--securityTourNextStepButton"]';
|
||||
export const END_TOUR_BUTTON = '[data-test-subj="onboarding--securityTourEndButton"]';
|
||||
export const SKIP_TOUR_BUTTON = '[data-test-subj="onboarding--securityTourSkipButton"]';
|
||||
export const COMPLETION_POPOVER = '[data-test-subj="manualCompletionPopover"]';
|
||||
|
||||
export const GLOBAL_TOUR_BUTTON = `[data-test-subj="guideButton"]`;
|
||||
|
||||
export const CLOSE_CREATE_CASE_FLYOUT = `[data-test-subj="create-case-flyout"] [data-test-subj="euiFlyoutCloseButton"]`;
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
const alertsGuideActiveState = {
|
||||
isActive: true,
|
||||
status: 'in_progress',
|
||||
steps: [
|
||||
{ id: 'add_data', status: 'complete' },
|
||||
{ id: 'rules', status: 'complete' },
|
||||
{ id: 'alertsCases', status: 'active' },
|
||||
],
|
||||
guideId: 'security',
|
||||
};
|
||||
|
||||
export const startAlertsCasesTour = () =>
|
||||
cy.request({
|
||||
method: 'PUT',
|
||||
url: 'api/guided_onboarding/state',
|
||||
headers: { 'kbn-xsrf': 'cypress-creds' },
|
||||
body: {
|
||||
status: 'in_progress',
|
||||
guide: alertsGuideActiveState,
|
||||
},
|
||||
});
|
||||
|
||||
export const quitGlobalTour = () =>
|
||||
cy.request({
|
||||
method: 'PUT',
|
||||
url: 'api/guided_onboarding/state',
|
||||
headers: { 'kbn-xsrf': 'cypress-creds' },
|
||||
body: {
|
||||
status: 'quit',
|
||||
guide: {
|
||||
...alertsGuideActiveState,
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
|
@ -5,21 +5,75 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ATTACH_TO_NEW_CASE_BUTTON, TAKE_ACTION_BTN } from '../screens/alerts';
|
||||
import { createCase } from './create_new_case';
|
||||
import {
|
||||
NEXT_STEP_BUTTON,
|
||||
END_TOUR_BUTTON,
|
||||
DATA_STEP,
|
||||
SKIP_TOUR_BUTTON,
|
||||
GLOBAL_TOUR_BUTTON,
|
||||
ALERTS_STEP_GUIDE_BUTTON,
|
||||
COMPLETION_POPOVER,
|
||||
COMPLETE_SIEM_GUIDE_BUTTON,
|
||||
CLOSE_CREATE_CASE_FLYOUT,
|
||||
} from '../screens/guided_onboarding';
|
||||
import { expandFirstAlert } from './alerts';
|
||||
|
||||
export const goToNextStep = (currentStep: string) => {
|
||||
cy.get(`${currentStep} ${NEXT_STEP_BUTTON}`).click();
|
||||
export const goToNextStep = (currentStep: number) => {
|
||||
cy.get(
|
||||
`[data-test-subj="tourStepAnchor-alertsCases-${currentStep}"] ${NEXT_STEP_BUTTON}`
|
||||
).click();
|
||||
};
|
||||
|
||||
export const completeTour = () => {
|
||||
cy.get(`${DATA_STEP} ${END_TOUR_BUTTON}`).click();
|
||||
export const startTour = () => {
|
||||
cy.get(GLOBAL_TOUR_BUTTON).click();
|
||||
cy.get(ALERTS_STEP_GUIDE_BUTTON).click();
|
||||
};
|
||||
|
||||
export const skipTour = () => {
|
||||
cy.get(SKIP_TOUR_BUTTON).click();
|
||||
export const finishTour = () => {
|
||||
cy.get(COMPLETION_POPOVER).should('exist');
|
||||
cy.get(GLOBAL_TOUR_BUTTON).click();
|
||||
cy.get(ALERTS_STEP_GUIDE_BUTTON).click();
|
||||
cy.get(COMPLETE_SIEM_GUIDE_BUTTON).click();
|
||||
};
|
||||
|
||||
export const completeTourWithNextButton = () => {
|
||||
for (let i = 1; i < 6; i++) {
|
||||
goToNextStep(i);
|
||||
}
|
||||
createCase();
|
||||
goToNextStep(7);
|
||||
};
|
||||
|
||||
export const addToCase = () => {
|
||||
cy.get(TAKE_ACTION_BTN).click();
|
||||
cy.get(ATTACH_TO_NEW_CASE_BUTTON).click();
|
||||
};
|
||||
|
||||
export const completeTourWithActions = () => {
|
||||
goToNextStep(1);
|
||||
expandFirstAlert();
|
||||
goToNextStep(3);
|
||||
addToCase();
|
||||
goToNextStep(5);
|
||||
createCase();
|
||||
goToNextStep(7);
|
||||
};
|
||||
|
||||
export const goToStep = (step: number) => {
|
||||
for (let i = 1; i < 6; i++) {
|
||||
if (i === step) {
|
||||
break;
|
||||
}
|
||||
goToNextStep(i);
|
||||
}
|
||||
if (step === 7) {
|
||||
createCase();
|
||||
}
|
||||
};
|
||||
|
||||
export const assertTourStepExist = (step: number) =>
|
||||
cy.get(`[data-test-subj="tourStepAnchor-alertsCases-${step}"]`).should('exist');
|
||||
|
||||
export const assertTourStepNotExist = (step: number) =>
|
||||
cy.get(`[data-test-subj="tourStepAnchor-alertsCases-${step}"]`).should('not.exist');
|
||||
|
||||
export const closeCreateCaseFlyout = () => cy.get(CLOSE_CREATE_CASE_FLYOUT).click();
|
||||
|
|
|
@ -27372,11 +27372,6 @@
|
|||
"xpack.securitySolution.detectionEngine.rules.allRules.columns.tagsTitle": "Balises",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.columns.versionTitle": "Version",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.exportFilenameTitle": "rules_export",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.nextStepLabel": "Aller à l'étape suivante",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.previousStepLabel": "Revenir à l'étape précédente",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.searchCapabilitiesDescription": "Il est maintenant possible de rechercher des règles par modèle d'indexation, tel que \"filebeat-*\", ou par tactique ou technique MITRE ATT&CK™, telle que \"Évasion par la défense \" ou \"TA0005\".",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.searchCapabilitiesTitle": "Capacités de recherche améliorées",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.tourTitle": "Nouveautés",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.filters.customRulesTitle": "Règles personnalisées",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.filters.elasticRulesTitle": "Règles Elastic",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.filters.noRulesBodyTitle": "Nous n'avons trouvé aucune règle avec les filtres ci-dessus.",
|
||||
|
|
|
@ -27347,11 +27347,6 @@
|
|||
"xpack.securitySolution.detectionEngine.rules.allRules.columns.tagsTitle": "タグ",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.columns.versionTitle": "バージョン",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.exportFilenameTitle": "rules_export",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.nextStepLabel": "次のステップに進む",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.previousStepLabel": "前のステップに戻る",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.searchCapabilitiesDescription": "「filebeat-*」などのインデックスパターンや、「Defense Evasion」や「TA0005」などのMITRE ATT&CK™方式または手法でルールを検索できます。",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.searchCapabilitiesTitle": "拡張検索機能",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.tourTitle": "新機能",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.filters.customRulesTitle": "カスタムルール",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.filters.elasticRulesTitle": "Elasticルール",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.filters.noRulesBodyTitle": "上記のフィルターでルールが見つかりませんでした。",
|
||||
|
|
|
@ -27381,11 +27381,6 @@
|
|||
"xpack.securitySolution.detectionEngine.rules.allRules.columns.tagsTitle": "标签",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.columns.versionTitle": "版本",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.exportFilenameTitle": "rules_export",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.nextStepLabel": "前往下一步",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.previousStepLabel": "前往上一步",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.searchCapabilitiesDescription": "现在可以按搜索模式(如“filebeat-*”) 或者 MITRE ATT&CK™ 策略或技术(如“Defense Evasion”或“TA0005”)搜索规则。",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.searchCapabilitiesTitle": "已增强搜索功能",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.featureTour.tourTitle": "最新动态",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.filters.customRulesTitle": "定制规则",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.filters.elasticRulesTitle": "Elastic 规则",
|
||||
"xpack.securitySolution.detectionEngine.rules.allRules.filters.noRulesBodyTitle": "使用上述筛选,我们无法找到任何规则。",
|
||||
|
|
|
@ -52,6 +52,8 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
|
||||
'alertDetailsPageEnabled',
|
||||
])}`,
|
||||
// mock cloud to enable the guided onboarding tour in e2e tests
|
||||
'--xpack.cloud.id=test',
|
||||
`--home.disableWelcomeScreen=true`,
|
||||
],
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue