[Discover] [Unified Data Table] Improve Discover / Unified Data Table performance in ES|QL mode (#191249)

## Summary

This PR includes several performance improvements for ES|QL mode in
Discover:
- Memoize `UnifiedDataTableRenderCellValue` to reduce re-renders.
- Show the loading spinner immediately on state changes that should
trigger a refetch so that changed state isn't applied to the grid before
the fetch completes. This also helps to reduce re-renders on state
changes.
- Replace [`EuiDataGrid` in-memory
sorting](https://eui.elastic.co/#/tabular-content/data-grid-advanced#data-grid-in-memory)
with a custom implementation using the `@kbn/sort-predicates` package
(the same one Lens uses for its data grid). EUI in-memory sorting has a
drastic impact on performance because it renders the entire grid off
screen in order to parse cell values, detect their schema, and then sort
the rows. This can cause rendering delays of several seconds for larger
datasets on each render of the data grid. The new approach will sort in
memory based on actual field values and pass the sorted rows to the data
grid, which is both much more performant as well as improving the
sorting behaviour across field types.
- Use the `overscanRowCount` option from
[react-window](https://github.com/bvaughn/react-window) to render some
additional rows outside of view in the data grid, which minimizes pop-in
of rows while scrolling quickly.

There are also a couple of bug fixes included in the PR as a result of
the new sorting behaviour:
- Numeric columns are now sorted correctly where previously they used
alphabetic sorting.
- The "Copy column" action in data grid columns now correctly copies the
column values in the current sort order instead of copying them unsorted
as it used to.

Before - 66,904 `UnifiedDataTableRenderCellValue` render calls:


https://github.com/user-attachments/assets/04caca0d-35e7-421c-b8e3-5a37a1d65177

After - 424 `UnifiedDataTableRenderCellValue` render calls:


https://github.com/user-attachments/assets/dba1a106-6bd6-4f1b-b60e-4741228c488b

Before profile:
<img width="300" alt="profile_old"
src="https://github.com/user-attachments/assets/44c07f30-55d2-44ab-a9b7-a912fa7beca1">

After profile:
<img width="300" alt="profile_new"
src="https://github.com/user-attachments/assets/d61cfd2a-8ac0-45bb-9afa-d3d97b0d03ce">

Before scrolling:


https://github.com/user-attachments/assets/8d9dbdbd-df3e-48df-af9a-539deda8d5ea

After scrolling:


https://github.com/user-attachments/assets/d6309275-e00d-44ee-a59f-2d1e5d30bb60

### Checklist

- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
- [ ] Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [ ] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)

### For maintainers

- [ ] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Jatin Kathuria <jtn.kathuria@gmail.com>
This commit is contained in:
Davis McPhee 2024-09-04 00:26:49 -03:00 committed by GitHub
parent 8b2cb75a57
commit 2629fa82a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 1133 additions and 696 deletions

View file

@ -72,6 +72,8 @@ const generateFieldValue = (field: DataViewField, index: number) => {
return Array.from(field.name).reduce((sum, char) => sum + char.charCodeAt(0) + index, 0);
case KBN_FIELD_TYPES.STRING:
return `${field.name}_${index}`;
case KBN_FIELD_TYPES._SOURCE:
return { [field.name]: `${field.name}_${index}` };
default:
throw new Error(`Unsupported type ${field.type}`);
}

View file

@ -23,7 +23,6 @@ import {
EuiLoadingSpinner,
EuiIcon,
EuiDataGridRefProps,
EuiDataGridInMemory,
EuiDataGridControlColumn,
EuiDataGridCustomBodyProps,
EuiDataGridStyle,
@ -43,7 +42,7 @@ import { getShouldShowFieldHandler } from '@kbn/discover-utils';
import type { DataViewFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public';
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
import type { ThemeServiceStart } from '@kbn/react-kibana-context-common';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { type DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
import { AdditionalFieldGroups } from '@kbn/unified-field-list';
import { DATA_GRID_DENSITY_STYLE_MAP, useDataGridDensity } from '../hooks/use_data_grid_density';
@ -91,8 +90,15 @@ import {
type ColorIndicatorControlColumnParams,
getAdditionalRowControlColumns,
} from './custom_control_columns';
import { useSorting } from '../hooks/use_sorting';
const CONTROL_COLUMN_IDS_DEFAULT = [SELECT_ROW, OPEN_DETAILS];
const THEME_DEFAULT = { darkMode: false };
const VIRTUALIZATION_OPTIONS: EuiDataGridProps['virtualizationOptions'] = {
// Allowing some additional rows to be rendered outside
// the view minimizes pop-in when scrolling quickly
overscanRowCount: 20,
};
export type SortOrder = [string, string];
@ -102,13 +108,6 @@ export enum DataLoadingState {
loaded = 'loaded',
}
const themeDefault = { darkMode: false };
interface SortObj {
id: string;
direction: string;
}
/**
* Unified Data Table props
*/
@ -484,7 +483,7 @@ export const UnifiedDataTable = ({
}: UnifiedDataTableProps) => {
const { fieldFormats, toastNotifications, dataViewFieldEditor, uiSettings, storage, data } =
services;
const { darkMode } = useObservable(services.theme?.theme$ ?? of(themeDefault), themeDefault);
const { darkMode } = useObservable(services.theme?.theme$ ?? of(THEME_DEFAULT), THEME_DEFAULT);
const dataGridRef = useRef<EuiDataGridRefProps>(null);
const [isFilterActive, setIsFilterActive] = useState(false);
const [isCompareActive, setIsCompareActive] = useState(false);
@ -507,20 +506,55 @@ export const UnifiedDataTable = ({
}
}, [isFilterActive, hasSelectedDocs, setIsFilterActive]);
const timeFieldName = dataView.timeFieldName;
const shouldPrependTimeFieldColumn = useCallback(
(activeColumns: string[]) =>
canPrependTimeFieldColumn(
activeColumns,
timeFieldName,
columnsMeta,
showTimeCol,
isPlainRecord
),
[timeFieldName, isPlainRecord, showTimeCol, columnsMeta]
);
const visibleColumns = useMemo(() => {
return getVisibleColumns(
displayedColumns,
dataView,
shouldPrependTimeFieldColumn(displayedColumns)
);
}, [dataView, displayedColumns, shouldPrependTimeFieldColumn]);
const { sortedRows, sorting } = useSorting({
rows,
visibleColumns,
columnsMeta,
sort,
dataView,
isPlainRecord,
isSortEnabled,
defaultColumns,
onSort,
});
const displayedRows = useMemo(() => {
if (!rows) {
if (!sortedRows) {
return [];
}
if (!isFilterActive || !hasSelectedDocs) {
return rows;
return sortedRows;
}
const rowsFiltered = rows.filter((row) => isDocSelected(row.id));
if (!rowsFiltered.length) {
// in case the selected docs are no longer part of the sample of 500, show all docs
return rows;
}
return rowsFiltered;
}, [rows, isFilterActive, hasSelectedDocs, isDocSelected]);
const rowsFiltered = sortedRows.filter((row) => isDocSelected(row.id));
return rowsFiltered.length
? rowsFiltered
: // in case the selected docs are no longer part of the sample of 500, show all docs
sortedRows;
}, [sortedRows, isFilterActive, hasSelectedDocs, isDocSelected]);
const valueToStringConverter: ValueToStringConverter = useCallback(
(rowIndex, columnId, options) => {
@ -709,25 +743,6 @@ export const UnifiedDataTable = ({
[dataView, onFieldEdited, services?.dataViewFieldEditor]
);
const timeFieldName = dataView.timeFieldName;
const shouldPrependTimeFieldColumn = useCallback(
(activeColumns: string[]) =>
canPrependTimeFieldColumn(
activeColumns,
timeFieldName,
columnsMeta,
showTimeCol,
isPlainRecord
),
[timeFieldName, isPlainRecord, showTimeCol, columnsMeta]
);
const visibleColumns = useMemo(
() =>
getVisibleColumns(displayedColumns, dataView, shouldPrependTimeFieldColumn(displayedColumns)),
[dataView, displayedColumns, shouldPrependTimeFieldColumn]
);
const getCellValue = useCallback<UseDataGridColumnsCellActionsProps['getCellValue']>(
(fieldName, rowIndex) =>
displayedRows[rowIndex % displayedRows.length].flattened[fieldName] as Serializable,
@ -848,47 +863,6 @@ export const UnifiedDataTable = ({
[visibleColumns, onSetColumns, shouldPrependTimeFieldColumn]
);
/**
* Sorting
*/
const sortingColumns = useMemo(
() =>
sort
.map(([id, direction]) => ({ id, direction }))
.filter(({ id }) => visibleColumns.includes(id)),
[sort, visibleColumns]
);
const onTableSort = useCallback(
(sortingColumnsData) => {
if (isSortEnabled) {
if (onSort) {
onSort(sortingColumnsData.map(({ id, direction }: SortObj) => [id, direction]));
}
}
},
[onSort, isSortEnabled]
);
const sorting = useMemo(() => {
if (isSortEnabled) {
// in ES|QL mode, sorting is disabled when in Document view
// ideally we want the @timestamp column to be sortable server side
// but it needs discussion before moving forward like this
if (isPlainRecord && !columns.length) {
return undefined;
}
return {
columns: sortingColumns,
onSort: onTableSort,
};
}
return {
columns: sortingColumns,
onSort: () => {},
};
}, [isSortEnabled, sortingColumns, isPlainRecord, columns.length, onTableSort]);
const canSetExpandedDoc = Boolean(setExpandedDoc && !!renderDocumentView);
const leadingControlColumns: EuiDataGridControlColumn[] = useMemo(() => {
@ -1036,12 +1010,6 @@ export const UnifiedDataTable = ({
onUpdateDataGridDensity,
]);
const inMemory = useMemo(() => {
return isPlainRecord && columns.length
? ({ level: 'sorting' } as EuiDataGridInMemory)
: undefined;
}, [columns.length, isPlainRecord]);
const toolbarVisibility = useMemo(
() =>
defaultColumns
@ -1161,13 +1129,13 @@ export const UnifiedDataTable = ({
sorting={sorting as EuiDataGridSorting}
toolbarVisibility={toolbarVisibility}
rowHeightsOptions={rowHeightsOptions}
inMemory={inMemory}
gridStyle={gridStyle}
renderCustomGridBody={renderCustomGridBody}
renderCustomToolbar={renderCustomToolbarFn}
trailingControlColumns={trailingControlColumns}
cellContext={cellContext}
renderCellPopover={renderCustomPopover}
virtualizationOptions={VIRTUALIZATION_OPTIONS}
/>
)}
</div>

View file

@ -0,0 +1,113 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { DataView } from '@kbn/data-views-plugin/public';
import type { DataTableRecord } from '@kbn/discover-utils';
import { getSortingCriteria } from '@kbn/sort-predicates';
import { useMemo } from 'react';
import type { EuiDataGridColumnSortingConfig, EuiDataGridProps } from '@elastic/eui';
import type { SortOrder } from '../components/data_table';
import type { DataTableColumnsMeta } from '../types';
export const useSorting = ({
rows,
visibleColumns,
columnsMeta,
sort,
dataView,
isPlainRecord,
isSortEnabled,
defaultColumns,
onSort,
}: {
rows: DataTableRecord[] | undefined;
visibleColumns: string[];
columnsMeta: DataTableColumnsMeta | undefined;
sort: SortOrder[];
dataView: DataView;
isPlainRecord: boolean;
isSortEnabled: boolean;
defaultColumns: boolean;
onSort: ((sort: string[][]) => void) | undefined;
}) => {
const sortingColumns = useMemo(() => {
return sort
.map(([id, direction]) => ({ id, direction }))
.filter((col) => visibleColumns.includes(col.id)) as EuiDataGridColumnSortingConfig[];
}, [sort, visibleColumns]);
const comparators = useMemo(() => {
if (!isPlainRecord || !rows || !sortingColumns.length) {
return;
}
return sortingColumns.reduce<Array<(a: DataTableRecord, b: DataTableRecord) => number>>(
(acc, { id, direction }) => {
const field = dataView.fields.getByName(id);
if (!field) {
return acc;
}
const sortField = getSortingCriteria(
columnsMeta?.[id]?.type ?? field.type,
id,
dataView.getFormatterForField(field)
);
acc.push((a, b) => sortField(a.flattened, b.flattened, direction as 'asc' | 'desc'));
return acc;
},
[]
);
}, [columnsMeta, dataView, isPlainRecord, rows, sortingColumns]);
const sortedRows = useMemo(() => {
if (!rows || !comparators) {
return rows;
}
return [...rows].sort((a, b) => {
for (const comparator of comparators) {
const result = comparator(a, b);
if (result !== 0) {
return result;
}
}
return 0;
});
}, [comparators, rows]);
const sorting = useMemo<EuiDataGridProps['sorting']>(() => {
if (!isSortEnabled) {
return {
columns: sortingColumns,
onSort: () => {},
};
}
// in ES|QL mode, sorting is disabled when in Document view
// ideally we want the @timestamp column to be sortable server side
// but it needs discussion before moving forward like this
if (isPlainRecord && defaultColumns) {
return undefined;
}
return {
columns: sortingColumns,
onSort: (sortingColumnsData) => {
onSort?.(sortingColumnsData.map(({ id, direction }) => [id, direction]));
},
};
}, [isSortEnabled, isPlainRecord, defaultColumns, sortingColumns, onSort]);
return { sortedRows, sorting };
};

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import React, { useEffect, useContext } from 'react';
import React, { useEffect, useContext, memo } from 'react';
import { i18n } from '@kbn/i18n';
import type { DataView, DataViewField } from '@kbn/data-views-plugin/public';
import {
@ -26,6 +26,8 @@ import { DataTablePopoverCellValue } from '../components/data_table_cell_value';
export const CELL_CLASS = 'unifiedDataTable__cellValue';
const IS_JEST_ENVIRONMENT = typeof jest !== 'undefined';
export const getRenderCellValueFn = ({
dataView,
rows,
@ -49,7 +51,7 @@ export const getRenderCellValueFn = ({
isPlainRecord?: boolean;
isCompressed?: boolean;
}) => {
return function UnifiedDataTableRenderCellValue({
const UnifiedDataTableRenderCellValue = ({
rowIndex,
columnId,
isDetails,
@ -57,7 +59,7 @@ export const getRenderCellValueFn = ({
colIndex,
isExpandable,
isExpanded,
}: EuiDataGridCellValueElementProps) {
}: EuiDataGridCellValueElementProps) => {
const row = rows ? rows[rowIndex] : undefined;
const field = dataView.fields.getByName(columnId);
const ctx = useContext(UnifiedDataTableContext);
@ -153,6 +155,14 @@ export const getRenderCellValueFn = ({
/>
);
};
// When memoizing renderCellValue, the following warning is logged in Jest tests:
// Failed prop type: Invalid prop `renderCellValue` supplied to `EuiDataGridCellContent`, expected one of type [function].
// This is due to incorrect prop type validation that EUI generates for testing components in Jest,
// but is not an actual issue encountered outside of tests
return IS_JEST_ENVIRONMENT
? UnifiedDataTableRenderCellValue
: memo(UnifiedDataTableRenderCellValue);
};
/**

View file

@ -39,5 +39,6 @@
"@kbn/unified-field-list",
"@kbn/core-notifications-browser",
"@kbn/core-capabilities-browser-mocks",
"@kbn/sort-predicates",
]
}

View file

@ -25,6 +25,7 @@ import {
DataSourceType,
isDataSourceType,
} from '../../../../../common/data_sources';
import { sendLoadingMsg } from '../../hooks/use_saved_search_messages';
/**
* Builds a subscribe function for the AppStateContainer, that is executed when the AppState changes in URL
@ -161,6 +162,11 @@ export const buildStateSubscribe =
JSON.stringify(logData, null, 2)
);
// Set documents loading to true immediately on state changes since there's a delay
// on the fetch and we don't want to see state changes reflected in the data grid
// until the fetch is complete (it also helps to minimize data grid re-renders)
sendLoadingMsg(dataState.data$.documents$, dataState.data$.documents$.getValue());
dataState.fetch();
}
};

View file

@ -7,7 +7,7 @@
*/
import expect from '@kbn/expect';
import kbnRison from '@kbn/rison';
import { FtrProviderContext } from '../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
@ -51,8 +51,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
'test/functional/fixtures/kbn_archiver/kibana_sample_data_flights_index_pattern'
);
await kibanaServer.uiSettings.replace(defaultSettings);
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
await PageObjects.common.navigateToApp('discover');
await PageObjects.timePicker.setDefaultAbsoluteRange();
});
after(async () => {
await PageObjects.timePicker.resetDefaultAbsoluteRangeViaUiSettings();
});
describe('ES|QL in Discover', () => {
@ -328,8 +332,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
describe('with slow queries', () => {
it('should show only one entry in inspector for table/visualization', async function () {
const state = kbnRison.encode({
dataSource: { type: 'esql' },
query: { esql: 'from kibana_sample_data_flights' },
});
await PageObjects.common.navigateToActualUrl('discover', `?_a=${state}`, {
ensureCurrentUrl: false,
});
await PageObjects.discover.selectTextBaseLang();
const testQuery = `from kibana_sample_data_flights | limit 10`;
const testQuery = `from logstash-* | limit 10`;
await monacoEditor.setCodeEditorValue(testQuery);
await browser.execute(() => {
@ -470,7 +481,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await retry.waitFor('first cell contains the highest value', async () => {
const cell = await dataGrid.getCellElementExcludingControlColumns(0, 0);
const text = await cell.getVisibleText();
return text === '483';
return text === '17,966';
});
expect(await testSubjects.getVisibleText('dataGridColumnSortingButton')).to.be(
@ -485,7 +496,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await retry.waitFor('first cell contains the same highest value', async () => {
const cell = await dataGrid.getCellElementExcludingControlColumns(0, 0);
const text = await cell.getVisibleText();
return text === '483';
return text === '17,966';
});
await browser.refresh();
@ -496,7 +507,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await retry.waitFor('first cell contains the same highest value after reload', async () => {
const cell = await dataGrid.getCellElementExcludingControlColumns(0, 0);
const text = await cell.getVisibleText();
return text === '483';
return text === '17,966';
});
await PageObjects.discover.clickNewSearchButton();
@ -514,7 +525,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
async () => {
const cell = await dataGrid.getCellElementExcludingControlColumns(0, 0);
const text = await cell.getVisibleText();
return text === '483';
return text === '17,966';
}
);

View file

@ -173,7 +173,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.header.waitUntilLoadingHasFinished();
await PageObjects.discover.waitUntilSearchingHasFinished();
expect(await dataGrid.getRowsText()).to.eql([
expect((await dataGrid.getRowsText()).slice(0, 6)).to.eql([
'Sep 22, 2015 @ 20:44:05.521jpg1,808',
'Sep 22, 2015 @ 20:41:53.463png1,969',
'Sep 22, 2015 @ 20:40:22.952jpg1,576',
@ -208,7 +208,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
'Sep 22, 2015 @ 17:22:12.782css1,583',
];
expect(await dataGrid.getRowsText()).to.eql(filteredRows);
expect((await dataGrid.getRowsText()).slice(0, 6)).to.eql(filteredRows);
expect(await PageObjects.discover.getHitCount()).to.be(totalHitsForTwoFilters);
await testSubjects.existOrFail('unsavedChangesBadge');
@ -217,7 +217,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.header.waitUntilLoadingHasFinished();
await PageObjects.discover.waitUntilSearchingHasFinished();
expect(await dataGrid.getRowsText()).to.eql(filteredRows);
expect((await dataGrid.getRowsText()).slice(0, 6)).to.eql(filteredRows);
expect(await PageObjects.discover.getHitCount()).to.be(totalHitsForTwoFilters);
await testSubjects.existOrFail('unsavedChangesBadge');
});

View file

@ -229,7 +229,7 @@ describe('unified data table', () => {
async () => {
const rowHeight = {
initial: 2,
new: 1,
new: 4,
};
const customMockStore = createMockStore();
@ -240,7 +240,9 @@ describe('unified data table', () => {
})
);
render(<TestComponent store={customMockStore} />);
render(
<TestComponent store={customMockStore} events={[mockTimelineData[0]]} totalCount={1} />
);
expect(await screen.findByTestId('discoverDocTable')).toBeVisible();

View file

@ -50,10 +50,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
'test/functional/fixtures/kbn_archiver/kibana_sample_data_flights_index_pattern'
);
await kibanaServer.uiSettings.replace(defaultSettings);
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
await PageObjects.svlCommonPage.loginAsAdmin();
await PageObjects.common.navigateToApp('discover');
await PageObjects.header.waitUntilLoadingHasFinished();
await PageObjects.timePicker.setDefaultAbsoluteRange();
});
after(async () => {
await PageObjects.timePicker.resetDefaultAbsoluteRangeViaUiSettings();
});
describe('ES|QL in Discover', () => {
@ -453,7 +457,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await retry.waitFor('first cell contains the highest value', async () => {
const cell = await dataGrid.getCellElementExcludingControlColumns(0, 0);
const text = await cell.getVisibleText();
return text === '483';
return text === '17,966';
});
expect(await testSubjects.getVisibleText('dataGridColumnSortingButton')).to.be(
@ -468,7 +472,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await retry.waitFor('first cell contains the same highest value', async () => {
const cell = await dataGrid.getCellElementExcludingControlColumns(0, 0);
const text = await cell.getVisibleText();
return text === '483';
return text === '17,966';
});
await browser.refresh();
@ -479,7 +483,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await retry.waitFor('first cell contains the same highest value after reload', async () => {
const cell = await dataGrid.getCellElementExcludingControlColumns(0, 0);
const text = await cell.getVisibleText();
return text === '483';
return text === '17,966';
});
await PageObjects.discover.clickNewSearchButton();
@ -497,7 +501,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
async () => {
const cell = await dataGrid.getCellElementExcludingControlColumns(0, 0);
const text = await cell.getVisibleText();
return text === '483';
return text === '17,966';
}
);