From 14d85755d92fdff5bc794b70bac29e23f0a2f4c5 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:59:53 +1100 Subject: [PATCH] [8.x] [ML][ES|QL] Adds query guardrails and technical preview badge to ES|QL data visualizer (#200325) (#200677) # Backport This will backport the following commits from `main` to `8.x`: - [[ML][ES|QL] Adds query guardrails and technical preview badge to ES|QL data visualizer (#200325)](https://github.com/elastic/kibana/pull/200325) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Quynh Nguyen (Quinn) <43350163+qn895@users.noreply.github.com> --- .../expanded_row/index_based_expanded_row.tsx | 12 ++- .../data_visualizer_stats_table.tsx | 5 +- .../stats_table/use_table_settings.ts | 7 +- .../index_data_visualizer_esql.tsx | 1 + .../search_panel/esql/limit_size.tsx | 8 -- .../constants/esql_constants.ts | 2 +- .../embeddable_esql_field_stats_table.tsx | 1 + .../esql/use_data_visualizer_esql_data.tsx | 42 ++++++++- .../hooks/esql/use_esql_overall_stats_data.ts | 1 - .../index_data_visualizer.tsx | 40 +++------ x-pack/plugins/data_visualizer/tsconfig.json | 1 - .../datavisualizer_selector.tsx | 15 +++- .../index_based/index_data_visualizer.tsx | 7 +- .../data_visualizer/esql_data_visualizer.ts | 26 +++--- .../functional/services/ml/data_visualizer.ts | 4 +- .../services/ml/data_visualizer_table.ts | 88 ++++++++++--------- 16 files changed, 155 insertions(+), 105 deletions(-) diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx index e0c83f36399e9..2982df103bded 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { useEffect } from 'react'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; import { useExpandedRowCss } from './use_expanded_row_css'; import { GeoPointContentWithMap } from './geo_point_content_with_map'; @@ -34,6 +34,7 @@ export const IndexBasedDataVisualizerExpandedRow = ({ totalDocuments, timeFieldName, typeAccessor = 'type', + onVisibilityChange, }: { item: FieldVisConfig; dataView: DataView | undefined; @@ -46,6 +47,7 @@ export const IndexBasedDataVisualizerExpandedRow = ({ */ onAddFilter?: (field: DataViewField | string, value: string, type: '+' | '-') => void; timeFieldName?: string; + onVisibilityChange?: (visible: boolean, item: FieldVisConfig) => void; }) => { const config = { ...item, stats: { ...item.stats, totalDocuments } }; const { loading, existsInDocs, fieldName } = config; @@ -98,6 +100,14 @@ export const IndexBasedDataVisualizerExpandedRow = ({ } } + useEffect(() => { + onVisibilityChange?.(true, item); + + return () => { + onVisibilityChange?.(false, item); + }; + }, [item, onVisibilityChange]); + return (
{loading === true ? : getCardContent()} diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx index 3b591a85ff472..e0e43efb694f2 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx @@ -63,6 +63,7 @@ interface DataVisualizerTableProps { overallStatsRunning: boolean; renderFieldName?: FieldStatisticTableEmbeddableProps['renderFieldName']; error?: Error | string; + isEsql?: boolean; } const UnmemoizedDataVisualizerTable = ({ @@ -78,6 +79,7 @@ const UnmemoizedDataVisualizerTable = ({ overallStatsRunning, renderFieldName, error, + isEsql = false, }: DataVisualizerTableProps) => { const { euiTheme } = useEuiTheme(); @@ -87,7 +89,8 @@ const UnmemoizedDataVisualizerTable = ({ const { onTableChange, pagination, sorting } = useTableSettings( items, pageState, - updatePageState + updatePageState, + isEsql ); const [showDistributions, setShowDistributions] = useState(showPreviewByDefault ?? true); const [dimensions, setDimensions] = useState(calculateTableColumnsDimensions()); diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/use_table_settings.ts b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/use_table_settings.ts index b2292970230c0..be427a6ebccae 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/use_table_settings.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/use_table_settings.ts @@ -27,7 +27,8 @@ interface UseTableSettingsReturnValue { export function useTableSettings( items: TypeOfItem[], pageState: DataVisualizerTableState, - updatePageState: (update: DataVisualizerTableState) => void + updatePageState: (update: DataVisualizerTableState) => void, + isEsql: boolean = false ): UseTableSettingsReturnValue { const { pageIndex, pageSize, sortField, sortDirection } = pageState; @@ -50,9 +51,9 @@ export function useTableSettings( pageIndex, pageSize, totalItemCount: items.length, - pageSizeOptions: PAGE_SIZE_OPTIONS, + pageSizeOptions: isEsql ? [10, 25] : PAGE_SIZE_OPTIONS, }), - [items, pageIndex, pageSize] + [items, pageIndex, pageSize, isEsql] ); const sorting = useMemo( diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_esql.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_esql.tsx index c6190c87bcae5..5953144e715fb 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_esql.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_esql.tsx @@ -332,6 +332,7 @@ export const IndexDataVisualizerESQL: FC = (dataVi + isEsql={true} items={configs} pageState={dataVisualizerListState} updatePageState={onTableChange} diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/esql/use_data_visualizer_esql_data.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/esql/use_data_visualizer_esql_data.tsx index 2323b231d67f7..26b8ff3cf24d7 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/esql/use_data_visualizer_esql_data.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/esql/use_data_visualizer_esql_data.tsx @@ -53,14 +53,14 @@ const defaultSearchQuery = { }; const FALLBACK_ESQL_QUERY: ESQLQuery = { esql: '' }; -const DEFAULT_LIMIT_SIZE = '10000'; +const DEFAULT_LIMIT_SIZE = '5000'; const defaults = getDefaultPageState(); export const getDefaultESQLDataVisualizerListState = ( overrides?: Partial ): Required => ({ pageIndex: 0, - pageSize: 25, + pageSize: 10, sortField: 'fieldName', sortDirection: 'asc', visibleFieldTypes: [], @@ -70,7 +70,7 @@ export const getDefaultESQLDataVisualizerListState = ( searchQuery: defaultSearchQuery, searchQueryLanguage: SEARCH_QUERY_LANGUAGE.KUERY, filters: [], - showDistributions: true, + showDistributions: false, showAllFields: false, showEmptyFields: false, probability: null, @@ -229,6 +229,21 @@ export const useESQLDataVisualizerData = ( } as QueryDslQueryContainer; } } + + // Ensure that we don't query frozen data + if (filter.bool === undefined) { + filter.bool = Object.create(null); + } + + if (filter.bool && filter.bool.must_not === undefined) { + filter.bool.must_not = []; + } + + if (filter.bool && Array.isArray(filter?.bool?.must_not)) { + filter.bool.must_not!.push({ + term: { _tier: 'data_frozen' }, + }); + } return { id: input.id, earliest, @@ -332,9 +347,25 @@ export const useESQLDataVisualizerData = ( const visibleFieldTypes = dataVisualizerListState.visibleFieldTypes ?? restorableDefaults.visibleFieldTypes; + const [expandedRows, setExpandedRows] = useState([]); + + const onVisibilityChange = useCallback((visible: boolean, item: FieldVisConfig) => { + if (visible) { + setExpandedRows((prev) => [...prev, item.fieldName]); + } else { + setExpandedRows((prev) => prev.filter((fieldName) => fieldName !== item.fieldName)); + } + }, []); + + const hasExpandedRows = useMemo(() => expandedRows.length > 0, [expandedRows]); useEffect( function updateFieldStatFieldsToFetch() { + if (dataVisualizerListState?.showDistributions === false && !hasExpandedRows) { + setFieldStatFieldsToFetch(undefined); + return; + } + const { sortField, sortDirection } = dataVisualizerListState; // Otherwise, sort the list of fields by the initial sort field and sort direction @@ -376,6 +407,8 @@ export const useESQLDataVisualizerData = ( dataVisualizerListState.sortDirection, nonMetricConfigs, metricConfigs, + dataVisualizerListState?.showDistributions, + hasExpandedRows, ] ); @@ -618,6 +651,7 @@ export const useESQLDataVisualizerData = ( typeAccessor="secondaryType" timeFieldName={timeFieldName} onAddFilter={input.onAddFilter} + onVisibilityChange={onVisibilityChange} /> ); } @@ -625,7 +659,7 @@ export const useESQLDataVisualizerData = ( }, {} as ItemIdToExpandedRowMap); }, // eslint-disable-next-line react-hooks/exhaustive-deps - [currentDataView, totalCount, query.esql, timeFieldName] + [currentDataView, totalCount, query.esql, timeFieldName, onVisibilityChange] ); const combinedProgress = useMemo( diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/esql/use_esql_overall_stats_data.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/esql/use_esql_overall_stats_data.ts index 3d023a6fc3811..7ea012d2d4b28 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/esql/use_esql_overall_stats_data.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/esql/use_esql_overall_stats_data.ts @@ -313,7 +313,6 @@ export const useESQLOverallStatsData = ( { strategy: ESQL_ASYNC_SEARCH_STRATEGY } )) as ESQLResponse | undefined; setQueryHistoryStatus(false); - const columnInfo = columnsResp?.rawResponse ? columnsResp.rawResponse.all_columns ?? columnsResp.rawResponse.columns : []; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx index 745e03da10d09..8a5e34f58a10f 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx @@ -16,7 +16,6 @@ import { i18n } from '@kbn/i18n'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; -import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme'; import { StorageContextProvider } from '@kbn/ml-local-storage'; import type { DataView } from '@kbn/data-views-plugin/public'; import { getNestedProperty } from '@kbn/ml-nested-property'; @@ -49,8 +48,6 @@ import { DATA_VISUALIZER_INDEX_VIEWER } from './constants/index_data_visualizer_ import { INDEX_DATA_VISUALIZER_NAME } from '../common/constants'; import { DV_STORAGE_KEYS } from './types/storage'; -const XXL_BREAKPOINT = 1400; - const localStorage = new Storage(window.localStorage); export interface DataVisualizerStateContextProviderProps { @@ -341,29 +338,20 @@ export const IndexDataVisualizer: FC = ({ return ( - - - - - {!esql ? ( - - ) : ( - - )} - - - - + + + + {!esql ? ( + + ) : ( + + )} + + + ); }; diff --git a/x-pack/plugins/data_visualizer/tsconfig.json b/x-pack/plugins/data_visualizer/tsconfig.json index 970526cdf464e..9e1c19c84067b 100644 --- a/x-pack/plugins/data_visualizer/tsconfig.json +++ b/x-pack/plugins/data_visualizer/tsconfig.json @@ -76,7 +76,6 @@ "@kbn/ml-time-buckets", "@kbn/aiops-log-rate-analysis", "@kbn/react-kibana-context-render", - "@kbn/react-kibana-context-theme", "@kbn/presentation-publishing", "@kbn/shared-ux-utility", "@kbn/search-types", diff --git a/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx b/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx index 41b2ac3a47d37..41291e3ac5057 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx @@ -18,6 +18,7 @@ import { EuiLink, EuiSpacer, EuiText, + EuiBetaBadge, EuiTextAlign, } from '@elastic/eui'; @@ -64,7 +65,6 @@ export const DatavisualizerSelector: FC = () => { }, } = useMlKibana(); const isEsqlEnabled = useMemo(() => uiSettings.get(ENABLE_ESQL), [uiSettings]); - const helpLink = docLinks.links.ml.guide; const navigateToPath = useNavigateToPath(); @@ -172,6 +172,19 @@ export const DatavisualizerSelector: FC = () => { {' '} + + } + tooltipPosition={'right'} /> diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx index e85da14ddb808..cd06783ddc17b 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx @@ -16,7 +16,7 @@ import type { GetAdditionalLinksParams, } from '@kbn/data-visualizer-plugin/public'; import { useTimefilter } from '@kbn/ml-date-picker'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, useEuiTheme } from '@elastic/eui'; import useMountedState from 'react-use/lib/useMountedState'; import { useMlApi, useMlKibana, useMlLocator } from '../../contexts/kibana'; import { HelpMenu } from '../../components/help_menu'; @@ -26,6 +26,7 @@ import { mlNodesAvailable, getMlNodeCount } from '../../ml_nodes_check/check_ml_ import { checkPermission } from '../../capabilities/check_capabilities'; import { MlPageHeader } from '../../components/page_header'; import { useEnabledFeatures } from '../../contexts/ml'; +import { TechnicalPreviewBadge } from '../../components/technical_preview_badge'; export const IndexDataVisualizerPage: FC<{ esql: boolean }> = ({ esql = false }) => { useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); const { @@ -188,6 +189,7 @@ export const IndexDataVisualizerPage: FC<{ esql: boolean }> = ({ esql = false }) // eslint-disable-next-line react-hooks/exhaustive-deps [mlLocator, mlFeaturesDisabled] ); + const { euiTheme } = useEuiTheme(); return IndexDataVisualizer ? ( {IndexDataVisualizer !== null ? ( @@ -203,6 +205,9 @@ export const IndexDataVisualizerPage: FC<{ esql: boolean }> = ({ esql = false }) + + + ) : null} diff --git a/x-pack/test/functional/apps/ml/data_visualizer/esql_data_visualizer.ts b/x-pack/test/functional/apps/ml/data_visualizer/esql_data_visualizer.ts index f6fe276ac33b7..96e01c67ff91c 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/esql_data_visualizer.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/esql_data_visualizer.ts @@ -39,7 +39,7 @@ const esqlFarequoteData = { sourceIndexOrSavedSearch: 'ft_farequote', expected: { hasDocCountChart: true, - initialLimitSize: '10,000 (100%)', + initialLimitSize: '5,000 (100%)', totalDocCountFormatted: '86,274', metricFields: [ { @@ -48,7 +48,7 @@ const esqlFarequoteData = { existsInDocs: true, aggregatable: true, loading: false, - docCountFormatted: '86,274 (100%)', + docCountFormatted: '10,000 (100%)', statsMaxDecimalPlaces: 3, topValuesCount: 11, viewableInLens: false, @@ -61,7 +61,7 @@ const esqlFarequoteData = { existsInDocs: true, aggregatable: true, loading: false, - docCountFormatted: '86,274 (100%)', + docCountFormatted: '10,000 (100%)', exampleCount: 2, viewableInLens: false, }, @@ -72,7 +72,7 @@ const esqlFarequoteData = { aggregatable: false, loading: false, exampleCount: 1, - docCountFormatted: '86,274 (100%)', + docCountFormatted: '10,000 (100%)', viewableInLens: false, }, { @@ -82,7 +82,7 @@ const esqlFarequoteData = { aggregatable: true, loading: false, exampleCount: 1, - docCountFormatted: '86,274 (100%)', + docCountFormatted: '10,000 (100%)', viewableInLens: false, }, { @@ -92,7 +92,7 @@ const esqlFarequoteData = { aggregatable: true, loading: false, exampleCount: 10, - docCountFormatted: '86,274 (100%)', + docCountFormatted: '10,000 (100%)', viewableInLens: false, }, { @@ -102,7 +102,7 @@ const esqlFarequoteData = { aggregatable: false, loading: false, exampleCount: 1, - docCountFormatted: '86,274 (100%)', + docCountFormatted: '10,000 (100%)', viewableInLens: false, }, { @@ -112,7 +112,7 @@ const esqlFarequoteData = { aggregatable: true, loading: false, exampleCount: 1, - docCountFormatted: '86,274 (100%)', + docCountFormatted: '10,000 (100%)', viewableInLens: false, }, ], @@ -253,7 +253,7 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { it(`${testData.suiteTitle} updates data when limit size changes`, async () => { if (testData.expected.initialLimitSize !== undefined) { - await ml.testExecution.logTestStep('shows analysis for 10,000 rows by default'); + await ml.testExecution.logTestStep('shows analysis for 5,000 rows by default'); for (const fieldRow of testData.expected.metricFields as Array< Required >) { @@ -263,13 +263,13 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { undefined, false, false, - true + false ); } } - await ml.testExecution.logTestStep('sets limit size to Analyze all'); - await ml.dataVisualizer.setLimitSize(100000); + await ml.testExecution.logTestStep('sets limit size to 10,000 rows'); + await ml.dataVisualizer.setLimitSize(10000); await ml.testExecution.logTestStep('updates table with newly set limit size'); for (const fieldRow of testData.expected.metricFields as Array< @@ -281,7 +281,7 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { undefined, false, false, - true + false ); } diff --git a/x-pack/test/functional/services/ml/data_visualizer.ts b/x-pack/test/functional/services/ml/data_visualizer.ts index 33d4e2f8f68ba..8597492a50a11 100644 --- a/x-pack/test/functional/services/ml/data_visualizer.ts +++ b/x-pack/test/functional/services/ml/data_visualizer.ts @@ -99,14 +99,14 @@ export function MachineLearningDataVisualizerProvider({ getService }: FtrProvide await testSubjects.existOrFail(`dvESQLLimitSize-${size}`, { timeout: 1000 }); }, - async setLimitSize(size: 5000 | 10000 | 100000) { + async setLimitSize(size: 5000 | 10000) { await retry.tryForTime(5000, async () => { // escape popover await browser.pressKeys(browser.keys.ESCAPE); // Once clicked, show list of options await testSubjects.clickWhenNotDisabled('dvESQLLimitSizeSelect'); - for (const option of [5000, 10000, 100000]) { + for (const option of [5000, 10000]) { await testSubjects.existOrFail(`dvESQLLimitSize-${option}`, { timeout: 1000 }); } diff --git a/x-pack/test/functional/services/ml/data_visualizer_table.ts b/x-pack/test/functional/services/ml/data_visualizer_table.ts index a6f936e43bf37..9bf1baf4a33d5 100644 --- a/x-pack/test/functional/services/ml/data_visualizer_table.ts +++ b/x-pack/test/functional/services/ml/data_visualizer_table.ts @@ -398,29 +398,31 @@ export function MachineLearningDataVisualizerTableProvider( await this.assertFieldDocCount(fieldName, docCountFormatted); await this.ensureDetailsOpen(fieldName); - await testSubjects.existOrFail( - this.detailsSelector(fieldName, 'dataVisualizerNumberSummaryTable') - ); - - if (topValuesCount !== undefined) { + await retry.tryForTime(3000, async () => { await testSubjects.existOrFail( - this.detailsSelector(fieldName, 'dataVisualizerFieldDataTopValues') + this.detailsSelector(fieldName, 'dataVisualizerNumberSummaryTable') ); - await this.assertTopValuesCount(fieldName, topValuesCount); - } - if (checkDistributionPreviewExist) { - await this.assertDistributionPreviewExist(fieldName); - } - if (viewableInLens) { - if (hasActionMenu) { - await this.assertActionMenuViewInLensEnabled(fieldName, true); + if (topValuesCount !== undefined) { + await testSubjects.existOrFail( + this.detailsSelector(fieldName, 'dataVisualizerFieldDataTopValues') + ); + await this.assertTopValuesCount(fieldName, topValuesCount); + } + + if (checkDistributionPreviewExist) { + await this.assertDistributionPreviewExist(fieldName); + } + if (viewableInLens) { + if (hasActionMenu) { + await this.assertActionMenuViewInLensEnabled(fieldName, true); + } else { + await this.assertViewInLensActionEnabled(fieldName, true); + } } else { - await this.assertViewInLensActionEnabled(fieldName, true); + await this.assertViewInLensActionNotExists(fieldName); } - } else { - await this.assertViewInLensActionNotExists(fieldName); - } + }); await this.ensureDetailsClosed(fieldName); } @@ -525,33 +527,35 @@ export function MachineLearningDataVisualizerTableProvider( hasActionMenu?: boolean, exampleContent?: string[] ) { - // Currently the data used in the data visualizer tests only contains these field types. - if (fieldType === ML_JOB_FIELD_TYPES.DATE) { - await this.assertDateFieldContents(fieldName, docCountFormatted); - } else if (fieldType === ML_JOB_FIELD_TYPES.KEYWORD) { - await this.assertKeywordFieldContents( - fieldName, - docCountFormatted, - exampleCount, - exampleContent - ); - } else if (fieldType === ML_JOB_FIELD_TYPES.TEXT) { - await this.assertTextFieldContents(fieldName, docCountFormatted, exampleCount); - } else if (fieldType === ML_JOB_FIELD_TYPES.GEO_POINT) { - await this.assertGeoPointFieldContents(fieldName, docCountFormatted, exampleCount); - } else if (fieldType === ML_JOB_FIELD_TYPES.UNKNOWN) { - await this.assertUnknownFieldContents(fieldName, docCountFormatted); - } + await retry.tryForTime(3000, async () => { + // Currently the data used in the data visualizer tests only contains these field types. + if (fieldType === ML_JOB_FIELD_TYPES.DATE) { + await this.assertDateFieldContents(fieldName, docCountFormatted); + } else if (fieldType === ML_JOB_FIELD_TYPES.KEYWORD) { + await this.assertKeywordFieldContents( + fieldName, + docCountFormatted, + exampleCount, + exampleContent + ); + } else if (fieldType === ML_JOB_FIELD_TYPES.TEXT) { + await this.assertTextFieldContents(fieldName, docCountFormatted, exampleCount); + } else if (fieldType === ML_JOB_FIELD_TYPES.GEO_POINT) { + await this.assertGeoPointFieldContents(fieldName, docCountFormatted, exampleCount); + } else if (fieldType === ML_JOB_FIELD_TYPES.UNKNOWN) { + await this.assertUnknownFieldContents(fieldName, docCountFormatted); + } - if (viewableInLens) { - if (hasActionMenu) { - await this.assertActionMenuViewInLensEnabled(fieldName, true); + if (viewableInLens) { + if (hasActionMenu) { + await this.assertActionMenuViewInLensEnabled(fieldName, true); + } else { + await this.assertViewInLensActionEnabled(fieldName, true); + } } else { - await this.assertViewInLensActionEnabled(fieldName, true); + await this.assertViewInLensActionNotExists(fieldName); } - } else { - await this.assertViewInLensActionNotExists(fieldName); - } + }); } public async assertLensActionShowChart(fieldName: string, visualizationContainer?: string) {