From e8fcb4920e96ca2d976c17bb06c183066b60a262 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Wed, 15 Apr 2020 22:11:41 +0200 Subject: [PATCH] Bugfix clear saved query crashes kibana on Discover in some cases (#63554) (#63628) * actual hotfix * add functional test --- .../discover/np_ready/angular/discover.js | 6 +----- .../query_string_input/language_switcher.tsx | 1 + .../ui/search_bar/create_search_bar.tsx | 5 +++-- .../ui/search_bar/lib/use_saved_query.ts | 4 ++-- .../apps/discover/_saved_queries.js | 19 ++++++++++++++++++ test/functional/services/query_bar.ts | 20 +++++++++++++++++++ 6 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js index d770e8334b3af..72276a38f6ac2 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js @@ -828,13 +828,9 @@ function discoverController( if (newSavedQueryId) { setAppState({ savedQuery: newSavedQueryId }); } else { - //reset filters and query string, remove savedQuery from state + // remove savedQueryId from state const state = { ...appStateContainer.getState(), - query: getDefaultQuery( - localStorage.get('kibana.userQueryLanguage') || config.get('search:queryLanguage') - ), - filters: [], }; delete state.savedQuery; appStateContainer.set(state); diff --git a/src/plugins/data/public/ui/query_string_input/language_switcher.tsx b/src/plugins/data/public/ui/query_string_input/language_switcher.tsx index 63f6997ce2fc3..ded48d462722d 100644 --- a/src/plugins/data/public/ui/query_string_input/language_switcher.tsx +++ b/src/plugins/data/public/ui/query_string_input/language_switcher.tsx @@ -61,6 +61,7 @@ export function QueryLanguageSwitcher(props: Props) { size="xs" onClick={() => setIsPopoverOpen(!isPopoverOpen)} className="euiFormControlLayout__append" + data-test-subj={'switchQueryLanguageButton'} > {props.language === 'lucene' ? luceneLabel : kqlLabel} diff --git a/src/plugins/data/public/ui/search_bar/create_search_bar.tsx b/src/plugins/data/public/ui/search_bar/create_search_bar.tsx index 5ca334d6bdcfe..7723254f3aa51 100644 --- a/src/plugins/data/public/ui/search_bar/create_search_bar.tsx +++ b/src/plugins/data/public/ui/search_bar/create_search_bar.tsx @@ -124,7 +124,8 @@ export function createSearchBar({ core, storage, data }: StatefulSearchBarDeps) const onQuerySubmitRef = useRef(props.onQuerySubmit); const defaultQuery = { query: '', - language: core.uiSettings.get('search:queryLanguage'), + language: + storage.get('kibana.userQueryLanguage') || core.uiSettings.get('search:queryLanguage'), }; const [query, setQuery] = useState(props.query || defaultQuery); @@ -161,7 +162,7 @@ export function createSearchBar({ core, storage, data }: StatefulSearchBarDeps) setQuery, savedQueryId: props.savedQueryId, notifications: core.notifications, - uiSettings: core.uiSettings, + defaultLanguage: defaultQuery.language, }); // Fire onQuerySubmit on query or timerange change diff --git a/src/plugins/data/public/ui/search_bar/lib/use_saved_query.ts b/src/plugins/data/public/ui/search_bar/lib/use_saved_query.ts index 817e890b7b42b..79aee3438d7aa 100644 --- a/src/plugins/data/public/ui/search_bar/lib/use_saved_query.ts +++ b/src/plugins/data/public/ui/search_bar/lib/use_saved_query.ts @@ -29,8 +29,8 @@ interface UseSavedQueriesProps { queryService: DataPublicPluginStart['query']; setQuery: Function; notifications: CoreStart['notifications']; - uiSettings: CoreStart['uiSettings']; savedQueryId?: string; + defaultLanguage: string; } interface UseSavedQueriesReturn { @@ -41,7 +41,7 @@ interface UseSavedQueriesReturn { export const useSavedQuery = (props: UseSavedQueriesProps): UseSavedQueriesReturn => { // Handle saved queries - const defaultLanguage = props.uiSettings.get('search:queryLanguage'); + const defaultLanguage = props.defaultLanguage; const [savedQuery, setSavedQuery] = useState(); // Effect is used to convert a saved query id into an object diff --git a/test/functional/apps/discover/_saved_queries.js b/test/functional/apps/discover/_saved_queries.js index 3cdaccf32cdc3..76f3a3aea365f 100644 --- a/test/functional/apps/discover/_saved_queries.js +++ b/test/functional/apps/discover/_saved_queries.js @@ -147,6 +147,25 @@ export default function({ getService, getPageObjects }) { await savedQueryManagementComponent.clearCurrentlyLoadedQuery(); expect(await queryBar.getQueryString()).to.eql(''); }); + + // https://github.com/elastic/kibana/issues/63505 + it('allows clearing if non default language was remembered in localstorage', async () => { + await queryBar.switchQueryLanguage('lucene'); + await PageObjects.common.navigateToApp('discover'); // makes sure discovered is reloaded without any state in url + await queryBar.expectQueryLanguageOrFail('lucene'); // make sure lucene is remembered after refresh (comes from localstorage) + await savedQueryManagementComponent.loadSavedQuery('OkResponse'); + await queryBar.expectQueryLanguageOrFail('kql'); + await savedQueryManagementComponent.clearCurrentlyLoadedQuery(); + await queryBar.expectQueryLanguageOrFail('lucene'); + }); + + // fails: bug in discover https://github.com/elastic/kibana/issues/63561 + // unskip this test when bug is fixed + it.skip('changing language removes saved query', async () => { + await savedQueryManagementComponent.loadSavedQuery('OkResponse'); + await queryBar.switchQueryLanguage('lucene'); + expect(await queryBar.getQueryString()).to.eql(''); + }); }); }); } diff --git a/test/functional/services/query_bar.ts b/test/functional/services/query_bar.ts index ace8b97155c09..7c7fd2d81f170 100644 --- a/test/functional/services/query_bar.ts +++ b/test/functional/services/query_bar.ts @@ -17,6 +17,7 @@ * under the License. */ +import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; export function QueryBarProvider({ getService, getPageObjects }: FtrProviderContext) { @@ -25,6 +26,7 @@ export function QueryBarProvider({ getService, getPageObjects }: FtrProviderCont const log = getService('log'); const PageObjects = getPageObjects(['header', 'common']); const find = getService('find'); + const browser = getService('browser'); class QueryBar { async getQueryString(): Promise { @@ -62,6 +64,24 @@ export function QueryBarProvider({ getService, getPageObjects }: FtrProviderCont public async clickQuerySubmitButton(): Promise { await testSubjects.click('querySubmitButton'); } + + public async switchQueryLanguage(lang: 'kql' | 'lucene'): Promise { + await testSubjects.click('switchQueryLanguageButton'); + const kqlToggle = await testSubjects.find('languageToggle'); + const currentLang = + (await kqlToggle.getAttribute('aria-checked')) === 'true' ? 'kql' : 'lucene'; + if (lang !== currentLang) { + await kqlToggle.click(); + } + + await browser.pressKeys(browser.keys.ESCAPE); // close popover + await this.expectQueryLanguageOrFail(lang); // make sure lang is switched + } + + public async expectQueryLanguageOrFail(lang: 'kql' | 'lucene'): Promise { + const queryLanguageButton = await testSubjects.find('switchQueryLanguageButton'); + expect((await queryLanguageButton.getVisibleText()).toLowerCase()).to.eql(lang); + } } return new QueryBar();