From 33cefaac6410c4dad74931728e48a8797754b67b Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Thu, 3 Mar 2022 20:13:40 -0800 Subject: [PATCH] updates exception flyout edit error messages --- .../exceptions/exceptions_flyout.spec.ts | 100 +++++++++++++++++- .../cypress/objects/exception.ts | 11 ++ .../cypress/screens/exceptions.ts | 7 ++ .../cypress/tasks/api_calls/exceptions.ts | 49 ++++++++- .../edit_exception_flyout/index.tsx | 54 ++++++---- 5 files changed, 192 insertions(+), 29 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts index d68def1284468c..e0ee08c15a0243 100644 --- a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts @@ -29,10 +29,19 @@ import { EXCEPTION_ITEM_CONTAINER, ADD_EXCEPTIONS_BTN, EXCEPTION_FIELD_LIST, + EDIT_EXCEPTIONS_BTN, + EXCEPTION_EDIT_FLYOUT_SAVE_BTN, + EXCEPTION_FLYOUT_VERSION_CONFLICT, } from '../../screens/exceptions'; import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; import { cleanKibana, reload } from '../../tasks/common'; +import { + createExceptionList, + createExceptionListItem, + updateExceptionListItem, +} from '../../tasks/api_calls/exceptions'; +import { getExceptionList } from '../../objects/exception'; // NOTE: You might look at these tests and feel they're overkill, // but the exceptions flyout has a lot of logic making it difficult @@ -43,7 +52,20 @@ describe('Exceptions flyout', () => { before(() => { cleanKibana(); loginAndWaitForPageWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - createCustomRule({ ...getNewRule(), index: ['exceptions-*'] }); + createExceptionList(getExceptionList(), getExceptionList().list_id).then((response) => + createCustomRule({ + ...getNewRule(), + index: ['exceptions-*'], + exceptionLists: [ + { + id: response.body.id, + list_id: getExceptionList().list_id, + type: getExceptionList().type, + namespace_type: getExceptionList().namespace_type, + }, + ], + }) + ); reload(); goToRuleDetails(); @@ -61,7 +83,7 @@ describe('Exceptions flyout', () => { esArchiverUnload('exceptions'); }); - it('Does not overwrite values and-ed together', () => { + it.skip('Does not overwrite values and-ed together', () => { cy.get(ADD_EXCEPTIONS_BTN).click({ force: true }); // add multiple entries with invalid field values @@ -79,7 +101,7 @@ describe('Exceptions flyout', () => { closeExceptionBuilderFlyout(); }); - it('Does not overwrite values or-ed together', () => { + it.skip('Does not overwrite values or-ed together', () => { cy.get(ADD_EXCEPTIONS_BTN).click({ force: true }); // exception item 1 @@ -132,7 +154,7 @@ describe('Exceptions flyout', () => { closeExceptionBuilderFlyout(); }); - it('Does not overwrite values of nested entry items', () => { + it.skip('Does not overwrite values of nested entry items', () => { openExceptionFlyoutFromRuleSettings(); cy.get(LOADING_SPINNER).should('not.exist'); @@ -196,7 +218,7 @@ describe('Exceptions flyout', () => { closeExceptionBuilderFlyout(); }); - it('Contains custom index fields', () => { + it.skip('Contains custom index fields', () => { cy.get(ADD_EXCEPTIONS_BTN).click({ force: true }); cy.get(FIELD_INPUT).eq(0).click({ force: true }); @@ -204,4 +226,72 @@ describe('Exceptions flyout', () => { closeExceptionBuilderFlyout(); }); + + context('When updating an item with version conflict', () => { + it('Displays version conflict error', () => { + // create exception item via api + createExceptionListItem(getExceptionList().list_id, { + list_id: getExceptionList().list_id, + item_id: 'simple_list_item', + tags: [], + type: 'simple', + description: 'Test exception item', + name: 'Sample Exception List Item', + namespace_type: 'single', + entries: [ + { + field: 'host.name', + operator: 'included', + type: 'match_any', + value: ['some host', 'another host'], + }, + ], + }); + + cy.reload(); + + goToExceptionsTab(); + + cy.get(EDIT_EXCEPTIONS_BTN).should('be.visible'); + + cy.get(EDIT_EXCEPTIONS_BTN).click({ force: true }); + + // update exception item via api + updateExceptionListItem('simple_list_item', { + name: 'Updated item name', + item_id: 'simple_list_item', + tags: [], + type: 'simple', + description: 'Test exception item', + namespace_type: 'single', + entries: [ + { + field: 'host.name', + operator: 'included', + type: 'match_any', + value: ['some host', 'another host'], + }, + ], + }); + + // try to save and see version conflict error + cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).click({ force: true }); + + cy.get(EXCEPTION_FLYOUT_VERSION_CONFLICT).should('be.visible'); + + closeExceptionBuilderFlyout(); + }); + }); + + context.skip('When updating an item for a list that has since been deleted', () => { + it.skip('Displays missing exception list error', () => { + cy.get(EDIT_EXCEPTIONS_BTN).click({ force: true }); + + // delete exception list via api + + // try to save and see error + + closeExceptionBuilderFlyout(); + }); + }); }); diff --git a/x-pack/plugins/security_solution/cypress/objects/exception.ts b/x-pack/plugins/security_solution/cypress/objects/exception.ts index fbb000f43fdd23..637adc9fc01348 100644 --- a/x-pack/plugins/security_solution/cypress/objects/exception.ts +++ b/x-pack/plugins/security_solution/cypress/objects/exception.ts @@ -22,6 +22,17 @@ export interface ExceptionList { type: 'detection' | 'endpoint'; } +export interface ExceptionListItem { + description: string; + list_id: string; + item_id: string; + name: string; + namespace_type: 'single' | 'agnostic'; + tags: string[]; + type: 'simple'; + entries: Array<{ field: string; operator: string; type: string; value: string[] }>; +} + export const getExceptionList = (): ExceptionList => ({ description: 'Test exception list description', list_id: 'test_exception_list', diff --git a/x-pack/plugins/security_solution/cypress/screens/exceptions.ts b/x-pack/plugins/security_solution/cypress/screens/exceptions.ts index e1b9e0639dfaad..2fd94b82ccc13e 100644 --- a/x-pack/plugins/security_solution/cypress/screens/exceptions.ts +++ b/x-pack/plugins/security_solution/cypress/screens/exceptions.ts @@ -5,6 +5,8 @@ * 2.0. */ +export const EDIT_EXCEPTIONS_BTN = '[data-test-subj="exceptionsViewerEditBtn"]'; + export const ADD_EXCEPTIONS_BTN = '[data-test-subj="exceptionsHeaderAddExceptionBtn"]'; export const CLOSE_ALERTS_CHECKBOX = @@ -61,3 +63,8 @@ export const EXCEPTION_FIELD_LIST = '[data-test-subj="comboBoxOptionsList fieldAutocompleteComboBox-optionsList"]'; export const EXCEPTION_FLYOUT_TITLE = '[data-test-subj="exception-flyout-title"]'; + +export const EXCEPTION_EDIT_FLYOUT_SAVE_BTN = '[data-test-subj="edit-exception-confirm-button"]'; + +export const EXCEPTION_FLYOUT_VERSION_CONFLICT = + '[data-test-subj="exceptionsFlyoutVersionConflict"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/api_calls/exceptions.ts b/x-pack/plugins/security_solution/cypress/tasks/api_calls/exceptions.ts index 7363bd5991b1c2..48722aca8663fc 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/api_calls/exceptions.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/api_calls/exceptions.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ExceptionList } from '../../objects/exception'; +import { ExceptionList, ExceptionListItem } from '../../objects/exception'; export const createExceptionList = ( exceptionList: ExceptionList, @@ -23,3 +23,50 @@ export const createExceptionList = ( headers: { 'kbn-xsrf': 'cypress-creds' }, failOnStatusCode: false, }); + +export const createExceptionListItem = ( + exceptionListId: string, + exceptionListItem?: ExceptionListItem +) => + cy.request({ + method: 'POST', + url: '/api/exception_lists/items', + body: { + list_id: exceptionListItem?.list_id ?? exceptionListId, + item_id: exceptionListItem?.item_id ?? 'simple_list_item', + tags: exceptionListItem?.tags ?? ['user added string for a tag', 'malware'], + type: exceptionListItem?.type ?? 'simple', + description: exceptionListItem?.description ?? 'This is a sample endpoint type exception', + name: exceptionListItem?.name ?? 'Sample Exception List Item', + entries: exceptionListItem?.entries ?? [ + { + field: 'actingProcess.file.signer', + operator: 'excluded', + type: 'exists', + }, + { + field: 'host.name', + operator: 'included', + type: 'match_any', + value: ['some host', 'another host'], + }, + ], + }, + headers: { 'kbn-xsrf': 'cypress-creds' }, + failOnStatusCode: false, + }); + +export const updateExceptionListItem = ( + exceptionListItemId: string, + exceptionListItemUpdate?: Partial +) => + cy.request({ + method: 'PUT', + url: '/api/exception_lists/items', + body: { + item_id: exceptionListItemId, + ...exceptionListItemUpdate, + }, + headers: { 'kbn-xsrf': 'cypress-creds' }, + failOnStatusCode: false, + }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/index.tsx index 6d01908732ec1b..0ed810b4ad2639 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/index.tsx @@ -410,27 +410,35 @@ export const EditExceptionFlyout = memo(function EditExceptionFlyout({ )} - {updateError != null && ( - - - - )} - {hasVersionConflict && ( - - -

{i18n.VERSION_CONFLICT_ERROR_DESCRIPTION}

-
-
- )} - {updateError == null && ( - + + + {hasVersionConflict && ( + <> + +

{i18n.VERSION_CONFLICT_ERROR_DESCRIPTION}

+
+ + + )} + {updateError != null && ( + <> + + + + )} + {updateError === null && ( {i18n.CANCEL} @@ -446,8 +454,8 @@ export const EditExceptionFlyout = memo(function EditExceptionFlyout({ {i18n.EDIT_EXCEPTION_SAVE_BUTTON} -
- )} + )} +
); });