From 77678a623143bd01b7049a18940ef027ad5f1f5b Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Fri, 27 Oct 2023 10:56:54 +0200 Subject: [PATCH] add functional tests for the dashboard attachment --- .../change_point_detection/fields_config.tsx | 8 +- .../embeddable_change_point_chart.tsx | 3 + .../apps/aiops/change_point_detection.ts | 8 ++ .../aiops/change_point_detection_page.ts | 128 ++++++++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/aiops/public/components/change_point_detection/fields_config.tsx b/x-pack/plugins/aiops/public/components/change_point_detection/fields_config.tsx index c07af22a5f16a..0776bbba908a6 100644 --- a/x-pack/plugins/aiops/public/components/change_point_detection/fields_config.tsx +++ b/x-pack/plugins/aiops/public/components/change_point_detection/fields_config.tsx @@ -236,6 +236,7 @@ const FieldPanel: FC = ({ }), icon: 'plusInCircle', panel: 'attachMainPanel', + 'data-test-subj': 'aiopsChangePointDetectionAttachButton', }, ] : []), @@ -248,6 +249,7 @@ const FieldPanel: FC = ({ disabled: removeDisabled, }, ], + 'data=test-subj': 'aiopsChangePointDetectionContextMenuPanel', }, { id: 'attachMainPanel', @@ -269,6 +271,7 @@ const FieldPanel: FC = ({ defaultMessage: 'To dashboard', }), panel: 'attachToDashboardPanel', + 'data-test-subj': 'aiopsChangePointDetectionAttachToDashboardButton', }, ] : []), @@ -290,6 +293,7 @@ const FieldPanel: FC = ({ ), } : {}), + 'data-test-subj': 'aiopsChangePointDetectionAttachToCaseButton', onClick: () => { openCasesModalCallback({ timeRange, @@ -308,6 +312,7 @@ const FieldPanel: FC = ({ ] : []), ], + 'data-test-subj': 'aiopsChangePointDetectionAttachChartPanel', }, { id: 'attachToDashboardPanel', @@ -318,7 +323,7 @@ const FieldPanel: FC = ({ content: ( - + = ({ }) } compressed + data-test-subj="aiopsChangePointDetectionAttachToDashboardApplyTimeRangeSwitch" /> {isDefined(fieldConfig.splitField) && selectedPartitions.length === 0 ? ( diff --git a/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx b/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx index f9d2109d88df6..3422d980f5fd8 100644 --- a/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx +++ b/x-pack/plugins/aiops/public/embeddable/embeddable_change_point_chart.tsx @@ -113,6 +113,9 @@ export class EmbeddableChangePointChart extends AbstractEmbeddable< // required for the export feature to work this.node.setAttribute('data-shared-item', ''); + // test subject selector for functional tests + this.node.setAttribute('data-test-subj', 'aiopsEmbeddableChangePointChart'); + const I18nContext = this.deps.i18n.Context; const datePickerDeps = { diff --git a/x-pack/test/functional/apps/aiops/change_point_detection.ts b/x-pack/test/functional/apps/aiops/change_point_detection.ts index 0cbff0642aa3c..f643de514c0cb 100644 --- a/x-pack/test/functional/apps/aiops/change_point_detection.ts +++ b/x-pack/test/functional/apps/aiops/change_point_detection.ts @@ -94,5 +94,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await aiops.changePointDetectionPage.addChangePointConfig(); await aiops.changePointDetectionPage.assertPanelExist(1); }); + + it('attaches change point charts to a dashboard', async () => { + await aiops.changePointDetectionPage.assertPanelExist(0); + await aiops.changePointDetectionPage.attachChartsToDashboard(0, { + applyTimeRange: true, + maxSeries: 1, + }); + }); }); } diff --git a/x-pack/test/functional/services/aiops/change_point_detection_page.ts b/x-pack/test/functional/services/aiops/change_point_detection_page.ts index 2eb539ef4fc78..eb9f47b187a64 100644 --- a/x-pack/test/functional/services/aiops/change_point_detection_page.ts +++ b/x-pack/test/functional/services/aiops/change_point_detection_page.ts @@ -9,6 +9,11 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; import { MlTableService } from '../ml/common_table_service'; +interface DashboardAttachmentOptions { + applyTimeRange: boolean; + maxSeries: number; +} + export function ChangePointDetectionPageProvider( { getService, getPageObject }: FtrProviderContext, tableService: MlTableService @@ -18,6 +23,7 @@ export function ChangePointDetectionPageProvider( const comboBox = getService('comboBox'); const browser = getService('browser'); const elasticChart = getService('elasticChart'); + const dashboardPage = getPageObject('dashboard'); return { async navigateToIndexPatternSelection() { @@ -124,6 +130,128 @@ export function ChangePointDetectionPageProvider( }); }, + async openPanelContextMenu(panelIndex: number) { + await testSubjects.click( + `aiopsChangePointPanel_${panelIndex} > aiopsChangePointDetectionContextMenuButton` + ); + await retry.tryForTime(30 * 1000, async () => { + await testSubjects.existOrFail(`aiopsChangePointDetectionAttachButton`); + }); + }, + + async clickAttachChartsButton() { + await testSubjects.click('aiopsChangePointDetectionAttachButton'); + await retry.tryForTime(30 * 1000, async () => { + await testSubjects.missingOrFail(`aiopsChangePointDetectionAttachButton`); + await testSubjects.existOrFail(`aiopsChangePointDetectionAttachToDashboardButton`); + }); + }, + + async clickAttachDashboardButton() { + await testSubjects.click('aiopsChangePointDetectionAttachToDashboardButton'); + await retry.tryForTime(30 * 1000, async () => { + await testSubjects.existOrFail(`aiopsChangePointDetectionDashboardAttachmentForm`); + }); + }, + + async assertApplyTimeRangeControl(expectedValue: boolean) { + const isChecked = await testSubjects.isEuiSwitchChecked( + `aiopsChangePointDetectionAttachToDashboardApplyTimeRangeSwitch` + ); + expect(isChecked).to.eql( + expectedValue, + `Expected apply time range to be ${expectedValue ? 'enabled' : 'disabled'}` + ); + }, + + async assertMaxSeriesControl(expectedValue: number) { + const currentValue = Number( + await testSubjects.getAttribute('aiopsMaxSeriesControlFieldNumber', 'value') + ); + expect(currentValue).to.eql( + expectedValue, + `Expected max series control to be ${expectedValue} (got ${currentValue})` + ); + }, + + async toggleApplyTimeRangeControl(isChecked: boolean) { + await testSubjects.setEuiSwitch( + `aiopsChangePointDetectionAttachToDashboardApplyTimeRangeSwitch`, + isChecked ? 'check' : 'uncheck' + ); + await this.assertApplyTimeRangeControl(isChecked); + }, + + async setMaxSeriesControl(value: number) { + await testSubjects.setValue('aiopsMaxSeriesControlFieldNumber', value.toString()); + await this.assertMaxSeriesControl(value); + }, + + async completeDashboardAttachmentForm(attachmentOptions: DashboardAttachmentOptions) { + // assert default values + await this.assertApplyTimeRangeControl(false); + await this.assertMaxSeriesControl(6); + + if (attachmentOptions.applyTimeRange) { + await this.toggleApplyTimeRangeControl(attachmentOptions.applyTimeRange); + } + + if (attachmentOptions.maxSeries) { + await this.setMaxSeriesControl(attachmentOptions.maxSeries); + } + + await testSubjects.click('aiopsChangePointDetectionSubmitDashboardAttachButton'); + + await retry.tryForTime(30 * 1000, async () => { + // await testSubjects.missingOrFail(`aiopsChangePointDetectionSubmitDashboardAttachButton`); + await testSubjects.existOrFail('savedObjectSaveModal'); + }); + }, + + async completeSaveToDashboardForm(options?: { createNew: boolean; dashboardName?: string }) { + await retry.tryForTime(30 * 1000, async () => { + const dashboardSelector = await testSubjects.find('add-to-dashboard-options'); + + if (options?.createNew) { + const label = await dashboardSelector.findByCssSelector( + `label[for="new-dashboard-option"]` + ); + await label.click(); + } + + await testSubjects.click('confirmSaveSavedObjectButton'); + await retry.waitForWithTimeout('Save modal to disappear', 1000, () => + testSubjects + .missingOrFail('confirmSaveSavedObjectButton') + .then(() => true) + .catch(() => false) + ); + + // make sure the dashboard page actually loaded + const dashboardItemCount = await dashboardPage.getSharedItemsCount(); + expect(dashboardItemCount).to.not.eql(undefined); + }); + // changing to the dashboard app might take some time + const embeddable = await testSubjects.find('aiopsEmbeddableChangePointChart', 30 * 1000); + const lensChart = await embeddable.findByClassName('lnsExpressionRenderer'); + expect(await lensChart.isDisplayed()).to.eql( + true, + 'Change point detection chart should be displayed in dashboard' + ); + }, + + async attachChartsToDashboard( + panelIndex: number, + attachmentOptions: DashboardAttachmentOptions + ) { + await this.assertPanelExist(panelIndex); + await this.openPanelContextMenu(panelIndex); + await this.clickAttachChartsButton(); + await this.clickAttachDashboardButton(); + await this.completeDashboardAttachmentForm(attachmentOptions); + await this.completeSaveToDashboardForm({ createNew: true }); + }, + getTable(index: number) { return tableService.getServiceInstance( 'ChangePointResultsTable',