mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[Cloud Security] [Misconfigurations] Test coverage for the Alerts workflow (#166788)
This commit is contained in:
parent
f9c35e4971
commit
778dbf26b9
6 changed files with 468 additions and 10 deletions
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { render, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { DetectionRuleCounter } from './detection_rule_counter';
|
||||
import { TestProvider } from '../test/test_provider';
|
||||
import { useFetchDetectionRulesByTags } from '../common/api/use_fetch_detection_rules_by_tags';
|
||||
import { useFetchDetectionRulesAlertsStatus } from '../common/api/use_fetch_detection_rules_alerts_status';
|
||||
import { RuleResponse } from '../common/types';
|
||||
|
||||
jest.mock('../common/api/use_fetch_detection_rules_by_tags', () => ({
|
||||
useFetchDetectionRulesByTags: jest.fn(),
|
||||
}));
|
||||
jest.mock('../common/api/use_fetch_detection_rules_alerts_status', () => ({
|
||||
useFetchDetectionRulesAlertsStatus: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('DetectionRuleCounter', () => {
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
it('should render loading skeleton when both rules and alerts are loading', () => {
|
||||
(useFetchDetectionRulesByTags as jest.Mock).mockReturnValue({
|
||||
data: undefined,
|
||||
isLoading: true,
|
||||
});
|
||||
|
||||
(useFetchDetectionRulesAlertsStatus as jest.Mock).mockReturnValue({
|
||||
data: undefined,
|
||||
isLoading: true,
|
||||
});
|
||||
const { getByTestId } = render(
|
||||
<TestProvider>
|
||||
<DetectionRuleCounter tags={['tag1', 'tag2']} createRuleFn={jest.fn()} />
|
||||
</TestProvider>
|
||||
);
|
||||
|
||||
const skeletonText = getByTestId('csp:detection-rule-counter-loading');
|
||||
expect(skeletonText).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render create rule link when no rules exist', () => {
|
||||
(useFetchDetectionRulesByTags as jest.Mock).mockReturnValue({
|
||||
data: { total: 0 },
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
(useFetchDetectionRulesAlertsStatus as jest.Mock).mockReturnValue({
|
||||
data: null,
|
||||
isLoading: false,
|
||||
isFetching: false,
|
||||
});
|
||||
|
||||
const { getByText, getByTestId } = render(
|
||||
<TestProvider>
|
||||
<DetectionRuleCounter tags={['tag1', 'tag2']} createRuleFn={jest.fn()} />
|
||||
</TestProvider>
|
||||
);
|
||||
|
||||
const createRuleLink = getByTestId('csp:findings-flyout-create-detection-rule-link');
|
||||
expect(createRuleLink).toBeInTheDocument();
|
||||
expect(getByText('Create a detection rule')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render alert and rule count when rules exist', () => {
|
||||
(useFetchDetectionRulesByTags as jest.Mock).mockReturnValue({
|
||||
data: { total: 5 },
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
(useFetchDetectionRulesAlertsStatus as jest.Mock).mockReturnValue({
|
||||
data: { total: 10 },
|
||||
isLoading: false,
|
||||
isFetching: false,
|
||||
});
|
||||
|
||||
const { getByText, getByTestId } = render(
|
||||
<TestProvider>
|
||||
<DetectionRuleCounter tags={['tag1', 'tag2']} createRuleFn={jest.fn()} />
|
||||
</TestProvider>
|
||||
);
|
||||
|
||||
const alertCountLink = getByTestId('csp:findings-flyout-alert-count');
|
||||
const ruleCountLink = getByTestId('csp:findings-flyout-detection-rule-count');
|
||||
|
||||
expect(alertCountLink).toBeInTheDocument();
|
||||
expect(getByText(/10 alerts/i)).toBeInTheDocument();
|
||||
expect(ruleCountLink).toBeInTheDocument();
|
||||
expect(getByText(/5 detection rules/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show loading spinner when creating a rule', async () => {
|
||||
(useFetchDetectionRulesByTags as jest.Mock).mockReturnValue({
|
||||
data: { total: 0 },
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
(useFetchDetectionRulesAlertsStatus as jest.Mock).mockReturnValue({
|
||||
data: null,
|
||||
isLoading: false,
|
||||
isFetching: false,
|
||||
});
|
||||
const createRuleFn = jest.fn(() => Promise.resolve({} as RuleResponse));
|
||||
const { getByTestId, queryByTestId } = render(
|
||||
<TestProvider>
|
||||
<DetectionRuleCounter tags={['tag1', 'tag2']} createRuleFn={createRuleFn} />
|
||||
</TestProvider>
|
||||
);
|
||||
|
||||
// Trigger createDetectionRuleOnClick
|
||||
const createRuleLink = getByTestId('csp:findings-flyout-create-detection-rule-link');
|
||||
userEvent.click(createRuleLink);
|
||||
|
||||
const loadingSpinner = getByTestId('csp:findings-flyout-detection-rule-counter-loading');
|
||||
expect(loadingSpinner).toBeInTheDocument();
|
||||
|
||||
(useFetchDetectionRulesByTags as jest.Mock).mockReturnValue({
|
||||
data: { total: 1 },
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
(useFetchDetectionRulesAlertsStatus as jest.Mock).mockReturnValue({
|
||||
data: { total: 0 },
|
||||
isLoading: false,
|
||||
isFetching: false,
|
||||
});
|
||||
|
||||
// Wait for the loading spinner to disappear
|
||||
await waitFor(() => {
|
||||
expect(queryByTestId('csp:findings-flyout-detection-rule-counter-loading')).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -68,7 +68,12 @@ export const DetectionRuleCounter = ({ tags, createRuleFn }: DetectionRuleCounte
|
|||
}, [createRuleFn, http, notifications, queryClient]);
|
||||
|
||||
return (
|
||||
<EuiSkeletonText lines={1} size="m" isLoading={ruleIsLoading || alertsIsLoading}>
|
||||
<EuiSkeletonText
|
||||
data-test-subj="csp:detection-rule-counter-loading"
|
||||
lines={1}
|
||||
size="m"
|
||||
isLoading={ruleIsLoading || alertsIsLoading}
|
||||
>
|
||||
{rulesData?.total === 0 ? (
|
||||
<>
|
||||
<EuiText size="s">
|
||||
|
@ -78,11 +83,17 @@ export const DetectionRuleCounter = ({ tags, createRuleFn }: DetectionRuleCounte
|
|||
id="xpack.csp.findingsFlyout.alerts.creatingRule"
|
||||
defaultMessage="Creating detection rule"
|
||||
/>{' '}
|
||||
<EuiLoadingSpinner size="s" />
|
||||
<EuiLoadingSpinner
|
||||
size="s"
|
||||
data-test-subj="csp:findings-flyout-detection-rule-counter-loading"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<EuiLink onClick={createDetectionRuleOnClick}>
|
||||
<EuiLink
|
||||
onClick={createDetectionRuleOnClick}
|
||||
data-test-subj="csp:findings-flyout-create-detection-rule-link"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.csp.findingsFlyout.alerts.createRuleAction"
|
||||
defaultMessage="Create a detection rule"
|
||||
|
@ -98,7 +109,7 @@ export const DetectionRuleCounter = ({ tags, createRuleFn }: DetectionRuleCounte
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<EuiLink onClick={alertsPageNavigation}>
|
||||
<EuiLink onClick={alertsPageNavigation} data-test-subj="csp:findings-flyout-alert-count">
|
||||
<FormattedMessage
|
||||
id="xpack.csp.findingsFlyout.alerts.alertCount"
|
||||
defaultMessage="{alertCount, plural, one {# alert} other {# alerts}}"
|
||||
|
@ -109,7 +120,10 @@ export const DetectionRuleCounter = ({ tags, createRuleFn }: DetectionRuleCounte
|
|||
id="xpack.csp.findingsFlyout.alerts.detectedBy"
|
||||
defaultMessage="detected by"
|
||||
/>{' '}
|
||||
<EuiLink onClick={rulePageNavigation}>
|
||||
<EuiLink
|
||||
onClick={rulePageNavigation}
|
||||
data-test-subj="csp:findings-flyout-detection-rule-count"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.csp.findingsFlyout.alerts.detectionRuleCount"
|
||||
defaultMessage="{ruleCount, plural, one {# detection rule} other {# detection rules}}"
|
||||
|
|
|
@ -40,10 +40,11 @@ export const showSuccessToast = (
|
|||
toastLifeTimeMs: 10000,
|
||||
color: 'success',
|
||||
iconType: '',
|
||||
'data-test-subj': 'csp:toast-success',
|
||||
text: toMountPoint(
|
||||
<div>
|
||||
<EuiText size="m">
|
||||
<strong>{ruleResponse.name}</strong>
|
||||
<strong data-test-subj="csp:toast-success-title">{ruleResponse.name}</strong>
|
||||
{` `}
|
||||
<FormattedMessage
|
||||
id="xpack.csp.flyout.ruleCreatedToastTitle"
|
||||
|
@ -58,7 +59,11 @@ export const showSuccessToast = (
|
|||
</EuiText>
|
||||
<EuiFlexGroup justifyContent="flexEnd" gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton size="s" href={http.basePath.prepend(RULE_PAGE_PATH + ruleResponse.id)}>
|
||||
<EuiButton
|
||||
data-test-subj="csp:toast-success-link"
|
||||
size="s"
|
||||
href={http.basePath.prepend(RULE_PAGE_PATH + ruleResponse.id)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.csp.flyout.ruleCreatedToastViewRuleButton"
|
||||
defaultMessage="View rule"
|
||||
|
|
|
@ -55,14 +55,20 @@ export function FindingsPageProvider({ getService, getPageObjects }: FtrProvider
|
|||
refresh: true,
|
||||
}),
|
||||
]),
|
||||
add: async <T>(findingsMock: T[]) => {
|
||||
add: async <
|
||||
T extends {
|
||||
'@timestamp'?: string;
|
||||
}
|
||||
>(
|
||||
findingsMock: T[]
|
||||
) => {
|
||||
await Promise.all([
|
||||
...findingsMock.map((finding) =>
|
||||
es.index({
|
||||
index: FINDINGS_INDEX,
|
||||
body: {
|
||||
...finding,
|
||||
'@timestamp': new Date().toISOString(),
|
||||
'@timestamp': finding['@timestamp'] ?? new Date().toISOString(),
|
||||
},
|
||||
refresh: true,
|
||||
})
|
||||
|
@ -72,7 +78,7 @@ export function FindingsPageProvider({ getService, getPageObjects }: FtrProvider
|
|||
index: FINDINGS_LATEST_INDEX,
|
||||
body: {
|
||||
...finding,
|
||||
'@timestamp': new Date().toISOString(),
|
||||
'@timestamp': finding['@timestamp'] ?? new Date().toISOString(),
|
||||
},
|
||||
refresh: true,
|
||||
})
|
||||
|
@ -81,6 +87,20 @@ export function FindingsPageProvider({ getService, getPageObjects }: FtrProvider
|
|||
},
|
||||
};
|
||||
|
||||
const detectionRuleApi = {
|
||||
remove: async () => {
|
||||
await supertest
|
||||
.post('/api/detection_engine/rules/_bulk_action?dry_run=false')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
|
||||
.send({
|
||||
action: 'delete',
|
||||
query: '',
|
||||
})
|
||||
.expect(200);
|
||||
},
|
||||
};
|
||||
|
||||
const distributionBar = {
|
||||
filterBy: async (type: 'passed' | 'failed') =>
|
||||
testSubjects.click(type === 'failed' ? 'distribution_bar_failed' : 'distribution_bar_passed'),
|
||||
|
@ -203,6 +223,12 @@ export function FindingsPageProvider({ getService, getPageObjects }: FtrProvider
|
|||
await nonStaleElement.click();
|
||||
}
|
||||
},
|
||||
|
||||
async openFlyoutAt(rowIndex: number) {
|
||||
const table = await this.getElement();
|
||||
const flyoutButton = await table.findAllByTestSubject('findings_table_expand_column');
|
||||
await flyoutButton[rowIndex].click();
|
||||
},
|
||||
});
|
||||
|
||||
const navigateToLatestFindingsPage = async () => {
|
||||
|
@ -247,6 +273,41 @@ export function FindingsPageProvider({ getService, getPageObjects }: FtrProvider
|
|||
const notInstalledVulnerabilities = createNotInstalledObject('cnvm-integration-not-installed');
|
||||
const notInstalledCSP = createNotInstalledObject('cloud_posture_page_package_not_installed');
|
||||
|
||||
const createFlyoutObject = (tableTestSubject: string) => ({
|
||||
async getElement() {
|
||||
return await testSubjects.find(tableTestSubject);
|
||||
},
|
||||
async clickTakeActionButton() {
|
||||
const element = await this.getElement();
|
||||
const button = await element.findByCssSelector('[data-test-subj="csp:take_action"] button');
|
||||
await button.click();
|
||||
return button;
|
||||
},
|
||||
async clickTakeActionCreateRuleButton() {
|
||||
await this.clickTakeActionButton();
|
||||
const button = await testSubjects.find('csp:create_rule');
|
||||
await button.click();
|
||||
return button;
|
||||
},
|
||||
async getVisibleText(testSubj: string) {
|
||||
const element = await this.getElement();
|
||||
return await (await element.findByTestSubject(testSubj)).getVisibleText();
|
||||
},
|
||||
});
|
||||
|
||||
const misconfigurationsFlyout = createFlyoutObject('findings_flyout');
|
||||
|
||||
const toastMessage = async (testSubj = 'csp:toast-success') => ({
|
||||
async getElement() {
|
||||
return await testSubjects.find(testSubj);
|
||||
},
|
||||
async clickToastMessageLink(linkTestSubj = 'csp:toast-success-link') {
|
||||
const element = await this.getElement();
|
||||
const link = await element.findByTestSubject(linkTestSubj);
|
||||
await link.click();
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
navigateToLatestFindingsPage,
|
||||
navigateToVulnerabilities,
|
||||
|
@ -259,5 +320,8 @@ export function FindingsPageProvider({ getService, getPageObjects }: FtrProvider
|
|||
index,
|
||||
waitForPluginInitialized,
|
||||
distributionBar,
|
||||
misconfigurationsFlyout,
|
||||
toastMessage,
|
||||
detectionRuleApi,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import Chance from 'chance';
|
||||
import type { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
const retry = getService('retry');
|
||||
const pageObjects = getPageObjects(['common', 'findings', 'header']);
|
||||
const chance = new Chance();
|
||||
|
||||
// We need to use a dataset for the tests to run
|
||||
const data = [
|
||||
{
|
||||
resource: { id: chance.guid(), name: `kubelet`, sub_type: 'lower case sub type' },
|
||||
result: { evaluation: chance.integer() % 2 === 0 ? 'passed' : 'failed' },
|
||||
rule: {
|
||||
tags: ['CIS', 'CIS K8S'],
|
||||
rationale: 'rationale steps for rule 1.1',
|
||||
references: '1. https://elastic.co/rules/1.1',
|
||||
name: 'Upper case rule name',
|
||||
section: 'Upper case section',
|
||||
benchmark: {
|
||||
rule_number: '1.1',
|
||||
id: 'cis_k8s',
|
||||
posture_type: 'kspm',
|
||||
name: 'CIS Kubernetes V1.23',
|
||||
version: 'v1.0.0',
|
||||
remediation: 'remediation guide',
|
||||
},
|
||||
type: 'process',
|
||||
},
|
||||
cluster_id: 'Upper case cluster id',
|
||||
},
|
||||
{
|
||||
'@timestamp': '2023-09-10T14:01:00.000Z',
|
||||
resource: { id: chance.guid(), name: `Pod`, sub_type: 'Upper case sub type' },
|
||||
result: { evaluation: chance.integer() % 2 === 0 ? 'passed' : 'failed' },
|
||||
rule: {
|
||||
tags: ['CIS', 'CIS K8S'],
|
||||
rationale: 'rationale steps',
|
||||
references: '1. https://elastic.co',
|
||||
name: 'lower case rule name',
|
||||
section: 'Another upper case section',
|
||||
benchmark: {
|
||||
rule_number: '1.2',
|
||||
id: 'cis_k8s',
|
||||
posture_type: 'kspm',
|
||||
name: 'CIS Kubernetes V1.23',
|
||||
version: 'v1.0.0',
|
||||
remediation: 'remediation guide',
|
||||
},
|
||||
type: 'process',
|
||||
},
|
||||
cluster_id: 'Another Upper case cluster id',
|
||||
},
|
||||
{
|
||||
'@timestamp': '2023-09-10T14:02:00.000Z',
|
||||
resource: { id: chance.guid(), name: `process`, sub_type: 'another lower case type' },
|
||||
result: { evaluation: 'passed' },
|
||||
rule: {
|
||||
tags: ['CIS', 'CIS K8S'],
|
||||
rationale: 'rationale steps',
|
||||
references: '1. https://elastic.co',
|
||||
name: 'Another upper case rule name',
|
||||
section: 'lower case section',
|
||||
benchmark: {
|
||||
rule_number: '1.3',
|
||||
id: 'cis_k8s',
|
||||
posture_type: 'kspm',
|
||||
name: 'CIS Kubernetes V1.23',
|
||||
version: 'v1.0.0',
|
||||
remediation: 'remediation guide',
|
||||
},
|
||||
type: 'process',
|
||||
},
|
||||
cluster_id: 'lower case cluster id',
|
||||
},
|
||||
{
|
||||
'@timestamp': '2023-09-10T14:03:00.000Z',
|
||||
resource: { id: chance.guid(), name: `process`, sub_type: 'Upper case type again' },
|
||||
result: { evaluation: 'failed' },
|
||||
rule: {
|
||||
tags: ['CIS', 'CIS K8S'],
|
||||
rationale: 'rationale steps',
|
||||
references: '1. https://elastic.co',
|
||||
name: 'some lower case rule name',
|
||||
section: 'another lower case section',
|
||||
benchmark: {
|
||||
rule_number: '1.4',
|
||||
id: 'cis_k8s',
|
||||
posture_type: 'kspm',
|
||||
name: 'CIS Kubernetes V1.23',
|
||||
version: 'v1.0.0',
|
||||
remediation: 'remediation guide',
|
||||
},
|
||||
type: 'process',
|
||||
},
|
||||
cluster_id: 'another lower case cluster id',
|
||||
},
|
||||
];
|
||||
|
||||
const ruleName1 = data[0].rule.name;
|
||||
|
||||
describe('Findings Page - Alerts', function () {
|
||||
this.tags(['cloud_security_posture_findings_alerts']);
|
||||
let findings: typeof pageObjects.findings;
|
||||
let latestFindingsTable: typeof findings.latestFindingsTable;
|
||||
let misconfigurationsFlyout: typeof findings.misconfigurationsFlyout;
|
||||
|
||||
before(async () => {
|
||||
findings = pageObjects.findings;
|
||||
latestFindingsTable = findings.latestFindingsTable;
|
||||
misconfigurationsFlyout = findings.misconfigurationsFlyout;
|
||||
// Before we start any test we must wait for cloud_security_posture plugin to complete its initialization
|
||||
await findings.waitForPluginInitialized();
|
||||
// Prepare mocked findings
|
||||
await findings.index.remove();
|
||||
await findings.index.add(data);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await findings.index.remove();
|
||||
await findings.detectionRuleApi.remove();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await findings.detectionRuleApi.remove();
|
||||
await findings.navigateToLatestFindingsPage();
|
||||
await retry.waitFor(
|
||||
'Findings table to be loaded',
|
||||
async () => (await latestFindingsTable.getRowsCount()) === data.length
|
||||
);
|
||||
pageObjects.header.waitUntilLoadingHasFinished();
|
||||
});
|
||||
|
||||
describe('Create detection rule', () => {
|
||||
it('Creates a detection rule from the Take Action button and navigates to rule page', async () => {
|
||||
await latestFindingsTable.openFlyoutAt(0);
|
||||
await misconfigurationsFlyout.clickTakeActionCreateRuleButton();
|
||||
|
||||
expect(
|
||||
await misconfigurationsFlyout.getVisibleText('csp:findings-flyout-alert-count')
|
||||
).to.be('0 alerts');
|
||||
|
||||
expect(
|
||||
await misconfigurationsFlyout.getVisibleText('csp:findings-flyout-detection-rule-count')
|
||||
).to.be('1 detection rule');
|
||||
|
||||
const toastMessage = await (await findings.toastMessage()).getElement();
|
||||
expect(toastMessage).to.be.ok();
|
||||
|
||||
const toastMessageTitle = await toastMessage.findByTestSubject('csp:toast-success-title');
|
||||
expect(await toastMessageTitle.getVisibleText()).to.be(ruleName1);
|
||||
|
||||
await (await findings.toastMessage()).clickToastMessageLink();
|
||||
|
||||
const rulePageTitle = await testSubjects.find('header-page-title');
|
||||
expect(await rulePageTitle.getVisibleText()).to.be(ruleName1);
|
||||
});
|
||||
it('Creates a detection rule from the Alerts section and navigates to rule page', async () => {
|
||||
await latestFindingsTable.openFlyoutAt(0);
|
||||
const flyout = await misconfigurationsFlyout.getElement();
|
||||
|
||||
await (
|
||||
await flyout.findByTestSubject('csp:findings-flyout-create-detection-rule-link')
|
||||
).click();
|
||||
|
||||
expect(
|
||||
await misconfigurationsFlyout.getVisibleText('csp:findings-flyout-alert-count')
|
||||
).to.be('0 alerts');
|
||||
|
||||
expect(
|
||||
await misconfigurationsFlyout.getVisibleText('csp:findings-flyout-detection-rule-count')
|
||||
).to.be('1 detection rule');
|
||||
|
||||
const toastMessage = await (await findings.toastMessage()).getElement();
|
||||
expect(toastMessage).to.be.ok();
|
||||
|
||||
const toastMessageTitle = await toastMessage.findByTestSubject('csp:toast-success-title');
|
||||
expect(await toastMessageTitle.getVisibleText()).to.be(ruleName1);
|
||||
|
||||
await (await findings.toastMessage()).clickToastMessageLink();
|
||||
|
||||
const rulePageTitle = await testSubjects.find('header-page-title');
|
||||
expect(await rulePageTitle.getVisibleText()).to.be(ruleName1);
|
||||
});
|
||||
});
|
||||
describe('Rule details', () => {
|
||||
it('The rule page contains the expected matching data', async () => {
|
||||
await latestFindingsTable.openFlyoutAt(0);
|
||||
await misconfigurationsFlyout.clickTakeActionCreateRuleButton();
|
||||
|
||||
await (await findings.toastMessage()).clickToastMessageLink();
|
||||
|
||||
const rulePageDescription = await testSubjects.find(
|
||||
'stepAboutRuleDetailsToggleDescriptionText'
|
||||
);
|
||||
expect(await rulePageDescription.getVisibleText()).to.be(data[0].rule.rationale);
|
||||
|
||||
const severity = await testSubjects.find('severity');
|
||||
expect(await severity.getVisibleText()).to.be('Low');
|
||||
|
||||
const referenceUrls = await testSubjects.find('urlsDescriptionReferenceLinkItem');
|
||||
expect(await referenceUrls.getVisibleText()).to.contain('https://elastic.co/rules/1.1');
|
||||
});
|
||||
});
|
||||
describe('Navigation', () => {
|
||||
it('Clicking on count of Rules should navigate to the rules page with benchmark tags as a filter', async () => {
|
||||
await latestFindingsTable.openFlyoutAt(0);
|
||||
await misconfigurationsFlyout.clickTakeActionCreateRuleButton();
|
||||
const flyout = await misconfigurationsFlyout.getElement();
|
||||
await (await flyout.findByTestSubject('csp:findings-flyout-detection-rule-count')).click();
|
||||
|
||||
expect(await (await testSubjects.find('ruleName')).getVisibleText()).to.be(ruleName1);
|
||||
});
|
||||
it('Clicking on count of Alerts should navigate to the alerts page', async () => {
|
||||
await latestFindingsTable.openFlyoutAt(0);
|
||||
await misconfigurationsFlyout.clickTakeActionCreateRuleButton();
|
||||
const flyout = await misconfigurationsFlyout.getElement();
|
||||
await (await flyout.findByTestSubject('csp:findings-flyout-alert-count')).click();
|
||||
|
||||
expect(await (await testSubjects.find('header-page-title')).getVisibleText()).to.be(
|
||||
'Alerts'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -12,6 +12,7 @@ export default function ({ loadTestFile }: FtrProviderContext) {
|
|||
describe('Cloud Security Posture', function () {
|
||||
loadTestFile(require.resolve('./findings_onboarding'));
|
||||
loadTestFile(require.resolve('./findings'));
|
||||
loadTestFile(require.resolve('./findings_alerts'));
|
||||
loadTestFile(require.resolve('./compliance_dashboard'));
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue