From 2282d53458fd67d47cfb238df07b0c86d5526402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Thu, 16 Sep 2021 16:05:50 +0200 Subject: [PATCH] [RAC] [Observability] Add functional tests covering the alert workflow status (#111788) --- .../pages/alerts/alerts_table_t_grid.tsx | 1 + .../alerts/workflow_status_filter.test.tsx | 2 +- .../pages/alerts/workflow_status_filter.tsx | 6 +- .../services/observability/alerts.ts | 83 ++++++++++++++--- .../observability/alerts/workflow_status.ts | 90 +++++++++++++++++++ .../apps/observability/index.ts | 1 + 6 files changed, 166 insertions(+), 17 deletions(-) create mode 100644 x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index bca8c8095511..9b6e9e249346 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -277,6 +277,7 @@ function ObservabilityActions({ iconType="boxesHorizontal" aria-label="More" onClick={() => toggleActionsPopover(eventId)} + data-test-subj="alerts-table-row-action-more" /> } isOpen={openActionsPopoverId === eventId} diff --git a/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.test.tsx b/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.test.tsx index cc16f1c5a44a..f7441742ff38 100644 --- a/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.test.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.test.tsx @@ -28,7 +28,7 @@ describe('StatusFilter', () => { const props = { onChange, status }; const { getByTestId } = render(); - const button = getByTestId(`WorkflowStatusFilter ${status} button`); + const button = getByTestId(`workflow-status-filter-${status}-button`); const input = button.querySelector('input') as Element; Simulate.change(input); diff --git a/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.tsx b/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.tsx index 475ba17a9d2f..20073e9937b4 100644 --- a/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/workflow_status_filter.tsx @@ -21,7 +21,7 @@ const options: Array = label: i18n.translate('xpack.observability.alerts.workflowStatusFilter.openButtonLabel', { defaultMessage: 'Open', }), - 'data-test-subj': 'WorkflowStatusFilter open button', + 'data-test-subj': 'workflow-status-filter-open-button', }, { id: 'acknowledged', @@ -31,14 +31,14 @@ const options: Array = defaultMessage: 'Acknowledged', } ), - 'data-test-subj': 'WorkflowStatusFilter acknowledged button', + 'data-test-subj': 'workflow-status-filter-acknowledged-button', }, { id: 'closed', label: i18n.translate('xpack.observability.alerts.workflowStatusFilter.closedButtonLabel', { defaultMessage: 'Closed', }), - 'data-test-subj': 'WorkflowStatusFilter closed button', + 'data-test-subj': 'workflow-status-filter-closed-button', }, ]; diff --git a/x-pack/test/functional/services/observability/alerts.ts b/x-pack/test/functional/services/observability/alerts.ts index ba7f952b30c6..8926d734d731 100644 --- a/x-pack/test/functional/services/observability/alerts.ts +++ b/x-pack/test/functional/services/observability/alerts.ts @@ -6,6 +6,7 @@ */ import querystring from 'querystring'; +import { chunk } from 'lodash'; import { FtrProviderContext } from '../../ftr_provider_context'; import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; @@ -16,12 +17,18 @@ const DATE_WITH_DATA = { }; const ALERTS_FLYOUT_SELECTOR = 'alertsFlyout'; +const ALERTS_TABLE_CONTAINER_SELECTOR = 'events-viewer-panel'; + +const ACTION_COLUMN_INDEX = 1; + +type WorkflowStatus = 'open' | 'acknowledged' | 'closed'; export function ObservabilityAlertsProvider({ getPageObjects, getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const flyoutService = getService('flyout'); const pageObjects = getPageObjects(['common']); const retry = getService('retry'); + const toasts = getService('toasts'); const navigateToTimeWithData = async () => { return await pageObjects.common.navigateToUrlWithBrowserHistory( @@ -31,13 +38,29 @@ export function ObservabilityAlertsProvider({ getPageObjects, getService }: FtrP ); }; + const getTableColumnHeaders = async () => { + const table = await testSubjects.find(ALERTS_TABLE_CONTAINER_SELECTOR); + const tableHeaderRow = await testSubjects.findDescendant('dataGridHeader', table); + const columnHeaders = await tableHeaderRow.findAllByXpath('./div'); + return columnHeaders; + }; + const getTableCells = async () => { // NOTE: This isn't ideal, but EuiDataGrid doesn't really have the concept of "rows" return await testSubjects.findAll('dataGridRowCell'); }; + const getTableCellsInRows = async () => { + const columnHeaders = await getTableColumnHeaders(); + if (columnHeaders.length <= 0) { + return []; + } + const cells = await getTableCells(); + return chunk(cells, columnHeaders.length); + }; + const getTableOrFail = async () => { - return await testSubjects.existOrFail('events-viewer-panel'); + return await testSubjects.existOrFail(ALERTS_TABLE_CONTAINER_SELECTOR); }; const getNoDataStateOrFail = async () => { @@ -109,21 +132,55 @@ export function ObservabilityAlertsProvider({ getPageObjects, getService }: FtrP return await testSubjects.findAllDescendant('alertsFlyoutDescriptionListDescription', flyout); }; + const openActionsMenuForRow = async (rowIndex: number) => { + const rows = await getTableCellsInRows(); + const actionsOverflowButton = await testSubjects.findDescendant( + 'alerts-table-row-action-more', + rows[rowIndex][ACTION_COLUMN_INDEX] + ); + await actionsOverflowButton.click(); + }; + + const setWorkflowStatusForRow = async (rowIndex: number, workflowStatus: WorkflowStatus) => { + await openActionsMenuForRow(rowIndex); + + if (workflowStatus === 'closed') { + await testSubjects.click('close-alert-status'); + } else { + await testSubjects.click(`${workflowStatus}-alert-status`); + } + + // wait for a confirmation toast (the css index is 1-based) + await toasts.getToastElement(1); + await toasts.dismissAllToasts(); + }; + + const setWorkflowStatusFilter = async (workflowStatus: WorkflowStatus) => { + const buttonGroupButton = await testSubjects.find( + `workflow-status-filter-${workflowStatus}-button` + ); + await buttonGroupButton.click(); + }; + return { clearQueryBar, - typeInQueryBar, - submitQuery, - getTableCells, - getTableOrFail, - getNoDataStateOrFail, - openAlertsFlyout, - getAlertsFlyout, - getAlertsFlyoutTitle, closeAlertsFlyout, - navigateToTimeWithData, - getAlertsFlyoutOrFail, - getAlertsFlyoutViewInAppButtonOrFail, - getAlertsFlyoutDescriptionListTitles, + getAlertsFlyout, getAlertsFlyoutDescriptionListDescriptions, + getAlertsFlyoutDescriptionListTitles, + getAlertsFlyoutOrFail, + getAlertsFlyoutTitle, + getAlertsFlyoutViewInAppButtonOrFail, + getNoDataStateOrFail, + getTableCells, + getTableCellsInRows, + getTableColumnHeaders, + getTableOrFail, + navigateToTimeWithData, + openAlertsFlyout, + setWorkflowStatusForRow, + setWorkflowStatusFilter, + submitQuery, + typeInQueryBar, }; } diff --git a/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts new file mode 100644 index 000000000000..d491e239c603 --- /dev/null +++ b/x-pack/test/observability_functional/apps/observability/alerts/workflow_status.ts @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const esArchiver = getService('esArchiver'); + + describe('alert workflow status', function () { + this.tags('includeFirefox'); + + const observability = getService('observability'); + const retry = getService('retry'); + + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); + await observability.alerts.navigateToTimeWithData(); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); + }); + + it('is filtered to only show "open" alerts by default', async () => { + await retry.try(async () => { + const tableRows = await observability.alerts.getTableCellsInRows(); + expect(tableRows.length).to.be(12); + }); + }); + + it('can be set to "acknowledged" using the row menu', async () => { + await observability.alerts.setWorkflowStatusForRow(0, 'acknowledged'); + + await retry.try(async () => { + const tableRows = await observability.alerts.getTableCellsInRows(); + expect(tableRows.length).to.be(11); + }); + }); + + it('can be filtered to only show "acknowledged" alerts using the filter button', async () => { + await observability.alerts.setWorkflowStatusFilter('acknowledged'); + + await retry.try(async () => { + const tableRows = await observability.alerts.getTableCellsInRows(); + expect(tableRows.length).to.be(3); + }); + }); + + it('can be set to "closed" using the row menu', async () => { + await observability.alerts.setWorkflowStatusForRow(0, 'closed'); + + await retry.try(async () => { + const tableRows = await observability.alerts.getTableCellsInRows(); + expect(tableRows.length).to.be(2); + }); + }); + + it('can be filtered to only show "closed" alerts using the filter button', async () => { + await observability.alerts.setWorkflowStatusFilter('closed'); + + await retry.try(async () => { + const tableRows = await observability.alerts.getTableCellsInRows(); + expect(tableRows.length).to.be(4); + }); + }); + + it('can be set to "open" using the row menu', async () => { + await observability.alerts.setWorkflowStatusForRow(0, 'open'); + + await retry.try(async () => { + const tableRows = await observability.alerts.getTableCellsInRows(); + expect(tableRows.length).to.be(3); + }); + }); + + it('can be filtered to only show "open" alerts using the filter button', async () => { + await observability.alerts.setWorkflowStatusFilter('open'); + + await retry.try(async () => { + const tableRows = await observability.alerts.getTableCellsInRows(); + expect(tableRows.length).to.be(12); + }); + }); + }); +}; diff --git a/x-pack/test/observability_functional/apps/observability/index.ts b/x-pack/test/observability_functional/apps/observability/index.ts index fbb401a67b55..b823e1ee0869 100644 --- a/x-pack/test/observability_functional/apps/observability/index.ts +++ b/x-pack/test/observability_functional/apps/observability/index.ts @@ -12,5 +12,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { this.tags('ciGroup6'); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./alerts')); + loadTestFile(require.resolve('./alerts/workflow_status')); }); }