From c078b9157c2eedeb28c7d136fdc584c9189f674f Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 10 Nov 2023 07:01:16 -0700 Subject: [PATCH] [discover] do not show old results on error (#170769) Prerequisite for https://github.com/elastic/kibana/issues/167904 ### Test 1. install sample web logs 2. Open discover 3. Select time range that displays results 4. Add filter ``` { "error_query": { "indices": [ { "error_type": "exception", "message": "local shard failure message 123", "name": "kibana_sample_data_logs" } ] } } ``` 5. Verify discover should display `EmptyPrompt` showing error message instead of callout with stale data. Screenshot 2023-11-07 at 9 23 43 AM --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../components/layout/discover_documents.tsx | 14 -- .../components/layout/discover_layout.tsx | 5 +- .../main/utils/get_result_state.test.ts | 23 +-- .../main/utils/get_result_state.ts | 8 +- .../components/common/error_callout.test.tsx | 77 +-------- .../components/common/error_callout.tsx | 151 ++++-------------- .../discover/group1/_discover_histogram.ts | 4 +- .../apps/discover/group1/_errors.ts | 2 +- .../apps/discover/group1/_field_data.ts | 2 +- .../group1/_field_data_with_fields_api.ts | 2 +- .../discover/group2/_data_grid_field_data.ts | 2 +- .../apps/discover/group3/_sidebar.ts | 8 +- .../apps/discover/group3/_view_mode_toggle.ts | 4 +- .../apps/discover/group4/_date_nested.ts | 3 +- .../apps/discover/group4/_esql_view.ts | 4 +- test/functional/page_objects/discover_page.ts | 8 +- .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - .../apps/discover/error_handling.ts | 2 +- .../tests/apps/discover/async_search.ts | 9 +- .../tests/apps/discover/sessions_in_space.ts | 1 - 22 files changed, 78 insertions(+), 257 deletions(-) diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx index bf01e2a7b6669..f655af89c0c4c 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx @@ -37,7 +37,6 @@ import { SHOW_MULTIFIELDS, SORT_DEFAULT_ORDER_SETTING, } from '@kbn/discover-utils'; -import { i18n } from '@kbn/i18n'; import useObservable from 'react-use/lib/useObservable'; import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; import { DiscoverGrid } from '../../../../components/discover_grid'; @@ -65,7 +64,6 @@ import { DiscoverGridFlyout } from '../../../../components/discover_grid_flyout' import { getRenderCustomToolbarWithElements } from '../../../../components/discover_grid/render_custom_toolbar'; import { useSavedSearchInitial } from '../../services/discover_state_provider'; import { useFetchMoreRecords } from './use_fetch_more_records'; -import { ErrorCallout } from '../../../../components/common/error_callout'; import { SelectedVSAvailableCallout } from './selected_vs_available_callout'; const containerStyles = css` @@ -256,22 +254,11 @@ function DiscoverDocumentsComponent({ [dataView, onAddColumn, onAddFilter, onRemoveColumn, query, savedSearch.id, setExpandedDoc] ); - const dataState = useDataState(stateContainer.dataState.data$.main$); const documents = useObservable(stateContainer.dataState.data$.documents$); const callouts = useMemo( () => ( <> - {dataState.error && ( - - )} ), [ - dataState.error, isTextBasedQuery, currentColumns, documents?.textBasedQueryColumns, diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index 6461603609903..b2d3a4b5058ee 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -114,8 +114,8 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { const isPlainRecord = useMemo(() => getRawRecordType(query) === RecordRawType.PLAIN, [query]); const resultState = useMemo( - () => getResultState(dataState.fetchStatus, dataState.foundDocuments!, isPlainRecord), - [dataState.fetchStatus, dataState.foundDocuments, isPlainRecord] + () => getResultState(dataState.fetchStatus, dataState.foundDocuments ?? false), + [dataState.fetchStatus, dataState.foundDocuments] ); const onOpenInspector = useInspector({ @@ -338,7 +338,6 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { } )} error={dataState.error} - data-test-subj="discoverNoResultsError" /> ) : ( { - test('fetching uninitialized', () => { + test(`should return 'uninitialized' when fetching uninitialized`, () => { const actual = getResultState(FetchStatus.UNINITIALIZED, false); expect(actual).toBe(resultStatuses.UNINITIALIZED); }); - test('fetching complete with no records', () => { + test(`should return 'loading' when fetching is loading`, () => { + const actual = getResultState(FetchStatus.LOADING, false); + expect(actual).toBe(resultStatuses.LOADING); + }); + + test(`should return 'none' when fetching is complete with no records`, () => { const actual = getResultState(FetchStatus.COMPLETE, false); expect(actual).toBe(resultStatuses.NO_RESULTS); }); - test('fetching ongoing aka loading', () => { - const actual = getResultState(FetchStatus.LOADING, false); - expect(actual).toBe(resultStatuses.LOADING); + test(`should return 'none' after a fetch error`, () => { + const actual = getResultState(FetchStatus.ERROR, false); + expect(actual).toBe(resultStatuses.NO_RESULTS); }); - test('fetching ready', () => { + test(`should return 'ready' when fetching completes with records`, () => { const actual = getResultState(FetchStatus.COMPLETE, true); expect(actual).toBe(resultStatuses.READY); }); - test('re-fetching after already data is available', () => { + test(`should reurn 'ready' when re-fetching after already data is available`, () => { const actual = getResultState(FetchStatus.LOADING, true); expect(actual).toBe(resultStatuses.READY); }); - test('after a fetch error when data was successfully fetched before ', () => { + test(`should return 'none' after a fetch error when data was successfully fetched before`, () => { const actual = getResultState(FetchStatus.ERROR, true); - expect(actual).toBe(resultStatuses.READY); + expect(actual).toBe(resultStatuses.NO_RESULTS); }); }); diff --git a/src/plugins/discover/public/application/main/utils/get_result_state.ts b/src/plugins/discover/public/application/main/utils/get_result_state.ts index ff31e114754ad..8d39707c65f9c 100644 --- a/src/plugins/discover/public/application/main/utils/get_result_state.ts +++ b/src/plugins/discover/public/application/main/utils/get_result_state.ts @@ -18,15 +18,11 @@ export const resultStatuses = { * Returns the current state of the result, depends on fetchStatus and the given fetched rows * Determines what is displayed in Discover main view (loading view, data view, empty data view, ...) */ -export function getResultState( - fetchStatus: FetchStatus, - foundDocuments: boolean = false, - isPlainRecord?: boolean -) { +export function getResultState(fetchStatus: FetchStatus, foundDocuments: boolean = false) { if (fetchStatus === FetchStatus.UNINITIALIZED) { return resultStatuses.UNINITIALIZED; } - if (isPlainRecord && fetchStatus === FetchStatus.ERROR) return resultStatuses.NO_RESULTS; + if (fetchStatus === FetchStatus.ERROR) return resultStatuses.NO_RESULTS; if (!foundDocuments && fetchStatus === FetchStatus.LOADING) return resultStatuses.LOADING; else if (foundDocuments) return resultStatuses.READY; diff --git a/src/plugins/discover/public/components/common/error_callout.test.tsx b/src/plugins/discover/public/components/common/error_callout.test.tsx index ec01af15cd7e2..fd07af1bd548d 100644 --- a/src/plugins/discover/public/components/common/error_callout.test.tsx +++ b/src/plugins/discover/public/components/common/error_callout.test.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { EuiButton, EuiCallOut, EuiEmptyPrompt, EuiLink, EuiModal } from '@elastic/eui'; +import { EuiButton, EuiEmptyPrompt } from '@elastic/eui'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { findTestSubject } from '@kbn/test-jest-helpers'; import { mount } from 'enzyme'; @@ -37,14 +37,11 @@ describe('ErrorCallout', () => { it('should render', () => { const title = 'Error title'; const error = new Error('My error'); - const wrapper = mountWithServices( - - ); + const wrapper = mountWithServices(); const prompt = wrapper.find(EuiEmptyPrompt); expect(prompt).toHaveLength(1); expect(prompt.prop('title')).toBeDefined(); expect(prompt.prop('title')).not.toBeInstanceOf(String); - expect(prompt.prop('data-test-subj')).toBe('errorCallout'); expect(prompt.prop('body')).toBeDefined(); expect(findTestSubject(prompt, 'discoverErrorCalloutTitle').contains(title)).toBe(true); expect(findTestSubject(prompt, 'discoverErrorCalloutMessage').contains(error.message)).toBe( @@ -53,97 +50,31 @@ describe('ErrorCallout', () => { expect(prompt.find(EuiButton)).toHaveLength(1); }); - it('should render inline', () => { - const title = 'Error title'; - const error = new Error('My error'); - const wrapper = mountWithServices( - - ); - const callout = wrapper.find(EuiCallOut); - expect(callout).toHaveLength(1); - expect(callout.prop('title')).toBeDefined(); - expect(callout.prop('title')).not.toBeInstanceOf(String); - expect(callout.prop('size')).toBe('s'); - expect(callout.prop('data-test-subj')).toBe('errorCallout'); - expect( - findTestSubject(callout, 'discoverErrorCalloutMessage').contains(`${title}: ${error.message}`) - ).toBe(true); - expect(callout.find(EuiLink)).toHaveLength(1); - }); - it('should render with override display', () => { const title = 'Override title'; const error = new Error('My error'); const overrideDisplay =
Override display
; mockGetSearchErrorOverrideDisplay.mockReturnValue({ title, body: overrideDisplay }); - const wrapper = mountWithServices( - - ); + const wrapper = mountWithServices(); const prompt = wrapper.find(EuiEmptyPrompt); expect(prompt).toHaveLength(1); expect(prompt.prop('title')).toBeDefined(); expect(prompt.prop('title')).not.toBeInstanceOf(String); - expect(prompt.prop('data-test-subj')).toBe('errorCallout'); expect(prompt.prop('body')).toBeDefined(); expect(findTestSubject(prompt, 'discoverErrorCalloutTitle').contains(title)).toBe(true); expect(prompt.contains(overrideDisplay)).toBe(true); expect(prompt.find(EuiButton)).toHaveLength(0); }); - it('should render with override display and inline', () => { - const title = 'Override title'; - const error = new Error('My error'); - const overrideDisplay =
Override display
; - mockGetSearchErrorOverrideDisplay.mockReturnValue({ title, body: overrideDisplay }); - const wrapper = mountWithServices( - - ); - const callout = wrapper.find(EuiCallOut); - expect(callout).toHaveLength(1); - expect(callout.prop('title')).toBeDefined(); - expect(callout.prop('title')).not.toBeInstanceOf(String); - expect(callout.prop('size')).toBe('s'); - expect(callout.prop('data-test-subj')).toBe('errorCallout'); - expect(callout.find(EuiLink)).toHaveLength(1); - expect(wrapper.find(EuiModal)).toHaveLength(0); - expect(wrapper.contains(title)).toBe(true); - expect(wrapper.contains(overrideDisplay)).toBe(false); - callout.find(EuiLink).simulate('click'); - expect(wrapper.find(EuiModal)).toHaveLength(1); - expect(findTestSubject(wrapper, 'discoverErrorCalloutOverrideModalTitle').contains(title)).toBe( - true - ); - expect( - findTestSubject(wrapper, 'discoverErrorCalloutOverrideModalBody').contains(overrideDisplay) - ).toBe(true); - expect(wrapper.contains(overrideDisplay)).toBe(true); - }); - it('should call showErrorDialog when the button is clicked', () => { (discoverServiceMock.core.notifications.showErrorDialog as jest.Mock).mockClear(); const title = 'Error title'; const error = new Error('My error'); - const wrapper = mountWithServices( - - ); + const wrapper = mountWithServices(); wrapper.find(EuiButton).find('button').simulate('click'); expect(discoverServiceMock.core.notifications.showErrorDialog).toHaveBeenCalledWith({ title, error, }); }); - - it('should call showErrorDialog when the button is clicked inline', () => { - (discoverServiceMock.core.notifications.showErrorDialog as jest.Mock).mockClear(); - const title = 'Error title'; - const error = new Error('My error'); - const wrapper = mountWithServices( - - ); - wrapper.find(EuiLink).find('button').simulate('click'); - expect(discoverServiceMock.core.notifications.showErrorDialog).toHaveBeenCalledWith({ - title, - error, - }); - }); }); diff --git a/src/plugins/discover/public/components/common/error_callout.tsx b/src/plugins/discover/public/components/common/error_callout.tsx index 84b5b979c0249..1b3e8f02f39a3 100644 --- a/src/plugins/discover/public/components/common/error_callout.tsx +++ b/src/plugins/discover/public/components/common/error_callout.tsx @@ -6,143 +6,58 @@ * Side Public License, v 1. */ -import { - EuiButton, - EuiCallOut, - EuiEmptyPrompt, - EuiLink, - EuiModal, - EuiModalBody, - EuiModalHeader, - EuiModalHeaderTitle, - EuiText, - useEuiTheme, -} from '@elastic/eui'; +import { EuiButton, EuiEmptyPrompt, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import { getSearchErrorOverrideDisplay } from '@kbn/data-plugin/public'; import { i18n } from '@kbn/i18n'; -import React, { ReactNode, useState } from 'react'; +import React from 'react'; import { useDiscoverServices } from '../../hooks/use_discover_services'; -export interface ErrorCalloutProps { +interface Props { title: string; error: Error; - inline?: boolean; - 'data-test-subj'?: string; } -export const ErrorCallout = ({ - title, - error, - inline, - 'data-test-subj': dataTestSubj, -}: ErrorCalloutProps) => { +export const ErrorCallout = ({ title, error }: Props) => { const { core } = useDiscoverServices(); const { euiTheme } = useEuiTheme(); - const showErrorMessage = i18n.translate('discover.errorCalloutShowErrorMessage', { - defaultMessage: 'View details', - }); - const overrideDisplay = getSearchErrorOverrideDisplay({ error, application: core.application, }); - const [overrideModalOpen, setOverrideModalOpen] = useState(false); - - const showError = overrideDisplay?.body - ? () => setOverrideModalOpen(true) - : () => core.notifications.showErrorDialog({ title, error }); - - let formattedTitle: ReactNode = overrideDisplay?.title || title; - - if (inline) { - const formattedTitleMessage = overrideDisplay - ? formattedTitle - : i18n.translate('discover.errorCalloutFormattedTitle', { - defaultMessage: '{title}: {errorMessage}', - values: { title, errorMessage: error.message }, - }); - - formattedTitle = ( - <> - - {formattedTitleMessage} - - - {showErrorMessage} - - - ); - } - return ( - <> - {inline ? ( - {overrideDisplay?.title ?? title}} + body={ +
- ) : ( - {formattedTitle}} - body={ -
- {overrideDisplay?.body ?? ( - <> -

- {error.message} -

- {showErrorMessage} - - )} -
- } - data-test-subj={dataTestSubj} - /> - )} - {overrideDisplay && overrideModalOpen && ( - setOverrideModalOpen(false)}> - - - {overrideDisplay.title} - - - - - {overrideDisplay.body} - - - - )} - + > + {overrideDisplay?.body ?? ( + <> +

+ {error.message} +

+ core.notifications.showErrorDialog({ title, error })}> + {i18n.translate('discover.errorCalloutShowErrorMessage', { + defaultMessage: 'View details', + })} + + + )} +
+ } + /> ); }; diff --git a/test/functional/apps/discover/group1/_discover_histogram.ts b/test/functional/apps/discover/group1/_discover_histogram.ts index 6e30f75f90a10..d69bd153b3d56 100644 --- a/test/functional/apps/discover/group1/_discover_histogram.ts +++ b/test/functional/apps/discover/group1/_discover_histogram.ts @@ -289,8 +289,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // type an invalid search query, hit refresh await queryBar.setQuery('this is > not valid'); await queryBar.submitQuery(); - // check the error state - expect(await testSubjects.exists('embeddable-lens-failure')).to.be(true); + + await PageObjects.discover.showsErrorCallout(); // now remove the query await queryBar.clearQuery(); diff --git a/test/functional/apps/discover/group1/_errors.ts b/test/functional/apps/discover/group1/_errors.ts index ef68df5b47204..6f0a7ba96b7ad 100644 --- a/test/functional/apps/discover/group1/_errors.ts +++ b/test/functional/apps/discover/group1/_errors.ts @@ -32,7 +32,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('invalid scripted field error', () => { it('is rendered', async () => { - expect(await PageObjects.discover.noResultsErrorVisible()).to.be(true); + await PageObjects.discover.showsErrorCallout(); const painlessStackTrace = await testSubjects.find('painlessStackTrace'); expect(painlessStackTrace).not.to.be(undefined); }); diff --git a/test/functional/apps/discover/group1/_field_data.ts b/test/functional/apps/discover/group1/_field_data.ts index 0125549ead92f..4047cfcdfc45d 100644 --- a/test/functional/apps/discover/group1/_field_data.ts +++ b/test/functional/apps/discover/group1/_field_data.ts @@ -76,7 +76,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'whitespace but "(" found.'; await queryBar.setQuery('xxx(yyy))'); await queryBar.submitQuery(); - expect(await PageObjects.discover.mainErrorVisible()).to.be(true); + await PageObjects.discover.showsErrorCallout(); const message = await PageObjects.discover.getDiscoverErrorMessage(); expect(message).to.contain(expectedError); }); diff --git a/test/functional/apps/discover/group1/_field_data_with_fields_api.ts b/test/functional/apps/discover/group1/_field_data_with_fields_api.ts index e262f3ce30c49..7a21210a78e0c 100644 --- a/test/functional/apps/discover/group1/_field_data_with_fields_api.ts +++ b/test/functional/apps/discover/group1/_field_data_with_fields_api.ts @@ -80,7 +80,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'whitespace but "(" found.'; await queryBar.setQuery('xxx(yyy))'); await queryBar.submitQuery(); - expect(await PageObjects.discover.mainErrorVisible()).to.be(true); + await PageObjects.discover.showsErrorCallout(); const message = await PageObjects.discover.getDiscoverErrorMessage(); expect(message).to.contain(expectedError); }); diff --git a/test/functional/apps/discover/group2/_data_grid_field_data.ts b/test/functional/apps/discover/group2/_data_grid_field_data.ts index 3347f398288a4..f12f378bbf94b 100644 --- a/test/functional/apps/discover/group2/_data_grid_field_data.ts +++ b/test/functional/apps/discover/group2/_data_grid_field_data.ts @@ -91,7 +91,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'whitespace but "(" found.'; await queryBar.setQuery('xxx(yyy))'); await queryBar.submitQuery(); - expect(await PageObjects.discover.mainErrorVisible()).to.be(true); + await PageObjects.discover.showsErrorCallout(); const message = await PageObjects.discover.getDiscoverErrorMessage(); expect(message).to.contain(expectedError); }); diff --git a/test/functional/apps/discover/group3/_sidebar.ts b/test/functional/apps/discover/group3/_sidebar.ts index b47e71f452818..01e357b7f01e6 100644 --- a/test/functional/apps/discover/group3/_sidebar.ts +++ b/test/functional/apps/discover/group3/_sidebar.ts @@ -697,8 +697,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should render even when retrieving documents failed with an error', async () => { await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.missingOrFail('discoverNoResultsError'); - expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be( INITIAL_FIELD_LIST_SUMMARY ); @@ -708,7 +706,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.header.waitUntilLoadingHasFinished(); // error in fetching documents because of the invalid runtime field - await testSubjects.existOrFail('discoverNoResultsError'); + await PageObjects.discover.showsErrorCallout(); await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); @@ -721,7 +719,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await browser.refresh(); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('discoverNoResultsError'); // still has error + await PageObjects.discover.showsErrorCallout(); // still has error // check that the sidebar is rendered event after a refresh await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); @@ -731,8 +729,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.discover.removeField('_invalid-runtimefield'); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded(); - - await testSubjects.missingOrFail('discoverNoResultsError'); }); it('should work correctly when time range is updated', async function () { diff --git a/test/functional/apps/discover/group3/_view_mode_toggle.ts b/test/functional/apps/discover/group3/_view_mode_toggle.ts index c47aad66c9a01..62c78efbc2432 100644 --- a/test/functional/apps/discover/group3/_view_mode_toggle.ts +++ b/test/functional/apps/discover/group3/_view_mode_toggle.ts @@ -79,13 +79,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await queryBar.submitQuery(); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('discoverMainError'); + await PageObjects.discover.showsErrorCallout(); await queryBar.clearQuery(); await queryBar.submitQuery(); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.missingOrFail('discoverMainError'); + await testSubjects.missingOrFail('discoverErrorCalloutTitle'); }); it('should show Field Statistics tab', async () => { diff --git a/test/functional/apps/discover/group4/_date_nested.ts b/test/functional/apps/discover/group4/_date_nested.ts index 9760645fe11c7..f761cdacc7fe9 100644 --- a/test/functional/apps/discover/group4/_date_nested.ts +++ b/test/functional/apps/discover/group4/_date_nested.ts @@ -10,7 +10,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); - const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['common', 'timePicker', 'discover']); const security = getService('security'); const kibanaServer = getService('kibanaServer'); @@ -34,7 +33,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should show an error message', async function () { await PageObjects.discover.selectIndexPattern('date-nested'); await PageObjects.discover.waitUntilSearchingHasFinished(); - await testSubjects.existOrFail('discoverNoResultsError'); + await PageObjects.discover.showsErrorCallout(); }); }); } diff --git a/test/functional/apps/discover/group4/_esql_view.ts b/test/functional/apps/discover/group4/_esql_view.ts index 773af0d512309..2b6547152970d 100644 --- a/test/functional/apps/discover/group4/_esql_view.ts +++ b/test/functional/apps/discover/group4/_esql_view.ts @@ -135,7 +135,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); describe('errors', () => { - it('should error messages for syntax errors in query', async function () { + it('should show error messages for syntax errors in query', async function () { await PageObjects.discover.selectTextBaseLang(); const brokenQueries = [ 'from logstash-* | limit 10*', @@ -149,7 +149,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.discover.waitUntilSearchingHasFinished(); // error in fetching documents because of the invalid query - await testSubjects.existOrFail('discoverNoResultsError'); + await PageObjects.discover.showsErrorCallout(); const message = await testSubjects.getVisibleText('discoverErrorCalloutMessage'); expect(message).to.contain( "[esql] > Couldn't parse Elasticsearch ES|QL query. Check your query and try again." diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index b20e055ea0d6a..47a79132212cc 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -453,12 +453,8 @@ export class DiscoverPageObject extends FtrService { return await this.testSubjects.exists('discoverNoResultsTimefilter'); } - public noResultsErrorVisible() { - return this.testSubjects.exists('discoverNoResultsError'); - } - - public mainErrorVisible() { - return this.testSubjects.exists('discoverMainError'); + public showsErrorCallout() { + return this.testSubjects.existOrFail('discoverErrorCalloutTitle'); } public getDiscoverErrorMessage() { diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 6c64ec463940e..a5ed852718005 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -2245,7 +2245,6 @@ "discover.docTable.totalDocuments": "{totalDocuments} documents", "discover.dscTour.stepAddFields.description": "Cliquez sur {plusIcon} pour ajouter les champs qui vous intéressent.", "discover.dscTour.stepExpand.description": "Cliquez sur {expandIcon} pour afficher, comparer et filtrer les documents.", - "discover.errorCalloutFormattedTitle": "{title} : {errorMessage}", "discover.formatHit.moreFields": "et {count} autre(s) {count, plural, one {champ} many {champs} other {champs}}", "discover.howToSeeOtherMatchingDocumentsDescription": "Voici les {sampleSize} premiers documents correspondant à votre recherche. Veuillez affiner cette dernière pour en voir davantage.", "discover.noMatchRoute.bannerText": "L'application Discover ne reconnaît pas cet itinéraire : {route}", @@ -2368,7 +2367,6 @@ "discover.docTable.tableRow.viewSingleDocumentLinkText": "Afficher un seul document", "discover.docTable.tableRow.viewSurroundingDocumentsLinkText": "Afficher les documents alentour", "discover.documentsAriaLabel": "Documents", - "discover.documentsErrorTitle": "Erreur lors de la recherche", "discover.docViews.table.scoreSortWarningTooltip": "Filtrez sur _score pour pouvoir récupérer les valeurs correspondantes.", "discover.dropZoneTableLabel": "Abandonner la zone pour ajouter un champ en tant que colonne dans la table", "discover.dscTour.stepAddFields.imageAltText": "Dans la liste Champs disponibles, cliquez sur l'icône Plus pour afficher/masquer un champ dans le tableau de documents.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a24d4d8cc7c10..58375f665fa0c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2259,7 +2259,6 @@ "discover.docTable.totalDocuments": "{totalDocuments}ドキュメント", "discover.dscTour.stepAddFields.description": "{plusIcon}をクリックして、関心があるフィールドを追加します。", "discover.dscTour.stepExpand.description": "{expandIcon}をクリックすると、ドキュメントを表示、比較、フィルタリングできます。", - "discover.errorCalloutFormattedTitle": "{title}:{errorMessage}", "discover.formatHit.moreFields": "およびその他{count}個の{count, plural, other {フィールド}}", "discover.howToSeeOtherMatchingDocumentsDescription": "これらは検索条件に一致した初めの{sampleSize}件のドキュメントです。他の結果を表示するには検索条件を絞ってください。", "discover.noMatchRoute.bannerText": "Discoverアプリケーションはこのルートを認識できません:{route}", @@ -2382,7 +2381,6 @@ "discover.docTable.tableRow.viewSingleDocumentLinkText": "単一のドキュメントを表示", "discover.docTable.tableRow.viewSurroundingDocumentsLinkText": "周りのドキュメントを表示", "discover.documentsAriaLabel": "ドキュメント", - "discover.documentsErrorTitle": "検索エラー", "discover.docViews.table.scoreSortWarningTooltip": "_scoreの値を取得するには、並べ替える必要があります。", "discover.dropZoneTableLabel": "フィールドを列として表に追加するには、ゾーンをドロップします", "discover.dscTour.stepAddFields.imageAltText": "[使用可能なフィールド]リストで、プラスアイコンをクリックし、フィールドをドキュメントテーブルに切り替えます。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index d9aaa9c724465..003312fef8d19 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2259,7 +2259,6 @@ "discover.docTable.totalDocuments": "{totalDocuments} 个文档", "discover.dscTour.stepAddFields.description": "单击 {plusIcon} 以添加您感兴趣的字段。", "discover.dscTour.stepExpand.description": "单击 {expandIcon} 以查看、比较和筛选文档。", - "discover.errorCalloutFormattedTitle": "{title}:{errorMessage}", "discover.formatHit.moreFields": "及另外 {count} 个{count, plural, other {字段}}", "discover.howToSeeOtherMatchingDocumentsDescription": "以下是匹配您的搜索的前 {sampleSize} 个文档,请优化您的搜索以查看其他文档。", "discover.noMatchRoute.bannerText": "Discover 应用程序无法识别此路由:{route}", @@ -2382,7 +2381,6 @@ "discover.docTable.tableRow.viewSingleDocumentLinkText": "查看单个文档", "discover.docTable.tableRow.viewSurroundingDocumentsLinkText": "查看周围文档", "discover.documentsAriaLabel": "文档", - "discover.documentsErrorTitle": "搜索错误", "discover.docViews.table.scoreSortWarningTooltip": "要检索 _score 的值,必须按其筛选。", "discover.dropZoneTableLabel": "放置区域以将字段作为列添加到表中", "discover.dscTour.stepAddFields.imageAltText": "在可用字段列表中,单击加号图标将字段切换为文档表。", diff --git a/x-pack/test/functional/apps/discover/error_handling.ts b/x-pack/test/functional/apps/discover/error_handling.ts index 46eff2e7d0c89..cf362e8a12475 100644 --- a/x-pack/test/functional/apps/discover/error_handling.ts +++ b/x-pack/test/functional/apps/discover/error_handling.ts @@ -31,7 +31,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // this is the same test as in OSS but it catches different error message issue in different licences describe('invalid scripted field error', () => { it('is rendered', async () => { - expect(await PageObjects.discover.noResultsErrorVisible()).to.be(true); + await PageObjects.discover.showsErrorCallout(); const painlessStackTrace = await testSubjects.find('painlessStackTrace'); expect(painlessStackTrace).not.to.be(undefined); }); diff --git a/x-pack/test/search_sessions_integration/tests/apps/discover/async_search.ts b/x-pack/test/search_sessions_integration/tests/apps/discover/async_search.ts index 9dc632931d301..251290c6f4b5e 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/discover/async_search.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/discover/async_search.ts @@ -62,7 +62,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await browser.navigateTo(savedSessionURL); await PageObjects.header.waitUntilLoadingHasFinished(); await searchSessions.expectState('restored'); - await testSubjects.existOrFail('discoverNoResultsError'); // expect error because of fake searchSessionId + await testSubjects.existOrFail('discoverErrorCalloutTitle'); // expect error because of fake searchSessionId await PageObjects.common.clearAllToasts(); const searchSessionId1 = await getSearchSessionId(); expect(searchSessionId1).to.be(fakeSearchSessionId); @@ -84,10 +84,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { // Note this currently fails, for some reason the fakeSearchSessionId is not restored await searchSessions.expectState('restored'); expect(await getSearchSessionId()).to.be(fakeSearchSessionId); + + // back navigation takes discover to fakeSearchSessionId which is in error state + // clean up page to get out of error state before proceeding to next test + await PageObjects.common.clearAllToasts(); + await queryBar.clickQuerySubmitButton(); + await PageObjects.header.waitUntilLoadingHasFinished(); }); it('navigation to context cleans the session', async () => { - await PageObjects.common.clearAllToasts(); const table = await PageObjects.discover.getDocTable(); const isLegacy = await PageObjects.discover.useLegacyTable(); await table.clickRowToggle({ rowIndex: 0 }); diff --git a/x-pack/test/search_sessions_integration/tests/apps/discover/sessions_in_space.ts b/x-pack/test/search_sessions_integration/tests/apps/discover/sessions_in_space.ts index ad1e2cae04877..1bb691629a63e 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/discover/sessions_in_space.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/discover/sessions_in_space.ts @@ -71,7 +71,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Check that session is restored await searchSessions.expectState('restored'); - await testSubjects.missingOrFail('discoverNoResultsError'); expect(await toasts.getToastCount()).to.be(0); // no session restoration related warnings }); });