mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Security Solution] Exceptions: Cypress tests to cover mapping conflicts functionality (#151366)
## Summary This PR adds cypress tests to cover new rule exceptions functionality introduced in [this PR](https://github.com/elastic/kibana/pull/149149). --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
5da80301fc
commit
7f9139f070
9 changed files with 216 additions and 37 deletions
|
@ -226,10 +226,15 @@ export const useField = ({
|
|||
</>
|
||||
);
|
||||
return (
|
||||
<EuiToolTip position="bottom" content={tooltipContent}>
|
||||
<EuiToolTip
|
||||
data-test-subj="mappingConflictsTooltip"
|
||||
position="bottom"
|
||||
content={tooltipContent}
|
||||
>
|
||||
<>
|
||||
{label}
|
||||
<EuiIcon
|
||||
data-test-subj="mappingConflictsWarningIcon"
|
||||
tabIndex={0}
|
||||
type="alert"
|
||||
title={i18n.FIELD_CONFLICT_INDICES_WARNING_TITLE}
|
||||
|
|
|
@ -224,29 +224,40 @@ export const BuilderEntryItem: React.FC<EntryItemProps> = ({
|
|||
id={'1'}
|
||||
buttonContent={
|
||||
<>
|
||||
<EuiIcon tabIndex={0} type="alert" size="s" css={warningIconCss} />
|
||||
<EuiIcon
|
||||
data-test-subj="mappingConflictsAccordionIcon"
|
||||
tabIndex={0}
|
||||
type="alert"
|
||||
size="s"
|
||||
css={warningIconCss}
|
||||
/>
|
||||
{i18n.FIELD_CONFLICT_INDICES_WARNING_DESCRIPTION}
|
||||
</>
|
||||
}
|
||||
arrowDisplay="none"
|
||||
>
|
||||
{conflictsInfo.map((info) => {
|
||||
const groupDetails = info.groupedIndices.map(
|
||||
({ name, count }) =>
|
||||
`${count > 1 ? i18n.CONFLICT_MULTIPLE_INDEX_DESCRIPTION(name, count) : name}`
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<EuiSpacer size="s" />
|
||||
{`${
|
||||
info.totalIndexCount > 1
|
||||
? i18n.CONFLICT_MULTIPLE_INDEX_DESCRIPTION(info.type, info.totalIndexCount)
|
||||
: info.type
|
||||
}: ${groupDetails.join(', ')}`}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
<EuiSpacer size="s" />
|
||||
<div data-test-subj="mappingConflictsDescription">
|
||||
{conflictsInfo.map((info) => {
|
||||
const groupDetails = info.groupedIndices.map(
|
||||
({ name, count }) =>
|
||||
`${count > 1 ? i18n.CONFLICT_MULTIPLE_INDEX_DESCRIPTION(name, count) : name}`
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<EuiSpacer size="s" />
|
||||
{`${
|
||||
info.totalIndexCount > 1
|
||||
? i18n.CONFLICT_MULTIPLE_INDEX_DESCRIPTION(
|
||||
info.type,
|
||||
info.totalIndexCount
|
||||
)
|
||||
: info.type
|
||||
}: ${groupDetails.join(', ')}`}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
<EuiSpacer size="s" />
|
||||
</div>
|
||||
</EuiAccordion>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -30,13 +30,16 @@ import {
|
|||
addExceptionEntryOperatorValue,
|
||||
addExceptionFlyoutItemName,
|
||||
closeExceptionBuilderFlyout,
|
||||
searchExceptionEntryFieldWithPrefix,
|
||||
selectCurrentEntryField,
|
||||
showFieldConflictsWarningTooltipWithMessage,
|
||||
showMappingConflictsWarningMessage,
|
||||
} from '../../../tasks/exceptions';
|
||||
import {
|
||||
ADD_AND_BTN,
|
||||
ADD_OR_BTN,
|
||||
ADD_NESTED_BTN,
|
||||
ENTRY_DELETE_BTN,
|
||||
FIELD_INPUT,
|
||||
LOADING_SPINNER,
|
||||
EXCEPTION_ITEM_CONTAINER,
|
||||
EXCEPTION_FIELD_LIST,
|
||||
|
@ -64,18 +67,23 @@ import { getExceptionList } from '../../../objects/exception';
|
|||
// to test in enzyme and very small changes can inadvertently add
|
||||
// bugs. As the complexity within the builder grows, these should
|
||||
// ensure the most basic logic holds.
|
||||
describe('Exceptions flyout', () => {
|
||||
describe('Exceptions flyout', { testIsolation: false }, () => {
|
||||
before(() => {
|
||||
esArchiverResetKibana();
|
||||
// this is a made-up index that has just the necessary
|
||||
// mappings to conduct tests, avoiding loading large
|
||||
// amounts of data like in auditbeat_exceptions
|
||||
esArchiverLoad('exceptions');
|
||||
esArchiverLoad('conflicts_1');
|
||||
esArchiverLoad('conflicts_2');
|
||||
login();
|
||||
createExceptionList(getExceptionList(), getExceptionList().list_id).then((response) =>
|
||||
createCustomRule({
|
||||
...getNewRule(),
|
||||
dataSource: { index: ['auditbeat-*', 'exceptions-*'], type: 'indexPatterns' },
|
||||
dataSource: {
|
||||
index: ['auditbeat-*', 'exceptions-*', 'conflicts-*'],
|
||||
type: 'indexPatterns',
|
||||
},
|
||||
exceptionLists: [
|
||||
{
|
||||
id: response.body.id,
|
||||
|
@ -95,6 +103,10 @@ describe('Exceptions flyout', () => {
|
|||
goToExceptionsTab();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
closeExceptionBuilderFlyout();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
esArchiverUnload('exceptions');
|
||||
});
|
||||
|
@ -123,8 +135,6 @@ describe('Exceptions flyout', () => {
|
|||
// add value again and button should be enabled again
|
||||
addExceptionEntryFieldMatchAnyValue('test', 0);
|
||||
cy.get(CONFIRM_BTN).should('be.enabled');
|
||||
|
||||
closeExceptionBuilderFlyout();
|
||||
});
|
||||
|
||||
it('Validates custom fields correctly', () => {
|
||||
|
@ -138,8 +148,6 @@ describe('Exceptions flyout', () => {
|
|||
addExceptionEntryFieldValue('blooberty', 0);
|
||||
addExceptionEntryFieldValueValue('blah', 0);
|
||||
cy.get(CONFIRM_BTN).should('be.enabled');
|
||||
|
||||
closeExceptionBuilderFlyout();
|
||||
});
|
||||
|
||||
it('Does not overwrite values and-ed together', () => {
|
||||
|
@ -161,8 +169,6 @@ describe('Exceptions flyout', () => {
|
|||
cy.get(LOADING_SPINNER).should('not.exist');
|
||||
cy.get(FIELD_INPUT_PARENT).eq(0).should('have.text', 'agent.name');
|
||||
cy.get(FIELD_INPUT_PARENT).eq(1).should('have.text', 'c');
|
||||
|
||||
closeExceptionBuilderFlyout();
|
||||
});
|
||||
|
||||
it('Does not overwrite values or-ed together', () => {
|
||||
|
@ -218,8 +224,6 @@ describe('Exceptions flyout', () => {
|
|||
.eq(1)
|
||||
.should('have.text', 'user.id.keyword');
|
||||
cy.get(EXCEPTION_ITEM_CONTAINER).eq(1).should('not.exist');
|
||||
|
||||
closeExceptionBuilderFlyout();
|
||||
});
|
||||
|
||||
it('Does not overwrite values of nested entry items', () => {
|
||||
|
@ -290,19 +294,14 @@ describe('Exceptions flyout', () => {
|
|||
.find(FIELD_INPUT_PARENT)
|
||||
.eq(1)
|
||||
.should('have.text', '@timestamp');
|
||||
|
||||
closeExceptionBuilderFlyout();
|
||||
});
|
||||
|
||||
it('Contains custom index fields', () => {
|
||||
// open add exception modal
|
||||
openExceptionFlyoutFromEmptyViewerPrompt();
|
||||
|
||||
cy.get(FIELD_INPUT).eq(0).click({ force: true });
|
||||
cy.get(FIELD_INPUT).eq(0).type('unique');
|
||||
searchExceptionEntryFieldWithPrefix('unique');
|
||||
cy.get(EXCEPTION_FIELD_LIST).contains('unique_value.test');
|
||||
|
||||
closeExceptionBuilderFlyout();
|
||||
});
|
||||
|
||||
it('Validates auto-suggested fields correctly', () => {
|
||||
|
@ -317,8 +316,28 @@ describe('Exceptions flyout', () => {
|
|||
cy.get(VALUES_INPUT).eq(0).type(`{enter}`);
|
||||
cy.get(VALUES_INPUT).eq(0).type(`{downarrow}{enter}`);
|
||||
cy.get(CONFIRM_BTN).should('be.enabled');
|
||||
});
|
||||
|
||||
closeExceptionBuilderFlyout();
|
||||
it('Warns users about mapping conflicts on problematic field selection', async () => {
|
||||
// open add exception modal
|
||||
openExceptionFlyoutFromEmptyViewerPrompt();
|
||||
|
||||
// find 'doc_id' field which has mapping conflicts accross different indices
|
||||
searchExceptionEntryFieldWithPrefix('doc_id');
|
||||
|
||||
const warningMessage =
|
||||
'This field is defined as different types across the following indices or is unmapped. This can cause unexpected query results.boolean: conflicts-0002long: conflicts-0001';
|
||||
|
||||
// hovering field should show warning tooltip
|
||||
showFieldConflictsWarningTooltipWithMessage(warningMessage);
|
||||
|
||||
// select problematic field
|
||||
selectCurrentEntryField();
|
||||
|
||||
// check that we show warning after the field selection in form of accordion component
|
||||
// underneath the field component and clicking on which reveals the extended warning message
|
||||
// with conflicts details
|
||||
showMappingConflictsWarningMessage(warningMessage);
|
||||
});
|
||||
|
||||
// TODO - Add back in error states into modal
|
||||
|
|
|
@ -68,6 +68,18 @@ export const EXCEPTION_ITEM_CONTAINER = '[data-test-subj="exceptionEntriesContai
|
|||
export const EXCEPTION_FIELD_LIST =
|
||||
'[data-test-subj="comboBoxOptionsList fieldAutocompleteComboBox-optionsList"]';
|
||||
|
||||
export const EXCEPTION_FIELD_MAPPING_CONFLICTS_TOOLTIP =
|
||||
'[data-test-subj="mappingConflictsTooltip"]';
|
||||
|
||||
export const EXCEPTION_FIELD_MAPPING_CONFLICTS_ICON =
|
||||
'[data-test-subj="mappingConflictsWarningIcon"]';
|
||||
|
||||
export const EXCEPTION_FIELD_MAPPING_CONFLICTS_ACCORDION_ICON =
|
||||
'[data-test-subj="mappingConflictsAccordionIcon"]';
|
||||
|
||||
export const EXCEPTION_FIELD_MAPPING_CONFLICTS_DESCRIPTION =
|
||||
'[data-test-subj="mappingConflictsDescription"]';
|
||||
|
||||
export const EXCEPTION_FLYOUT_TITLE = '[data-test-subj="exceptionFlyoutTitle"]';
|
||||
|
||||
export const EXCEPTION_EDIT_FLYOUT_SAVE_BTN = '[data-test-subj="editExceptionConfirmButton"]';
|
||||
|
|
|
@ -24,6 +24,10 @@ import {
|
|||
SHARED_LIST_SWITCH,
|
||||
OS_SELECTION_SECTION,
|
||||
OS_INPUT,
|
||||
EXCEPTION_FIELD_MAPPING_CONFLICTS_ICON,
|
||||
EXCEPTION_FIELD_MAPPING_CONFLICTS_TOOLTIP,
|
||||
EXCEPTION_FIELD_MAPPING_CONFLICTS_ACCORDION_ICON,
|
||||
EXCEPTION_FIELD_MAPPING_CONFLICTS_DESCRIPTION,
|
||||
} from '../screens/exceptions';
|
||||
|
||||
export const addExceptionEntryFieldValueOfItemX = (
|
||||
|
@ -39,6 +43,26 @@ export const addExceptionEntryFieldValueOfItemX = (
|
|||
cy.get(EXCEPTION_FLYOUT_TITLE).click();
|
||||
};
|
||||
|
||||
export const searchExceptionEntryFieldWithPrefix = (fieldPrefix: string, index = 0) => {
|
||||
cy.get(FIELD_INPUT).eq(index).click({ force: true });
|
||||
cy.get(FIELD_INPUT).eq(index).type(fieldPrefix);
|
||||
};
|
||||
|
||||
export const showFieldConflictsWarningTooltipWithMessage = (message: string, index = 0) => {
|
||||
cy.get(EXCEPTION_FIELD_MAPPING_CONFLICTS_ICON).eq(index).trigger('mouseover');
|
||||
cy.get(EXCEPTION_FIELD_MAPPING_CONFLICTS_TOOLTIP).should('be.visible');
|
||||
cy.get(EXCEPTION_FIELD_MAPPING_CONFLICTS_TOOLTIP).should('have.text', message);
|
||||
};
|
||||
|
||||
export const showMappingConflictsWarningMessage = (message: string, index = 0) => {
|
||||
cy.get(EXCEPTION_FIELD_MAPPING_CONFLICTS_ACCORDION_ICON).eq(index).click({ force: true });
|
||||
cy.get(EXCEPTION_FIELD_MAPPING_CONFLICTS_DESCRIPTION).eq(index).should('have.text', message);
|
||||
};
|
||||
|
||||
export const selectCurrentEntryField = (index = 0) => {
|
||||
cy.get(FIELD_INPUT).eq(index).type(`{downarrow}{enter}`);
|
||||
};
|
||||
|
||||
export const addExceptionEntryFieldValue = (field: string, index = 0) => {
|
||||
cy.get(FIELD_INPUT).eq(index).type(`${field}{enter}`);
|
||||
cy.get(EXCEPTION_FLYOUT_TITLE).click();
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "k9V5UIYBpykOpthsKsB8",
|
||||
"index": "conflicts-0001",
|
||||
"source": {
|
||||
"@timestamp": "2023-02-14T00:45:06.527Z",
|
||||
"doc_id": 11111,
|
||||
"my_field": "Value 1",
|
||||
"title" : "Document 1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "o9WEUIYBpykOpthswsA9",
|
||||
"index": "conflicts-0001",
|
||||
"source": {
|
||||
"@timestamp": "2023-02-14T02:45:06.527Z",
|
||||
"doc_id": 2222,
|
||||
"my_field": "Value 2",
|
||||
"title" : "Document 2"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"aliases": {
|
||||
},
|
||||
"index": "conflicts-0001",
|
||||
"mappings": {
|
||||
"dynamic": false,
|
||||
"properties": {
|
||||
"@timestamp":{
|
||||
"type":"date"
|
||||
},
|
||||
"doc_id": {
|
||||
"type": "long"
|
||||
},
|
||||
"my_field": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "tNWLUIYBpykOpthsMsB9",
|
||||
"index": "conflicts-0002",
|
||||
"source": {
|
||||
"@timestamp": "2023-02-14T03:45:06.527Z",
|
||||
"doc_id": false,
|
||||
"my_unique_field": "Value 3",
|
||||
"title" : "Document 3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "ttWLUIYBpykOpthsUMAD",
|
||||
"index": "conflicts-0002",
|
||||
"source": {
|
||||
"@timestamp": "2023-02-14T04:45:06.527Z",
|
||||
"doc_id": true,
|
||||
"my_unique_field": "Value 4",
|
||||
"title" : "Document 4"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"aliases": {
|
||||
},
|
||||
"index": "conflicts-0002",
|
||||
"mappings": {
|
||||
"dynamic": false,
|
||||
"properties": {
|
||||
"@timestamp":{
|
||||
"type":"date"
|
||||
},
|
||||
"doc_id": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"my_field": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue