From fc10fb6b4fc4d5073a1861577a5d643ff321bb3f Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Tue, 28 Jan 2020 10:04:41 +0100 Subject: [PATCH] [SIEM] Fields browser readable (#56000) * extracts methods to tasks * uses cypress api for assertions * refactor * removes tag --- .../integration/lib/fields_browser/helpers.ts | 8 +- .../integration/lib/timeline/selectors.ts | 3 + .../fields_browser/fields_browser.spec.ts | 136 +++++++----------- .../cypress/screens/hosts/fields_browser.ts | 2 - .../screens/timeline/fields_browser.ts | 60 ++++++++ .../siem/cypress/screens/timeline/main.ts | 18 +++ .../cypress/tasks/timeline/fields_browser.ts | 61 ++++++++ .../siem/cypress/tasks/timeline/main.ts | 31 ++++ 8 files changed, 227 insertions(+), 92 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/cypress/screens/timeline/fields_browser.ts create mode 100644 x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts create mode 100644 x-pack/legacy/plugins/siem/cypress/tasks/timeline/fields_browser.ts create mode 100644 x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.ts diff --git a/x-pack/legacy/plugins/siem/cypress/integration/lib/fields_browser/helpers.ts b/x-pack/legacy/plugins/siem/cypress/integration/lib/fields_browser/helpers.ts index 405c8eb34d6fc..b02eda513cba3 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/lib/fields_browser/helpers.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/lib/fields_browser/helpers.ts @@ -4,18 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - FIELDS_BROWSER_CONTAINER, - FIELDS_BROWSER_FILTER_INPUT, - TIMELINE_FIELDS_BUTTON, -} from './selectors'; +import { FIELDS_BROWSER_CONTAINER, FIELDS_BROWSER_FILTER_INPUT } from './selectors'; import { assertAtLeastOneEventMatchesSearch, executeKQL, hostExistsQuery, toggleTimelineVisibility, } from '../timeline/helpers'; -import { TIMELINE_DATA_PROVIDERS } from '../timeline/selectors'; +import { TIMELINE_DATA_PROVIDERS, TIMELINE_FIELDS_BUTTON } from '../timeline/selectors'; /** Opens the timeline's Field Browser */ export const openTimelineFieldsBrowser = () => { diff --git a/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts b/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts index 0ec0c506cbb1a..5515c1f7d58e2 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts @@ -7,6 +7,9 @@ /** A data provider rendered in the timeline's data providers drop area */ export const DATA_PROVIDER = '[data-test-subj="providerContainer"]'; +export const TIMELINE_FIELDS_BUTTON = + '[data-test-subj="timeline"] [data-test-subj="show-field-browser"]'; + /** Data providers are dropped and rendered in this area of the timeline */ export const TIMELINE_DATA_PROVIDERS = '[data-test-subj="dataProviders"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts index d1289732b6d7d..2889d78891a06 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts @@ -4,27 +4,40 @@ * you may not use this file except in compliance with the Elastic License. */ -import { drag, drop } from '../../lib/drag_n_drop/helpers'; -import { - clearFieldsBrowser, - clickOutsideFieldsBrowser, - openTimelineFieldsBrowser, - populateTimeline, - filterFieldsBrowser, -} from '../../lib/fields_browser/helpers'; +import { HOSTS_PAGE } from '../../lib/urls'; + +import { loginAndWaitForPage, DEFAULT_TIMEOUT } from '../../../tasks/login'; + import { + FIELDS_BROWSER_TITLE, + FIELDS_BROWSER_SELECTED_CATEGORY_TITLE, + FIELDS_BROWSER_SELECTED_CATEGORY_COUNT, FIELDS_BROWSER_CATEGORIES_COUNT, - FIELDS_BROWSER_CONTAINER, - FIELDS_BROWSER_FIELDS_COUNT, - FIELDS_BROWSER_FILTER_INPUT, FIELDS_BROWSER_HOST_CATEGORIES_COUNT, - FIELDS_BROWSER_SELECTED_CATEGORY_COUNT, - FIELDS_BROWSER_SELECTED_CATEGORY_TITLE, FIELDS_BROWSER_SYSTEM_CATEGORIES_COUNT, - FIELDS_BROWSER_TITLE, -} from '../../lib/fields_browser/selectors'; -import { HOSTS_PAGE } from '../../lib/urls'; -import { loginAndWaitForPage, DEFAULT_TIMEOUT } from '../../lib/util/helpers'; + FIELDS_BROWSER_FIELDS_COUNT, + FIELDS_BROWSER_MESSAGE_HEADER, + FIELDS_BROWSER_HOST_GEO_CITY_NAME_HEADER, + FIELDS_BROWSER_HOST_GEO_COUNTRY_NAME_HEADER, + FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER, +} from '../../../screens/timeline/fields_browser'; + +import { + openTimeline, + populateTimeline, + openTimelineFieldsBrowser, +} from '../../../tasks/timeline/main'; + +import { + clearFieldsBrowser, + filterFieldsBrowser, + closeFieldsBrowser, + removesMessageField, + addsHostGeoCityNameToTimeline, + addsHostGeoCountryNameToTimelineDraggingIt, + addsHostGeoContinentNameToTimeline, + resetFields, +} from '../../../tasks/timeline/fields_browser'; const defaultHeaders = [ { id: '@timestamp' }, @@ -41,6 +54,7 @@ describe('Fields Browser', () => { context('Fields Browser rendering', () => { before(() => { loginAndWaitForPage(HOSTS_PAGE); + openTimeline(); populateTimeline(); openTimelineFieldsBrowser(); }); @@ -78,7 +92,7 @@ describe('Fields Browser', () => { filterFieldsBrowser(filterInput); - cy.get(FIELDS_BROWSER_CATEGORIES_COUNT) + cy.get(FIELDS_BROWSER_CATEGORIES_COUNT, { timeout: DEFAULT_TIMEOUT }) .invoke('text') .should('eq', '2 categories'); }); @@ -88,18 +102,13 @@ describe('Fields Browser', () => { filterFieldsBrowser(filterInput); - cy.get(FIELDS_BROWSER_FILTER_INPUT, { timeout: DEFAULT_TIMEOUT }).should( - 'not.have.class', - 'euiFieldSearch-isLoading' - ); - cy.get(FIELDS_BROWSER_HOST_CATEGORIES_COUNT) .invoke('text') .then(hostCategoriesCount => { cy.get(FIELDS_BROWSER_SYSTEM_CATEGORIES_COUNT) .invoke('text') .then(systemCategoriesCount => { - cy.get(FIELDS_BROWSER_FIELDS_COUNT) + cy.get(FIELDS_BROWSER_FIELDS_COUNT, { timeout: DEFAULT_TIMEOUT }) .invoke('text') .should('eq', `${+hostCategoriesCount + +systemCategoriesCount} fields`); }); @@ -120,6 +129,7 @@ describe('Fields Browser', () => { context('Editing the timeline', () => { before(() => { loginAndWaitForPage(HOSTS_PAGE); + openTimeline(); populateTimeline(); openTimelineFieldsBrowser(); }); @@ -130,31 +140,17 @@ describe('Fields Browser', () => { }); it('removes the message field from the timeline when the user un-checks the field', () => { - const toggleField = 'message'; - - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'exist' - ); + cy.get(FIELDS_BROWSER_MESSAGE_HEADER).should('exist'); - cy.get( - `[data-test-subj="timeline"] [data-test-subj="field-${toggleField}-checkbox"]` - ).uncheck({ - force: true, - }); + removesMessageField(); + closeFieldsBrowser(); - clickOutsideFieldsBrowser(); - - cy.get(FIELDS_BROWSER_CONTAINER).should('not.exist'); - - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); + cy.get(FIELDS_BROWSER_MESSAGE_HEADER).should('not.exist'); }); it('selects a search results label with the expected count of categories matching the filter input', () => { const category = 'host'; - - filterFieldsBrowser(`${category}.`); + filterFieldsBrowser(category); cy.get(FIELDS_BROWSER_SELECTED_CATEGORY_TITLE) .invoke('text') @@ -163,75 +159,47 @@ describe('Fields Browser', () => { it('adds a field to the timeline when the user clicks the checkbox', () => { const filterInput = 'host.geo.c'; - const toggleField = 'host.geo.city_name'; filterFieldsBrowser(filterInput); + cy.get(FIELDS_BROWSER_HOST_GEO_CITY_NAME_HEADER).should('not.exist'); + addsHostGeoCityNameToTimeline(); + closeFieldsBrowser(); - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); - - cy.get(`[data-test-subj="timeline"] [data-test-subj="field-${toggleField}-checkbox"]`).check({ - force: true, - }); - - clickOutsideFieldsBrowser(); - - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`, { + cy.get(FIELDS_BROWSER_HOST_GEO_CITY_NAME_HEADER, { timeout: DEFAULT_TIMEOUT, }).should('exist'); }); it('adds a field to the timeline when the user drags and drops a field', () => { const filterInput = 'host.geo.c'; - const toggleField = 'host.geo.country_name'; filterFieldsBrowser(filterInput); - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); - - cy.get( - `[data-test-subj="timeline"] [data-test-subj="field-name-${toggleField}"]` - ).then(field => drag(field)); + cy.get(FIELDS_BROWSER_HOST_GEO_COUNTRY_NAME_HEADER).should('not.exist'); - cy.get(`[data-test-subj="timeline"] [data-test-subj="headers-group"]`).then(headersDropArea => - drop(headersDropArea) - ); + addsHostGeoCountryNameToTimelineDraggingIt(); - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`, { + cy.get(FIELDS_BROWSER_HOST_GEO_COUNTRY_NAME_HEADER, { timeout: DEFAULT_TIMEOUT, }).should('exist'); }); it('resets all fields in the timeline when `Reset Fields` is clicked', () => { const filterInput = 'host.geo.c'; - const toggleField = 'host.geo.continent_name'; filterFieldsBrowser(filterInput); - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); - - cy.get(`[data-test-subj="timeline"] [data-test-subj="field-${toggleField}-checkbox"]`).check({ - force: true, - }); + cy.get(FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER).should('not.exist'); - clickOutsideFieldsBrowser(); + addsHostGeoContinentNameToTimeline(); + closeFieldsBrowser(); - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'exist' - ); + cy.get(FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER).should('exist'); openTimelineFieldsBrowser(); + resetFields(); - cy.get('[data-test-subj="timeline"] [data-test-subj="reset-fields"]').click({ force: true }); - - cy.get(`[data-test-subj="timeline"] [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); + cy.get(FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER).should('not.exist'); }); }); }); diff --git a/x-pack/legacy/plugins/siem/cypress/screens/hosts/fields_browser.ts b/x-pack/legacy/plugins/siem/cypress/screens/hosts/fields_browser.ts index f4da73ba5e5f9..252fa7d44a7c7 100644 --- a/x-pack/legacy/plugins/siem/cypress/screens/hosts/fields_browser.ts +++ b/x-pack/legacy/plugins/siem/cypress/screens/hosts/fields_browser.ts @@ -5,8 +5,6 @@ */ /** Clicking this button in the timeline opens the Fields browser */ -export const TIMELINE_FIELDS_BUTTON = - '[data-test-subj="timeline"] [data-test-subj="show-field-browser"]'; /** The title displayed in the fields browser (i.e. Customize Columns) */ export const FIELDS_BROWSER_TITLE = '[data-test-subj="field-browser-title"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/screens/timeline/fields_browser.ts b/x-pack/legacy/plugins/siem/cypress/screens/timeline/fields_browser.ts new file mode 100644 index 0000000000000..aa63aaf89f98b --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/screens/timeline/fields_browser.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const FIELDS_BROWSER_TITLE = '[data-test-subj="field-browser-title"]'; + +/** Typing in this input filters the Field Browser */ +export const FIELDS_BROWSER_FILTER_INPUT = '[data-test-subj="field-search"]'; + +/** The title of the selected category in the right-hand side of the fields browser */ +export const FIELDS_BROWSER_SELECTED_CATEGORY_TITLE = '[data-test-subj="selected-category-title"]'; + +export const FIELDS_BROWSER_SELECTED_CATEGORY_COUNT = + '[data-test-subj="selected-category-count-badge"]'; + +export const FIELDS_BROWSER_CATEGORIES_COUNT = '[data-test-subj="categories-count"]'; + +export const FIELDS_BROWSER_HOST_CATEGORIES_COUNT = '[data-test-subj="host-category-count"]'; + +export const FIELDS_BROWSER_SYSTEM_CATEGORIES_COUNT = '[data-test-subj="system-category-count"]'; + +export const FIELDS_BROWSER_FIELDS_COUNT = '[data-test-subj="fields-count"]'; + +/** Contains the body of the fields browser */ +export const FIELDS_BROWSER_CONTAINER = '[data-test-subj="fields-browser-container"]'; + +export const FIELDS_BROWSER_MESSAGE_HEADER = + '[data-test-subj="timeline"] [data-test-subj="header-text-message"]'; + +export const FIELDS_BROWSER_MESSAGE_CHECKBOX = + '[data-test-subj="timeline"] [data-test-subj="field-message-checkbox"]'; + +export const FIELDS_BROWSER_HOST_GEO_COUNTRY_NAME_HEADER = + '[data-test-subj="header-text-host.geo.country_name"]'; + +export const FIELDS_BROWSER_HOST_GEO_COUNTRY_NAME_CHECKBOX = + '[data-test-subj="field-host.geo.country_name-checkbox"]'; + +export const FIELDS_BROWSER_DRAGGABLE_HOST_GEO_COUNTRY_NAME_HEADER = + '[data-test-subj="timeline"] [data-test-subj="field-name-host.geo.country_name"]'; + +export const FIELDS_BROWSER_HOST_GEO_CITY_NAME_HEADER = + '[data-test-subj="header-text-host.geo.city_name"]'; + +export const FIELDS_BROWSER_HOST_GEO_CITY_NAME_CHECKBOX = + '[data-test-subj="field-host.geo.city_name-checkbox"]'; + +export const FIELDS_BROWSER_HEADER_DROP_AREA = + '[data-test-subj="timeline"] [data-test-subj="headers-group"]'; + +export const FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER = + '[data-test-subj="header-text-host.geo.continent_name"]'; + +export const FIELDS_BROWSER_HOST_GEO_CONTINENT_NAME_CHECKBOX = + '[data-test-subj="field-host.geo.continent_name-checkbox"]'; + +export const FIELDS_BROWSER_RESET_FIELDS = + '[data-test-subj="timeline"] [data-test-subj="reset-fields"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts b/x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts new file mode 100644 index 0000000000000..cf3267d2b650e --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** The `Timeline ^` button that toggles visibility of the Timeline */ +export const TIMELINE_TOGGLE_BUTTON = '[data-test-subj="flyoutOverlay"]'; + +/** Contains the KQL bar for searching or filtering in the timeline */ +export const SEARCH_OR_FILTER_CONTAINER = + '[data-test-subj="timeline-search-or-filter-search-container"]'; + +export const TIMELINE_FIELDS_BUTTON = + '[data-test-subj="timeline"] [data-test-subj="show-field-browser"]'; + +/** The total server-side count of the events matching the timeline's search criteria */ +export const SERVER_SIDE_EVENT_COUNT = '[data-test-subj="server-side-event-count"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/timeline/fields_browser.ts b/x-pack/legacy/plugins/siem/cypress/tasks/timeline/fields_browser.ts new file mode 100644 index 0000000000000..c78eb8f73f650 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/tasks/timeline/fields_browser.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { drag, drop } from '../../integration/lib/drag_n_drop/helpers'; + +import { + FIELDS_BROWSER_FILTER_INPUT, + FIELDS_BROWSER_MESSAGE_CHECKBOX, + FIELDS_BROWSER_HOST_GEO_CITY_NAME_CHECKBOX, + FIELDS_BROWSER_DRAGGABLE_HOST_GEO_COUNTRY_NAME_HEADER, + FIELDS_BROWSER_HEADER_DROP_AREA, + FIELDS_BROWSER_HOST_GEO_CONTINENT_NAME_CHECKBOX, + FIELDS_BROWSER_RESET_FIELDS, +} from '../../screens/timeline/fields_browser'; +import { DEFAULT_TIMEOUT } from '../../integration/lib/util/helpers'; +import { KQL_SEARCH_BAR } from '../../screens/hosts/main'; + +export const clearFieldsBrowser = () => { + cy.get(FIELDS_BROWSER_FILTER_INPUT).type('{selectall}{backspace}'); +}; + +export const filterFieldsBrowser = (fieldName: string) => { + cy.get(FIELDS_BROWSER_FILTER_INPUT) + .type(fieldName) + .should('not.have.class', 'euiFieldSearch-isLoading'); +}; + +export const closeFieldsBrowser = () => { + cy.get(KQL_SEARCH_BAR, { timeout: DEFAULT_TIMEOUT }).click({ force: true }); +}; + +export const removesMessageField = () => { + cy.get(FIELDS_BROWSER_MESSAGE_CHECKBOX).uncheck({ + force: true, + }); +}; + +export const addsHostGeoCityNameToTimeline = () => { + cy.get(FIELDS_BROWSER_HOST_GEO_CITY_NAME_CHECKBOX).check({ + force: true, + }); +}; + +export const addsHostGeoCountryNameToTimelineDraggingIt = () => { + cy.get(FIELDS_BROWSER_DRAGGABLE_HOST_GEO_COUNTRY_NAME_HEADER).should('exist'); + cy.get(FIELDS_BROWSER_DRAGGABLE_HOST_GEO_COUNTRY_NAME_HEADER).then(field => drag(field)); + + cy.get(FIELDS_BROWSER_HEADER_DROP_AREA).then(headersDropArea => drop(headersDropArea)); +}; + +export const addsHostGeoContinentNameToTimeline = () => { + cy.get(FIELDS_BROWSER_HOST_GEO_CONTINENT_NAME_CHECKBOX).check({ + force: true, + }); +}; + +export const resetFields = () => { + cy.get(FIELDS_BROWSER_RESET_FIELDS).click({ force: true }); +}; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.ts b/x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.ts new file mode 100644 index 0000000000000..51026fef757d8 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DEFAULT_TIMEOUT } from '../../integration/lib/util/helpers'; + +import { + TIMELINE_TOGGLE_BUTTON, + SEARCH_OR_FILTER_CONTAINER, + TIMELINE_FIELDS_BUTTON, + SERVER_SIDE_EVENT_COUNT, +} from '../../screens/timeline/main'; + +export const hostExistsQuery = 'host.name: *'; + +export const openTimeline = () => { + cy.get(TIMELINE_TOGGLE_BUTTON, { timeout: DEFAULT_TIMEOUT }).click(); +}; + +export const populateTimeline = () => { + cy.get(`${SEARCH_OR_FILTER_CONTAINER} input`).type(`${hostExistsQuery} {enter}`); + cy.get(SERVER_SIDE_EVENT_COUNT, { timeout: DEFAULT_TIMEOUT }) + .invoke('text') + .should('be.above', 0); +}; + +export const openTimelineFieldsBrowser = () => { + cy.get(TIMELINE_FIELDS_BUTTON).click({ force: true }); +};