diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts index 417d8227b121c6..43404c32cb3d4f 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts @@ -174,7 +174,7 @@ export class IndexPattern implements IIndexPattern { private updateFromElasticSearch(response: any, forceFieldRefresh: boolean = false) { if (!response.found) { - throw new SavedObjectNotFound(type, this.id, '#/management/kibana/indexPatterns'); + throw new SavedObjectNotFound(type, this.id, 'kibana#/management/kibana/indexPatterns'); } _.forOwn(this.mapping, (fieldMapping: FieldMappingSpec, name: string | undefined) => { diff --git a/test/functional/apps/dashboard/dashboard_error_handling.ts b/test/functional/apps/dashboard/dashboard_error_handling.ts new file mode 100644 index 00000000000000..6bd8327a110b9f --- /dev/null +++ b/test/functional/apps/dashboard/dashboard_error_handling.ts @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const PageObjects = getPageObjects(['dashboard', 'header', 'common']); + const browser = getService('browser'); + const testSubjects = getService('testSubjects'); + + /** + * Common test suite for testing exception scenarious within dashboard + */ + describe('dashboard error handling', () => { + before(async () => { + await esArchiver.loadIfNeeded('dashboard/current/kibana'); + await PageObjects.common.navigateToApp('dashboard'); + }); + + // wrapping into own describe to make sure new tab is cleaned up even if test failed + // see: https://github.com/elastic/kibana/pull/67280#discussion_r430528122 + describe('recreate index pattern link works', () => { + let tabsCount = 1; + it('recreate index pattern link works', async () => { + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.loadSavedDashboard('dashboard with missing index pattern'); + await PageObjects.header.waitUntilLoadingHasFinished(); + const errorEmbeddable = await testSubjects.find('embeddableStackError'); + await (await errorEmbeddable.findByTagName('a')).click(); + await browser.switchTab(1); + tabsCount++; + await testSubjects.existOrFail('createIndexPatternButton'); + }); + + after(async () => { + if (tabsCount > 1) { + await browser.closeCurrentWindow(); + await browser.switchTab(0); + } + }); + }); + }); +} diff --git a/test/functional/apps/dashboard/index.js b/test/functional/apps/dashboard/index.js index 9ae1a2afddcc6c..a8d0e03c9421e8 100644 --- a/test/functional/apps/dashboard/index.js +++ b/test/functional/apps/dashboard/index.js @@ -57,6 +57,7 @@ export default function ({ getService, loadTestFile }) { loadTestFile(require.resolve('./data_shared_attributes')); loadTestFile(require.resolve('./embed_mode')); loadTestFile(require.resolve('./dashboard_back_button')); + loadTestFile(require.resolve('./dashboard_error_handling')); // Note: This one must be last because it unloads some data for one of its tests! // No, this isn't ideal, but loading/unloading takes so much time and these are all bunched diff --git a/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz b/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz index 767d27fb325df9..e83e34a2e07fab 100644 Binary files a/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz and b/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz differ diff --git a/test/functional/services/common/browser.ts b/test/functional/services/common/browser.ts index 46d57f030937bd..3f71c16bd3c44b 100644 --- a/test/functional/services/common/browser.ts +++ b/test/functional/services/common/browser.ts @@ -409,6 +409,20 @@ export async function BrowserProvider({ getService }: FtrProviderContext) { return await driver.getAllWindowHandles(); } + /** + * Switches driver to specific browser tab by index + * + * @param {string} tabIndex + * @return {Promise} + */ + public async switchTab(tabIndex: number) { + const tabs = await driver.getAllWindowHandles(); + if (tabs.length <= tabIndex) { + throw new Error(`Out of existing tabs bounds`); + } + await driver.switchTo().window(tabs[tabIndex]); + } + /** * Sets a value in local storage for the focused window/frame. *