Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security solution] [Explore] Alerts/cases guided onboarding cypress tests #145312

Merged
merged 10 commits into from
Nov 17, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// eslint-disable-next-line no-empty
} catch (e) {}

return {
status: 'not_started',
isActivePeriod: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

before(() => {
login();
});
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';

// need to redo these tests for new implementation
describe.skip('Guided onboarding tour', () => {
describe('Tour is enabled', () => {
beforeEach(() => {
visit(OVERVIEW_URL);
});
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);
});

it('can be completed', () => {
// Step 1: Overview
cy.get(WELCOME_STEP).should('be.visible');
goToNextStep(WELCOME_STEP);
it('Completes the tour with action clicks', () => {
startTour();
completeTourWithActions();
finishTour();
cy.url().should('include', DASHBOARDS_URL);
});

// Step 2: Manage
cy.get(MANAGE_STEP).should('be.visible');
goToNextStep(MANAGE_STEP);
// 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);
});

// Step 3: Alerts
cy.get(ALERTS_STEP).should('be.visible');
goToNextStep(ALERTS_STEP);
describe('persists tour steps in flyout on flyout toggle', () => {
const stepsInAlertsFlyout = [
AlertsCasesTourSteps.reviewAlertDetailsFlyout,
AlertsCasesTourSteps.addAlertToCase,
AlertsCasesTourSteps.viewCase,
];

// Step 4: Cases
cy.get(CASES_STEP).should('be.visible');
goToNextStep(CASES_STEP);
const stepsInCasesFlyout = [AlertsCasesTourSteps.createCase, AlertsCasesTourSteps.submitCase];

// Step 5: Add data
cy.get(DATA_STEP).should('be.visible');
completeTour();
stepsInAlertsFlyout.forEach((step) => {
it(`step: ${step}, resets to ${step}`, () => {
startTour();
goToStep(step);
assertTourStepExist(step);
closeAlertFlyout();
assertTourStepNotExist(step);
expandFirstAlert();
assertTourStepExist(step);
});
});

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);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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"]`;
Original file line number Diff line number Diff line change
@@ -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,
},
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -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();
5 changes: 0 additions & 5 deletions x-pack/plugins/translations/translations/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -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&amp;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.",
Expand Down
5 changes: 0 additions & 5 deletions x-pack/plugins/translations/translations/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -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&amp;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": "上記のフィルターでルールが見つかりませんでした。",
Expand Down
5 changes: 0 additions & 5 deletions x-pack/plugins/translations/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -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&amp;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": "使用上述筛选,我们无法找到任何规则。",
Expand Down
2 changes: 2 additions & 0 deletions x-pack/test/security_solution_cypress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
stephmilovic marked this conversation as resolved.
Show resolved Hide resolved
`--home.disableWelcomeScreen=true`,
],
},
Expand Down