From c82ca8efb82ef132ed894cdbadc917f582486fba Mon Sep 17 00:00:00 2001 From: Robert Jaszczurek <92210485+rbrtj@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:13:57 +0200 Subject: [PATCH] [ML] Links to the Single Metric Viewer from the Annotations and Forecasts table fix (#192000) ## Summary Fix for: [#191936](https://github.com/elastic/kibana/issues/191936) Fixes navigation from the Forecasts & Annotations table to the Single Metric Viewer. Added functional tests. Tested on 8.15 - issue doesn't exist, it was probably introduced in [#189729](https://github.com/elastic/kibana/pull/189729) ### Checklist - [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../annotations_table/annotations_table.js | 8 +++- .../forecasts_table/forecasts_table.js | 4 +- .../job_expanded_details.ts | 14 ++++++- .../services/ml/job_expanded_details.ts | 37 ++++++++++++++----- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js index b5842e479ba11b..31ac00c1f79db9 100644 --- a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js +++ b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js @@ -223,6 +223,7 @@ class AnnotationsTableUI extends Component { openSingleMetricView = async (annotation = {}) => { const { services: { + chrome: { recentlyAccessed }, application: { navigateToUrl }, share, }, @@ -307,7 +308,12 @@ class AnnotationsTableUI extends Component { { absolute: true } ); - addItemToRecentlyAccessed('timeseriesexplorer', job.job_id, singleMetricViewerLink); + addItemToRecentlyAccessed( + 'timeseriesexplorer', + job.job_id, + singleMetricViewerLink, + recentlyAccessed + ); await navigateToUrl(singleMetricViewerLink); }; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js index 976ea8bc9968bc..5f1cbb1c76ca0e 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/forecasts_table/forecasts_table.js @@ -89,6 +89,7 @@ export class ForecastsTable extends Component { async openSingleMetricView(forecast) { const { services: { + chrome: { recentlyAccessed }, application: { navigateToUrl }, share, }, @@ -156,7 +157,8 @@ export class ForecastsTable extends Component { addItemToRecentlyAccessed( 'timeseriesexplorer', this.props.job.job_id, - singleMetricViewerForecastLink + singleMetricViewerForecastLink, + recentlyAccessed ); await navigateToUrl(singleMetricViewerForecastLink); } diff --git a/x-pack/test/functional/apps/ml/anomaly_detection_jobs/job_expanded_details.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/job_expanded_details.ts index c1c8eee13ba225..e48ca875bb1f26 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection_jobs/job_expanded_details.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/job_expanded_details.ts @@ -83,11 +83,21 @@ export default function ({ getService }: FtrProviderContext) { await ml.jobExpandedDetails.assertJobRowCalendars(jobId, [calendarId]); }); - it('expanded row with forecast should display open forecast button', async () => { - await ml.jobExpandedDetails.assertForecastElements(jobId); + it('expanded row with forecast should navigate to Single Metric Viewer on button click', async () => { + await ml.jobExpandedDetails.openForecastJob(jobId); + }); + + it('expanded row with annotations should navigate to Single Metric Viewer on button click', async () => { + await ml.navigation.navigateToJobManagement(); + + const annotationsFromApi = await ml.api.getAnnotations(jobId); + + await ml.jobExpandedDetails.openAnnotationInSingleMetricViewer(jobId, annotationsFromApi); }); it('expanded row with annotations can be edited', async () => { + await ml.navigation.navigateToJobManagement(); + const annotationsFromApi = await ml.api.getAnnotations(jobId); await ml.jobExpandedDetails.editAnnotation(jobId, 'edited annotation', annotationsFromApi); diff --git a/x-pack/test/functional/services/ml/job_expanded_details.ts b/x-pack/test/functional/services/ml/job_expanded_details.ts index 44e8cb9c09bfd8..d9c82d72eabc4a 100644 --- a/x-pack/test/functional/services/ml/job_expanded_details.ts +++ b/x-pack/test/functional/services/ml/job_expanded_details.ts @@ -46,12 +46,11 @@ export function MachineLearningJobExpandedDetailsProvider( }); }, - async assertForecastElements(jobId: string): Promise { + async openForecastJob(jobId: string): Promise { await jobTable.ensureDetailsOpen(jobId); await this.openForecastTab(jobId); - await testSubjects.existOrFail('mlJobListForecastTabOpenSingleMetricViewButton', { - timeout: 5_000, - }); + await testSubjects.click('mlJobListForecastTabOpenSingleMetricViewButton', 5000); + await testSubjects.existOrFail('mlSingleMetricViewerChart'); }, async clearSearchButton() { @@ -61,16 +60,36 @@ export function MachineLearningJobExpandedDetailsProvider( } }, + async assertAnnotationsFromApi(annotationsFromApi: any) { + const length = annotationsFromApi.length; + expect(length).to.eql( + 1, + `Expect annotations from api to have length of 1, but got [${length}]` + ); + }, + + async openAnnotationInSingleMetricViewer( + jobId: string, + annotationsFromApi: any + ): Promise { + await this.assertAnnotationsFromApi(annotationsFromApi); + + const { _id: annotationId }: { _id: string } = annotationsFromApi[0]; + + await jobTable.ensureDetailsOpen(jobId); + await jobTable.openAnnotationsTab(jobId); + await this.clearSearchButton(); + await jobAnnotationsTable.ensureAnnotationsActionsMenuOpen(annotationId); + await testSubjects.click('mlAnnotationsActionOpenInSingleMetricViewer'); + await testSubjects.existOrFail('mlSingleMetricViewerChart'); + }, + async editAnnotation( jobId: string, newAnnotationText: string, annotationsFromApi: any ): Promise { - const length = annotationsFromApi.length; - expect(length).to.eql( - 1, - `Expect annotions from api to have length of 1, but got [${length}]` - ); + await this.assertAnnotationsFromApi(annotationsFromApi); await jobTable.ensureDetailsOpen(jobId); await jobTable.openAnnotationsTab(jobId);