Skip to content

Commit b4041e1

Browse files
committed
[SIEM] Adds 'Load prebuilt rules' Cypress test (#59529)
* adds 'load prebuilt rules' * fixes typecheck issue * updates jest snapshot
1 parent bbb428c commit b4041e1

13 files changed

Lines changed: 250 additions & 83 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { ELASTIC_RULES_BTN, RULES_TABLE, RULES_ROW } from '../screens/signal_detection_rules';
8+
9+
import {
10+
changeToThreeHundredRowsPerPage,
11+
loadPrebuiltDetectionRules,
12+
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded,
13+
waitForPrebuiltDetectionRulesToBeLoaded,
14+
waitForRulesToBeLoaded,
15+
} from '../tasks/signal_detection_rules';
16+
import {
17+
goToManageSignalDetectionRules,
18+
waitForSignalsIndexToBeCreated,
19+
waitForSignalsPanelToBeLoaded,
20+
} from '../tasks/detections';
21+
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
22+
23+
import { DETECTIONS } from '../urls/navigation';
24+
25+
describe('Signal detection rules', () => {
26+
before(() => {
27+
loginAndWaitForPageWithoutDateRange(DETECTIONS);
28+
});
29+
it('Loads prebuilt rules', () => {
30+
waitForSignalsPanelToBeLoaded();
31+
waitForSignalsIndexToBeCreated();
32+
goToManageSignalDetectionRules();
33+
waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded();
34+
loadPrebuiltDetectionRules();
35+
waitForPrebuiltDetectionRulesToBeLoaded();
36+
37+
const expectedElasticRulesBtnText = 'Elastic rules (92)';
38+
cy.get(ELASTIC_RULES_BTN)
39+
.invoke('text')
40+
.should('eql', expectedElasticRulesBtnText);
41+
42+
changeToThreeHundredRowsPerPage();
43+
waitForRulesToBeLoaded();
44+
45+
const expectedNumberOfRules = 92;
46+
cy.get(RULES_TABLE).then($table => {
47+
cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules);
48+
});
49+
});
50+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
export const LOADING_SIGNALS_PANEL = '[data-test-subj="loading-signals-panel"]';
8+
9+
export const MANAGE_SIGNAL_DETECTION_RULES_BTN = '[data-test-subj="manage-signal-detection-rules"]';
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
export const ELASTIC_RULES_BTN = '[data-test-subj="show-elastic-rules-filter-button"]';
8+
9+
export const LOAD_PREBUILT_RULES_BTN = '[data-test-subj="load-prebuilt-rules"]';
10+
11+
export const LOADING_INITIAL_PREBUILT_RULES_TABLE =
12+
'[data-test-subj="initialLoadingPanelAllRulesTable"]';
13+
14+
export const LOADING_SPINNER = '[data-test-subj="loading-spinner"]';
15+
16+
export const PAGINATION_POPOVER_BTN = '[data-test-subj="tablePaginationPopoverButton"]';
17+
18+
export const RULES_TABLE = '[data-test-subj="rules-table"]';
19+
20+
export const RULES_ROW = '.euiTableRow';
21+
22+
export const THREE_HUNDRED_ROWS = '[data-test-subj="tablePagination-300-rows"]';
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { LOADING_SIGNALS_PANEL, MANAGE_SIGNAL_DETECTION_RULES_BTN } from '../screens/detections';
8+
9+
export const goToManageSignalDetectionRules = () => {
10+
cy.get(MANAGE_SIGNAL_DETECTION_RULES_BTN)
11+
.should('exist')
12+
.click({ force: true });
13+
};
14+
15+
export const waitForSignalsIndexToBeCreated = () => {
16+
cy.request({ url: '/api/detection_engine/index', retryOnStatusCodeFailure: true }).then(
17+
response => {
18+
if (response.status !== 200) {
19+
cy.wait(7500);
20+
}
21+
}
22+
);
23+
};
24+
25+
export const waitForSignalsPanelToBeLoaded = () => {
26+
cy.get(LOADING_SIGNALS_PANEL).should('exist');
27+
cy.get(LOADING_SIGNALS_PANEL).should('not.exist');
28+
};
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import {
8+
LOAD_PREBUILT_RULES_BTN,
9+
LOADING_INITIAL_PREBUILT_RULES_TABLE,
10+
LOADING_SPINNER,
11+
PAGINATION_POPOVER_BTN,
12+
RULES_TABLE,
13+
THREE_HUNDRED_ROWS,
14+
} from '../screens/signal_detection_rules';
15+
16+
export const changeToThreeHundredRowsPerPage = () => {
17+
cy.get(PAGINATION_POPOVER_BTN).click({ force: true });
18+
cy.get(THREE_HUNDRED_ROWS).click();
19+
};
20+
21+
export const loadPrebuiltDetectionRules = () => {
22+
cy.get(LOAD_PREBUILT_RULES_BTN)
23+
.should('exist')
24+
.click({ force: true });
25+
};
26+
27+
export const waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded = () => {
28+
cy.get(LOADING_INITIAL_PREBUILT_RULES_TABLE).should('exist');
29+
cy.get(LOADING_INITIAL_PREBUILT_RULES_TABLE).should('not.exist');
30+
};
31+
32+
export const waitForPrebuiltDetectionRulesToBeLoaded = () => {
33+
cy.get(LOAD_PREBUILT_RULES_BTN).should('not.exist');
34+
cy.get(RULES_TABLE).should('exist');
35+
};
36+
37+
export const waitForRulesToBeLoaded = () => {
38+
cy.get(LOADING_SPINNER).should('exist');
39+
cy.get(LOADING_SPINNER).should('not.exist');
40+
};

x-pack/legacy/plugins/siem/cypress/urls/navigation.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7+
export const DETECTIONS = 'app/siem#/detections';
78
export const HOSTS_PAGE = '/app/siem#/hosts/allHosts';
89
export const HOSTS_PAGE_TAB_URLS = {
910
allHosts: '/app/siem#/hosts/allHosts',

x-pack/legacy/plugins/siem/public/components/loader/__snapshots__/index.test.tsx.snap

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/legacy/plugins/siem/public/components/loader/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const Loader = React.memo<LoaderProps>(({ children, overlay, overlayBackg
6262
<Aside overlay={overlay} overlayBackground={overlayBackground}>
6363
<FlexGroup overlay={{ overlay }}>
6464
<EuiFlexItem grow={false}>
65-
<EuiLoadingSpinner size={size} />
65+
<EuiLoadingSpinner data-test-subj="loading-spinner" size={size} />
6666
</EuiFlexItem>
6767

6868
{children && (

x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ const SignalsTableComponent: React.FC<SignalsTableComponentProps> = ({
290290
return (
291291
<EuiPanel>
292292
<HeaderSection title={i18n.SIGNALS_TABLE_TITLE} />
293-
<EuiLoadingContent />
293+
<EuiLoadingContent data-test-subj="loading-signals-panel" />
294294
</EuiPanel>
295295
);
296296
}

x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx

Lines changed: 90 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import { useParams } from 'react-router-dom';
1010
import { StickyContainer } from 'react-sticky';
1111
import { connect, ConnectedProps } from 'react-redux';
1212

13-
import { useGlobalTime } from '../../containers/global_time';
14-
import { useWithSource } from '../../containers/source';
13+
import { GlobalTime } from '../../containers/global_time';
14+
import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source';
1515
import { AlertsTable } from '../../components/alerts_viewer/alerts_table';
1616
import { FiltersGlobal } from '../../components/filters_global';
1717
import {
@@ -88,10 +88,6 @@ const DetectionEnginePageComponent: React.FC<PropsFromRedux> = ({
8888
signalIndexName,
8989
]);
9090

91-
const { indexPattern, contentAvailable } = useWithSource(indexToAdd);
92-
93-
const { to, from, deleteQuery, setQuery } = useGlobalTime();
94-
9591
if (isUserAuthenticated != null && !isUserAuthenticated && !loading) {
9692
return (
9793
<WrapperPage>
@@ -113,81 +109,94 @@ const DetectionEnginePageComponent: React.FC<PropsFromRedux> = ({
113109
<>
114110
{hasEncryptionKey != null && !hasEncryptionKey && <NoApiIntegrationKeyCallOut />}
115111
{hasIndexWrite != null && !hasIndexWrite && <NoWriteSignalsCallOut />}
116-
{contentAvailable ? (
117-
<StickyContainer>
118-
<FiltersGlobal>
119-
<SiemSearchBar id="global" indexPattern={indexPattern} />
120-
</FiltersGlobal>
121-
<WrapperPage>
122-
<DetectionEngineHeaderPage
123-
subtitle={
124-
lastSignals != null && (
125-
<>
126-
{i18n.LAST_SIGNAL}
127-
{': '}
128-
{lastSignals}
129-
</>
130-
)
131-
}
132-
title={i18n.PAGE_TITLE}
133-
>
134-
<EuiButton fill href={getRulesUrl()} iconType="gear">
135-
{i18n.BUTTON_MANAGE_RULES}
136-
</EuiButton>
137-
</DetectionEngineHeaderPage>
138-
139-
<>
140-
<SiemNavigation navTabs={detectionsTabs} />
141-
<EuiSpacer />
142-
{tabName === DetectionEngineTab.signals && (
143-
<>
144-
<SignalsHistogramPanel
145-
deleteQuery={deleteQuery}
146-
filters={filters}
147-
from={from}
148-
query={query}
149-
setQuery={setQuery}
150-
showTotalSignalsCount={true}
151-
signalIndexName={signalIndexName}
152-
stackByOptions={signalsHistogramOptions}
153-
to={to}
154-
updateDateRange={updateDateRangeCallback}
155-
/>
156-
<EuiSpacer size="l" />
157-
<SignalsTable
158-
loading={loading}
159-
hasIndexWrite={hasIndexWrite ?? false}
160-
canUserCRUD={(canUserCRUD ?? false) && (hasEncryptionKey ?? false)}
161-
from={from}
162-
signalsIndex={signalIndexName ?? ''}
163-
to={to}
164-
/>
165-
</>
166-
)}
167-
{tabName === DetectionEngineTab.alerts && (
168-
<>
169-
<AlertsByCategory
170-
deleteQuery={deleteQuery}
171-
filters={filters}
172-
from={from}
173-
hideHeaderChildren={true}
174-
indexPattern={indexPattern}
175-
query={query}
176-
setQuery={setQuery}
177-
to={to}
178-
/>
179-
<AlertsTable endDate={to} startDate={from} />
180-
</>
181-
)}
182-
</>
183-
</WrapperPage>
184-
</StickyContainer>
185-
) : (
186-
<WrapperPage>
187-
<DetectionEngineHeaderPage border title={i18n.PAGE_TITLE} />
188-
<DetectionEngineEmptyPage />
189-
</WrapperPage>
190-
)}
112+
<WithSource sourceId="default" indexToAdd={indexToAdd}>
113+
{({ indicesExist, indexPattern }) => {
114+
return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? (
115+
<StickyContainer>
116+
<FiltersGlobal>
117+
<SiemSearchBar id="global" indexPattern={indexPattern} />
118+
</FiltersGlobal>
119+
<WrapperPage>
120+
<DetectionEngineHeaderPage
121+
subtitle={
122+
lastSignals != null && (
123+
<>
124+
{i18n.LAST_SIGNAL}
125+
{': '}
126+
{lastSignals}
127+
</>
128+
)
129+
}
130+
title={i18n.PAGE_TITLE}
131+
>
132+
<EuiButton
133+
fill
134+
href={getRulesUrl()}
135+
iconType="gear"
136+
data-test-subj="manage-signal-detection-rules"
137+
>
138+
{i18n.BUTTON_MANAGE_RULES}
139+
</EuiButton>
140+
</DetectionEngineHeaderPage>
141+
142+
<GlobalTime>
143+
{({ to, from, deleteQuery, setQuery }) => (
144+
<>
145+
<SiemNavigation navTabs={detectionsTabs} />
146+
<EuiSpacer />
147+
{tabName === DetectionEngineTab.signals && (
148+
<>
149+
<SignalsHistogramPanel
150+
deleteQuery={deleteQuery}
151+
filters={filters}
152+
from={from}
153+
query={query}
154+
setQuery={setQuery}
155+
showTotalSignalsCount={true}
156+
signalIndexName={signalIndexName}
157+
stackByOptions={signalsHistogramOptions}
158+
to={to}
159+
updateDateRange={updateDateRangeCallback}
160+
/>
161+
<EuiSpacer size="l" />
162+
<SignalsTable
163+
loading={loading}
164+
hasIndexWrite={hasIndexWrite ?? false}
165+
canUserCRUD={(canUserCRUD ?? false) && (hasEncryptionKey ?? false)}
166+
from={from}
167+
signalsIndex={signalIndexName ?? ''}
168+
to={to}
169+
/>
170+
</>
171+
)}
172+
{tabName === DetectionEngineTab.alerts && (
173+
<>
174+
<AlertsByCategory
175+
deleteQuery={deleteQuery}
176+
filters={filters}
177+
from={from}
178+
hideHeaderChildren={true}
179+
indexPattern={indexPattern}
180+
query={query}
181+
setQuery={setQuery}
182+
to={to}
183+
/>
184+
<AlertsTable endDate={to} startDate={from} />
185+
</>
186+
)}
187+
</>
188+
)}
189+
</GlobalTime>
190+
</WrapperPage>
191+
</StickyContainer>
192+
) : (
193+
<WrapperPage>
194+
<DetectionEngineHeaderPage border title={i18n.PAGE_TITLE} />
195+
<DetectionEngineEmptyPage />
196+
</WrapperPage>
197+
);
198+
}}
199+
</WithSource>
191200
<SpyRoute />
192201
</>
193202
);

0 commit comments

Comments
 (0)