From 3d88ae2428dfd7b7cb92bc3f90fe8577ab227703 Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Fri, 10 Jan 2020 13:46:54 +0100 Subject: [PATCH] [SIEM] Improves event viewer Cypress tests time execution (#54117) * groups tests in context * makes tests fully order-independent * updates Readme file Co-authored-by: Elastic Machine --- x-pack/legacy/plugins/siem/cypress/README.md | 15 +- .../lib/events_viewer/selectors.ts | 2 + .../events_viewer/events_viewer.spec.ts | 243 +++++++++--------- 3 files changed, 138 insertions(+), 122 deletions(-) diff --git a/x-pack/legacy/plugins/siem/cypress/README.md b/x-pack/legacy/plugins/siem/cypress/README.md index fb2b6cd2e3fd30..c9e0d4e18f78f7 100644 --- a/x-pack/legacy/plugins/siem/cypress/README.md +++ b/x-pack/legacy/plugins/siem/cypress/README.md @@ -51,10 +51,23 @@ export const USERNAME = '[data-test-subj="loginUsername"]'; We prefer not to mock API responses in most of our smoke tests, but sometimes it's necessary because a test must assert that a specific value is rendered, and it's not possible to derive that value based on the data in the -envrionment where tests are running. +environment where tests are running. Mocked responses API from the server are located in `siem/cypress/fixtures`. +## Speeding up test execution time + +Loading the web page takes a big amount of time, in order to minimize that impact, the following points should be +taken into consideration until another solution is implemented: + +- Don't refresh the page for every test to clean the state of it. +- Instead, group the tests that are similar in different contexts. +- For every context login only once, clean the state between tests if needed without re-loading the page. +- All tests in a spec file must be order-independent. + - If you need to reload the page to make the tests order-independent, consider to create a new context. + +Remember that minimizing the number of times the web page is loaded, we minimize as well the execution time. + ## Authentication When running tests, there are two ways to specify the credentials used to diff --git a/x-pack/legacy/plugins/siem/cypress/integration/lib/events_viewer/selectors.ts b/x-pack/legacy/plugins/siem/cypress/integration/lib/events_viewer/selectors.ts index 0e3717feef7ad0..6f7906d7fd7910 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/lib/events_viewer/selectors.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/lib/events_viewer/selectors.ts @@ -19,6 +19,8 @@ export const HEADER_SUBTITLE = `${EVENTS_VIEWER_PANEL} [data-test-subj="header-p /** The inspect query modal */ export const INSPECT_MODAL = '[data-test-subj="modal-inspect-euiModal"]'; +export const CLOSE_MODAL = '[data-test-subj="modal-inspect-close"]'; + /** The inspect query button that launches the inspect query modal */ export const INSPECT_QUERY = `${EVENTS_VIEWER_PANEL} [data-test-subj="inspect-icon-button"]`; diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts index 79169d3769a781..1450ee8dc8abf6 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/events_viewer/events_viewer.spec.ts @@ -18,6 +18,7 @@ import { filterSearchBar, } from '../../lib/events_viewer/helpers'; import { + CLOSE_MODAL, EVENTS_VIEWER_PANEL, HEADER_SUBTITLE, INSPECT_MODAL, @@ -39,162 +40,162 @@ const defaultHeadersInDefaultEcsCategory = [ ]; describe('Events Viewer', () => { - beforeEach(() => { - loginAndWaitForPage(HOSTS_PAGE); - - clickEventsTab(); - }); - - it('renders the fields browser with the expected title when the Events Viewer Fields Browser button is clicked', () => { - openEventsViewerFieldsBrowser(); - - cy.get(FIELDS_BROWSER_TITLE) - .invoke('text') - .should('eq', 'Customize Columns'); - }); + context('Fields rendering', () => { + before(() => { + loginAndWaitForPage(HOSTS_PAGE); + clickEventsTab(); + }); - it('closes the fields browser when the user clicks outside of it', () => { - openEventsViewerFieldsBrowser(); + beforeEach(() => { + openEventsViewerFieldsBrowser(); + }); - clickOutsideFieldsBrowser(); + afterEach(() => { + clickOutsideFieldsBrowser(); + cy.get(FIELDS_BROWSER_CONTAINER).should('not.exist'); + }); - cy.get(FIELDS_BROWSER_CONTAINER).should('not.exist'); - }); + it('renders the fields browser with the expected title when the Events Viewer Fields Browser button is clicked', () => { + cy.get(FIELDS_BROWSER_TITLE) + .invoke('text') + .should('eq', 'Customize Columns'); + }); - it('displays the `default ECS` category (by default)', () => { - openEventsViewerFieldsBrowser(); + it('displays the `default ECS` category (by default)', () => { + cy.get(FIELDS_BROWSER_SELECTED_CATEGORY_TITLE) + .invoke('text') + .should('eq', 'default ECS'); + }); - cy.get(FIELDS_BROWSER_SELECTED_CATEGORY_TITLE) - .invoke('text') - .should('eq', 'default ECS'); + it('displays a checked checkbox for all of the default events viewer columns that are also in the default ECS category', () => { + defaultHeadersInDefaultEcsCategory.forEach(header => + cy.get(`[data-test-subj="field-${header.id}-checkbox"]`).should('be.checked') + ); + }); }); - it('displays a checked checkbox for all of the default events viewer columns that are also in the default ECS category', () => { - openEventsViewerFieldsBrowser(); - - defaultHeadersInDefaultEcsCategory.forEach(header => - cy.get(`[data-test-subj="field-${header.id}-checkbox"]`).should('be.checked') - ); - }); + context('Events viewer query modal', () => { + before(() => { + loginAndWaitForPage(HOSTS_PAGE); + clickEventsTab(); + }); - it('removes the message field from the timeline when the user un-checks the field', () => { - const toggleField = 'message'; + after(() => { + cy.get(CLOSE_MODAL).click(); + cy.get(INSPECT_MODAL, { timeout: DEFAULT_TIMEOUT }).should('not.exist'); + }); - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should('exist'); + it('launches the inspect query modal when the inspect button is clicked', () => { + // wait for data to load + cy.get(SERVER_SIDE_EVENT_COUNT, { timeout: DEFAULT_TIMEOUT }) + .should('exist') + .invoke('text', { timeout: DEFAULT_TIMEOUT }) + .should('not.equal', '0'); - openEventsViewerFieldsBrowser(); + cy.get(INSPECT_QUERY, { timeout: DEFAULT_TIMEOUT }) + .should('exist') + .trigger('mousemove', { force: true }) + .click({ force: true }); - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="field-${toggleField}-checkbox"]`).uncheck({ - force: true, + cy.get(INSPECT_MODAL, { timeout: DEFAULT_TIMEOUT }).should('exist'); }); - - clickOutsideFieldsBrowser(); - - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); }); - it('filters the events by applying filter criteria from the search bar at the top of the page', () => { - const filterInput = '4bf34c1c-eaa9-46de-8921-67a4ccc49829'; // this will never match real data - - cy.get(HEADER_SUBTITLE) - .invoke('text') - .then(text1 => { - cy.get(HEADER_SUBTITLE) - .invoke('text', { timeout: DEFAULT_TIMEOUT }) - .should('not.equal', 'Showing: 0 events'); + context('Events viewer fields behaviour', () => { + before(() => { + loginAndWaitForPage(HOSTS_PAGE); + clickEventsTab(); + }); - filterSearchBar(filterInput); + beforeEach(() => { + openEventsViewerFieldsBrowser(); + }); - cy.get(HEADER_SUBTITLE) - .invoke('text') - .should(text2 => { - expect(text1).not.to.eq(text2); - }); - }); - }); + it('adds a field to the events viewer when the user clicks the checkbox', () => { + const filterInput = 'host.geo.c'; + const toggleField = 'host.geo.city_name'; - it('adds a field to the events viewer when the user clicks the checkbox', () => { - const filterInput = 'host.geo.c'; - const toggleField = 'host.geo.city_name'; + filterFieldsBrowser(filterInput); - openEventsViewerFieldsBrowser(); + cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( + 'not.exist' + ); - filterFieldsBrowser(filterInput); + cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="field-${toggleField}-checkbox"]`).check({ + force: true, + }); - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); + clickOutsideFieldsBrowser(); - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="field-${toggleField}-checkbox"]`).check({ - force: true, + cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( + 'exist' + ); }); - clickOutsideFieldsBrowser(); + it('resets all fields in the events viewer when `Reset Fields` is clicked', () => { + const filterInput = 'host.geo.c'; + const toggleField = 'host.geo.country_name'; - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should('exist'); - }); + filterFieldsBrowser(filterInput); - it('loads more events when the load more button is clicked', () => { - cy.get(LOCAL_EVENTS_COUNT, { timeout: DEFAULT_TIMEOUT }) - .invoke('text') - .then(text1 => { - cy.get(LOCAL_EVENTS_COUNT) - .invoke('text') - .should('equal', '25'); - - cy.get(LOAD_MORE).click({ force: true }); - - cy.get(LOCAL_EVENTS_COUNT) - .invoke('text') - .should(text2 => { - expect(text1).not.to.eq(text2); - }); - }); - }); + cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( + 'not.exist' + ); - it('launches the inspect query modal when the inspect button is clicked', () => { - // wait for data to load - cy.get(SERVER_SIDE_EVENT_COUNT, { timeout: DEFAULT_TIMEOUT }) - .should('exist') - .invoke('text', { timeout: DEFAULT_TIMEOUT }) - .should('not.equal', '0'); + cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="field-${toggleField}-checkbox"]`).check({ + force: true, + }); - cy.get(INSPECT_QUERY, { timeout: DEFAULT_TIMEOUT }) - .should('exist') - .trigger('mousemove', { force: true }) - .click({ force: true }); + cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="reset-fields"]`).click({ force: true }); - cy.get(INSPECT_MODAL, { timeout: DEFAULT_TIMEOUT }).should('exist'); + cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( + 'not.exist' + ); + }); }); - it('resets all fields in the events viewer when `Reset Fields` is clicked', () => { - const filterInput = 'host.geo.c'; - const toggleField = 'host.geo.city_name'; - - openEventsViewerFieldsBrowser(); - - filterFieldsBrowser(filterInput); - - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); - - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="field-${toggleField}-checkbox"]`).check({ - force: true, + context('Events behaviour', () => { + before(() => { + loginAndWaitForPage(HOSTS_PAGE); + clickEventsTab(); }); - clickOutsideFieldsBrowser(); + it('filters the events by applying filter criteria from the search bar at the top of the page', () => { + const filterInput = '4bf34c1c-eaa9-46de-8921-67a4ccc49829'; // this will never match real data - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should('exist'); + cy.get(HEADER_SUBTITLE) + .invoke('text') + .then(text1 => { + cy.get(HEADER_SUBTITLE) + .invoke('text', { timeout: DEFAULT_TIMEOUT }) + .should('not.equal', 'Showing: 0 events'); - openEventsViewerFieldsBrowser(); + filterSearchBar(filterInput); - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="reset-fields"]`).click({ force: true }); + cy.get(HEADER_SUBTITLE) + .invoke('text') + .should(text2 => { + expect(text1).not.to.eq(text2); + }); + }); + }); - cy.get(`${EVENTS_VIEWER_PANEL} [data-test-subj="header-text-${toggleField}"]`).should( - 'not.exist' - ); + it('loads more events when the load more button is clicked', () => { + cy.get(LOCAL_EVENTS_COUNT, { timeout: DEFAULT_TIMEOUT }) + .invoke('text') + .then(text1 => { + cy.get(LOCAL_EVENTS_COUNT) + .invoke('text') + .should('equal', '25'); + + cy.get(LOAD_MORE).click({ force: true }); + + cy.get(LOCAL_EVENTS_COUNT) + .invoke('text') + .should(text2 => { + expect(text1).not.to.eq(text2); + }); + }); + }); }); });