diff --git a/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts b/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts index 82264b2b0516b..576f7c06c8dc8 100644 --- a/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts +++ b/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.ts @@ -124,6 +124,7 @@ export const useDashboardAppState = ({ savedDashboards, kbnUrlStateStorage, initializerContext, + savedObjectsTagging, isEmbeddedExternally, dashboardCapabilities, dispatchDashboardStateChange, diff --git a/test/functional/page_objects/dashboard_page.ts b/test/functional/page_objects/dashboard_page.ts index ecba9549cea02..41a8a3f1768e1 100644 --- a/test/functional/page_objects/dashboard_page.ts +++ b/test/functional/page_objects/dashboard_page.ts @@ -280,9 +280,11 @@ export class DashboardPageObject extends FtrService { } public async clickQuickSave() { - await this.expectQuickSaveButtonEnabled(); - this.log.debug('clickQuickSave'); - await this.testSubjects.click('dashboardQuickSaveMenuItem'); + await this.retry.try(async () => { + await this.expectQuickSaveButtonEnabled(); + this.log.debug('clickQuickSave'); + await this.testSubjects.click('dashboardQuickSaveMenuItem'); + }); } public async clickNewDashboard(continueEditing = false) { @@ -388,10 +390,11 @@ export class DashboardPageObject extends FtrService { */ public async saveDashboard( dashboardName: string, - saveOptions: SaveDashboardOptions = { waitDialogIsClosed: true, exitFromEditMode: true } + saveOptions: SaveDashboardOptions = { waitDialogIsClosed: true, exitFromEditMode: true }, + clickMenuItem = true ) { await this.retry.try(async () => { - await this.enterDashboardTitleAndClickSave(dashboardName, saveOptions); + await this.enterDashboardTitleAndClickSave(dashboardName, saveOptions, clickMenuItem); if (saveOptions.needsConfirm) { await this.ensureDuplicateTitleCallout(); @@ -431,9 +434,12 @@ export class DashboardPageObject extends FtrService { */ public async enterDashboardTitleAndClickSave( dashboardTitle: string, - saveOptions: SaveDashboardOptions = { waitDialogIsClosed: true } + saveOptions: SaveDashboardOptions = { waitDialogIsClosed: true }, + clickMenuItem = true ) { - await this.testSubjects.click('dashboardSaveMenuItem'); + if (clickMenuItem) { + await this.testSubjects.click('dashboardSaveMenuItem'); + } const modalDialog = await this.testSubjects.find('savedObjectSaveModal'); this.log.debug('entering new title'); diff --git a/x-pack/test/functional/apps/dashboard/dashboard_tagging.ts b/x-pack/test/functional/apps/dashboard/dashboard_tagging.ts new file mode 100644 index 0000000000000..707b3877a70b5 --- /dev/null +++ b/x-pack/test/functional/apps/dashboard/dashboard_tagging.ts @@ -0,0 +1,89 @@ +/* + * 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 function ({ getService, getPageObjects }: FtrProviderContext) { + const listingTable = getService('listingTable'); + const testSubjects = getService('testSubjects'); + const esArchiver = getService('esArchiver'); + const find = getService('find'); + const PageObjects = getPageObjects([ + 'common', + 'tagManagement', + 'header', + 'dashboard', + 'visualize', + 'lens', + ]); + + const dashboardTag = 'extremely-cool-dashboard'; + const dashboardTitle = 'Coolest Blank Dashboard'; + + describe('dashboard tagging', () => { + const verifyTagFromListingPage = async () => { + await PageObjects.dashboard.gotoDashboardLandingPage(); + await listingTable.waitUntilTableIsLoaded(); + + // open the filter dropdown + const filterButton = await find.byCssSelector('.euiFilterGroup .euiFilterButton'); + await filterButton.click(); + await testSubjects.click( + `tag-searchbar-option-${PageObjects.tagManagement.testSubjFriendly(dashboardTag)}` + ); + // click elsewhere to close the filter dropdown + const searchFilter = await find.byCssSelector('.euiPageBody .euiFieldSearch'); + await searchFilter.click(); + // wait until the table refreshes + await listingTable.waitUntilTableIsLoaded(); + const itemNames = await listingTable.getAllItemsNames(); + expect(itemNames).to.contain(dashboardTitle); + }; + + const createTagFromDashboard = async () => { + await testSubjects.click('dashboardSaveMenuItem'); + await testSubjects.click('savedObjectTagSelector'); + await testSubjects.click(`tagSelectorOption-action__create`); + + expect(await PageObjects.tagManagement.tagModal.isOpened()).to.be(true); + + await PageObjects.tagManagement.tagModal.fillForm( + { + name: dashboardTag, + color: '#fc03db', + description: '', + }, + { + submit: true, + } + ); + expect(await PageObjects.tagManagement.tagModal.isOpened()).to.be(false); + }; + + before(async () => { + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/lens/basic'); + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.preserveCrossAppState(); + await PageObjects.dashboard.clickNewDashboard(); + }); + + it('adds a new tag to a new Dashboard', async () => { + await createTagFromDashboard(); + PageObjects.dashboard.saveDashboard(dashboardTitle, {}, false); + await verifyTagFromListingPage(); + }); + + it('retains its saved object tags after quicksave', async () => { + await PageObjects.dashboard.gotoDashboardEditMode(dashboardTitle); + await PageObjects.dashboard.useMargins(false); // turn margins off to cause quicksave to be enabled + await PageObjects.dashboard.clickQuickSave(); + await verifyTagFromListingPage(); + }); + }); +} diff --git a/x-pack/test/functional/apps/dashboard/index.ts b/x-pack/test/functional/apps/dashboard/index.ts index 99f8c6ffedefc..83307a7670f5f 100644 --- a/x-pack/test/functional/apps/dashboard/index.ts +++ b/x-pack/test/functional/apps/dashboard/index.ts @@ -17,6 +17,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./drilldowns')); loadTestFile(require.resolve('./sync_colors')); loadTestFile(require.resolve('./_async_dashboard')); + loadTestFile(require.resolve('./dashboard_tagging')); loadTestFile(require.resolve('./dashboard_lens_by_value')); loadTestFile(require.resolve('./dashboard_maps_by_value'));