From 2e674d8c49447354cde97a44e01908cb91593731 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Tue, 20 Apr 2021 14:43:02 +0200 Subject: [PATCH] [Discover] Enable EuiDataGrid (#89264) * Now the new EuiDataGrid based document table is the default * Columns can be sorted by drag and drop * Column width can be changed by drag and drop * There's a fullscreen mode * There's document selection * There's document navigation in the flyover of a expanded document * Sorting is much more user friendly, less confusing and sort order can be changed by drag and drop # Conflicts: # test/functional/apps/discover/_discover.ts # x-pack/test/functional/apps/security/doc_level_security_roles.js # x-pack/test/functional/apps/security/field_level_security.js --- src/plugins/discover/server/ui_settings.ts | 2 +- test/accessibility/apps/discover.ts | 1 + test/examples/embeddables/dashboard.ts | 2 +- .../apps/context/_context_navigation.js | 6 + .../apps/context/_discover_navigation.js | 4 +- .../apps/dashboard/dashboard_filter_bar.ts | 10 +- .../apps/dashboard/dashboard_time_picker.ts | 8 +- .../apps/dashboard/embeddable_rendering.ts | 2 +- .../apps/dashboard/saved_search_embeddable.ts | 2 +- .../apps/discover/_data_grid_field_data.ts | 4 +- .../apps/discover/_date_nanos_mixed.ts | 16 +- test/functional/apps/discover/_discover.ts | 21 +- .../apps/discover/_doc_navigation.ts | 13 +- test/functional/apps/discover/_doc_table.ts | 208 ++++++++++-------- test/functional/apps/discover/_field_data.ts | 64 ++++-- .../discover/_field_data_with_fields_api.ts | 61 +++-- .../functional/apps/discover/_large_string.ts | 2 +- .../apps/discover/_runtime_fields_editor.ts | 8 +- test/functional/apps/home/_sample_data.ts | 2 +- .../apps/management/_scripted_fields.js | 26 +-- .../functional/page_objects/dashboard_page.ts | 15 +- test/functional/page_objects/discover_page.ts | 45 ++-- .../services/dashboard/expectations.ts | 8 - test/functional/services/data_grid.ts | 45 +++- .../test_suites/data_plugin/session.ts | 2 +- .../apps/dashboard/_async_dashboard.ts | 2 +- .../dashboard_mode/dashboard_view_mode.js | 2 +- .../apps/security/doc_level_security_roles.js | 2 +- .../apps/security/field_level_security.js | 8 +- .../apps/visualize/precalculated_histogram.ts | 4 +- .../save_search_session_relative_time.ts | 2 +- .../tests/apps/discover/async_search.ts | 16 +- 32 files changed, 367 insertions(+), 246 deletions(-) diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index d3fdb6e72c6510..103a06965835ea 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -157,7 +157,7 @@ export const uiSettings: Record = { name: i18n.translate('discover.advancedSettings.docTableVersionName', { defaultMessage: 'Use legacy table', }), - value: true, + value: false, description: i18n.translate('discover.advancedSettings.docTableVersionDescription', { defaultMessage: 'Discover uses a new table layout that includes better data sorting, drag-and-drop columns, and a full screen ' + diff --git a/test/accessibility/apps/discover.ts b/test/accessibility/apps/discover.ts index a46a27a5bdf9c7..67abe15ea537a7 100644 --- a/test/accessibility/apps/discover.ts +++ b/test/accessibility/apps/discover.ts @@ -23,6 +23,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await esArchiver.loadIfNeeded('logstash_functional'); await kibanaServer.uiSettings.update({ defaultIndex: 'logstash-*', + 'doc_table:legacy': true, }); await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setDefaultAbsoluteRange(); diff --git a/test/examples/embeddables/dashboard.ts b/test/examples/embeddables/dashboard.ts index 7db49d9dfbfcb1..70e5ba115c3af8 100644 --- a/test/examples/embeddables/dashboard.ts +++ b/test/examples/embeddables/dashboard.ts @@ -117,7 +117,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide }); it('saved search', async () => { - await dashboardExpect.savedSearchRowCount(50); + await dashboardExpect.savedSearchRowCount(11); }); }); diff --git a/test/functional/apps/context/_context_navigation.js b/test/functional/apps/context/_context_navigation.js index 56415f38f92fd5..7f72d44c50ea00 100644 --- a/test/functional/apps/context/_context_navigation.js +++ b/test/functional/apps/context/_context_navigation.js @@ -19,10 +19,12 @@ export default function ({ getService, getPageObjects }) { const browser = getService('browser'); const docTable = getService('docTable'); const PageObjects = getPageObjects(['common', 'context', 'discover', 'timePicker']); + const kibanaServer = getService('kibanaServer'); describe('discover - context - back navigation', function contextSize() { before(async function () { await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.uiSettings.update({ 'doc_table:legacy': true }); await PageObjects.common.navigateToApp('discover'); for (const [columnName, value] of TEST_FILTER_COLUMN_NAMES) { await PageObjects.discover.clickFieldListItem(columnName); @@ -30,6 +32,10 @@ export default function ({ getService, getPageObjects }) { } }); + after(async function () { + await kibanaServer.uiSettings.replace({}); + }); + it('should go back after loading', async function () { await retry.waitFor('user navigating to context and returning to discover', async () => { // navigate to the context view diff --git a/test/functional/apps/context/_discover_navigation.js b/test/functional/apps/context/_discover_navigation.js index 572ee3dedf35a0..dc5d56271c7fd7 100644 --- a/test/functional/apps/context/_discover_navigation.js +++ b/test/functional/apps/context/_discover_navigation.js @@ -30,10 +30,12 @@ export default function ({ getService, getPageObjects }) { const testSubjects = getService('testSubjects'); const dashboardAddPanel = getService('dashboardAddPanel'); const browser = getService('browser'); + const kibanaServer = getService('kibanaServer'); describe('context link in discover', () => { before(async () => { await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.uiSettings.update({ 'doc_table:legacy': true }); await PageObjects.common.navigateToApp('discover'); for (const columnName of TEST_COLUMN_NAMES) { @@ -46,7 +48,7 @@ export default function ({ getService, getPageObjects }) { } }); after(async () => { - await PageObjects.timePicker.resetDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.uiSettings.replace({}); }); it('should open the context view with the selected document as anchor', async () => { diff --git a/test/functional/apps/dashboard/dashboard_filter_bar.ts b/test/functional/apps/dashboard/dashboard_filter_bar.ts index cb2b4a1792a478..ad7e4be9b19352 100644 --- a/test/functional/apps/dashboard/dashboard_filter_bar.ts +++ b/test/functional/apps/dashboard/dashboard_filter_bar.ts @@ -11,6 +11,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { + const dataGrid = getService('dataGrid'); const dashboardExpect = getService('dashboardExpect'); const dashboardAddPanel = getService('dashboardAddPanel'); const testSubjects = getService('testSubjects'); @@ -173,8 +174,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('are added when a cell magnifying glass is clicked', async function () { await dashboardAddPanel.addSavedSearch('Rendering-Test:-saved-search'); await PageObjects.dashboard.waitForRenderComplete(); - await testSubjects.click('docTableCellFilter'); - + const documentCell = await dataGrid.getCellElement(1, 3); + await documentCell.click(); + const expandCellContentButton = await documentCell.findByClassName( + 'euiDataGridRowCell__expandButtonIcon' + ); + await expandCellContentButton.click(); + await testSubjects.click('filterForButton'); const filterCount = await filterBar.getFilterCount(); expect(filterCount).to.equal(1); }); diff --git a/test/functional/apps/dashboard/dashboard_time_picker.ts b/test/functional/apps/dashboard/dashboard_time_picker.ts index ef033204385821..eb7c05079fb448 100644 --- a/test/functional/apps/dashboard/dashboard_time_picker.ts +++ b/test/functional/apps/dashboard/dashboard_time_picker.ts @@ -12,13 +12,13 @@ import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { - const dashboardExpect = getService('dashboardExpect'); const pieChart = getService('pieChart'); const dashboardVisualizations = getService('dashboardVisualizations'); const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'timePicker']); const browser = getService('browser'); const log = getService('log'); const kibanaServer = getService('kibanaServer'); + const dataGrid = getService('dataGrid'); describe('dashboard time picker', function describeIndexTests() { before(async function () { @@ -49,14 +49,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { name: 'saved search', fields: ['bytes', 'agent'], }); - await dashboardExpect.docTableFieldCount(150); + const initialRows = await dataGrid.getDocTableRows(); + expect(initialRows.length).to.be(11); // Set to time range with no data await PageObjects.timePicker.setAbsoluteRange( 'Jan 1, 2000 @ 00:00:00.000', 'Jan 1, 2000 @ 01:00:00.000' ); - await dashboardExpect.docTableFieldCount(0); + const noResults = await dataGrid.hasNoResults(); + expect(noResults).to.be.ok(); }); it('Timepicker start, end, interval values are set by url', async () => { diff --git a/test/functional/apps/dashboard/embeddable_rendering.ts b/test/functional/apps/dashboard/embeddable_rendering.ts index bbfa1ae4189816..c9ffd3f6ae86e7 100644 --- a/test/functional/apps/dashboard/embeddable_rendering.ts +++ b/test/functional/apps/dashboard/embeddable_rendering.ts @@ -64,7 +64,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // TODO add test for 'scripted filter and query' viz // TODO add test for 'animal weight linked to search' viz // TODO add test for the last vega viz - await dashboardExpect.savedSearchRowCount(50); + await dashboardExpect.savedSearchRowCount(11); }; const expectNoDataRenders = async () => { diff --git a/test/functional/apps/dashboard/saved_search_embeddable.ts b/test/functional/apps/dashboard/saved_search_embeddable.ts index 71f19b23da9dd9..bea5c7d7491623 100644 --- a/test/functional/apps/dashboard/saved_search_embeddable.ts +++ b/test/functional/apps/dashboard/saved_search_embeddable.ts @@ -45,7 +45,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const marks = $('mark') .toArray() .map((mark) => $(mark).text()); - expect(marks.length).to.be(50); + expect(marks.length).to.be(11); }); it('removing a filter removes highlights', async function () { diff --git a/test/functional/apps/discover/_data_grid_field_data.ts b/test/functional/apps/discover/_data_grid_field_data.ts index 112a49ecf0f4f7..9e4196aa7e6ae2 100644 --- a/test/functional/apps/discover/_data_grid_field_data.ts +++ b/test/functional/apps/discover/_data_grid_field_data.ts @@ -45,9 +45,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('the search term should be highlighted in the field data', async function () { // marks is the style that highlights the text in yellow + await PageObjects.discover.clickFieldListItemAdd('extension'); const marks = await PageObjects.discover.getMarks(); - expect(marks.length).to.be(50); + expect(marks.length).to.be.greaterThan(0); expect(marks.indexOf('php')).to.be(0); + await PageObjects.discover.clickFieldListItemRemove('extension'); }); it('search type:apache should show the correct hit count', async function () { diff --git a/test/functional/apps/discover/_date_nanos_mixed.ts b/test/functional/apps/discover/_date_nanos_mixed.ts index 35439ef1e8eb03..47c3a19c069868 100644 --- a/test/functional/apps/discover/_date_nanos_mixed.ts +++ b/test/functional/apps/discover/_date_nanos_mixed.ts @@ -33,14 +33,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('shows a list of records of indices with date & date_nanos fields in the right order', async function () { - const rowData1 = await PageObjects.discover.getDocTableIndex(1); - expect(rowData1.startsWith('Jan 1, 2019 @ 12:10:30.124000000')).to.be.ok(); - const rowData2 = await PageObjects.discover.getDocTableIndex(3); - expect(rowData2.startsWith('Jan 1, 2019 @ 12:10:30.123498765')).to.be.ok(); - const rowData3 = await PageObjects.discover.getDocTableIndex(5); - expect(rowData3.startsWith('Jan 1, 2019 @ 12:10:30.123456789')).to.be.ok(); - const rowData4 = await PageObjects.discover.getDocTableIndex(7); - expect(rowData4.startsWith('Jan 1, 2019 @ 12:10:30.123000000')).to.be.ok(); + const rowData1 = await PageObjects.discover.getDocTableField(1); + expect(rowData1).to.be('Jan 1, 2019 @ 12:10:30.124000000'); + const rowData2 = await PageObjects.discover.getDocTableField(2); + expect(rowData2).to.be('Jan 1, 2019 @ 12:10:30.123498765'); + const rowData3 = await PageObjects.discover.getDocTableField(3); + expect(rowData3).to.be('Jan 1, 2019 @ 12:10:30.123456789'); + const rowData4 = await PageObjects.discover.getDocTableField(4); + expect(rowData4).to.be('Jan 1, 2019 @ 12:10:30.123000000'); }); }); } diff --git a/test/functional/apps/discover/_discover.ts b/test/functional/apps/discover/_discover.ts index 8babba146d7ffe..ec01e6302b4dd9 100644 --- a/test/functional/apps/discover/_discover.ts +++ b/test/functional/apps/discover/_discover.ts @@ -46,6 +46,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const time = await PageObjects.timePicker.getTimeConfig(); expect(time.start).to.be(PageObjects.timePicker.defaultStartTime); expect(time.end).to.be(PageObjects.timePicker.defaultEndTime); + const rowData = await PageObjects.discover.getDocTableIndex(1); + log.debug('check the newest doc timestamp in UTC (check diff timezone in last test)'); + expect(rowData).to.contain('Sep 22, 2015 @ 23:50:13.253'); }); it('save query should show toast message and display query name', async function () { @@ -92,11 +95,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const time = await PageObjects.timePicker.getTimeConfig(); expect(time.start).to.be('Sep 21, 2015 @ 09:00:00.000'); expect(time.end).to.be('Sep 21, 2015 @ 12:00:00.000'); - await retry.waitFor('doc table to contain the right search result', async () => { - const rowData = await PageObjects.discover.getDocTableField(1); - log.debug(`The first timestamp value in doc table: ${rowData}`); - return rowData.includes('Sep 21, 2015 @ 11:59:22.316'); - }); + await retry.waitForWithTimeout( + 'doc table to contain the right search result', + 1000, + async () => { + const rowData = await PageObjects.discover.getDocTableField(1); + log.debug(`The first timestamp value in doc table: ${rowData}`); + return rowData.includes('Sep 21, 2015 @ 11:59:22.316'); + } + ); }); it('should modify the time range when the histogram is brushed', async function () { @@ -323,7 +330,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); await PageObjects.common.navigateToApp('discover'); await PageObjects.discover.clickFieldListItemAdd('_score'); - await PageObjects.discover.clickFieldSort('_score'); + await PageObjects.discover.clickFieldSort('_score', 'Sort Low-High'); const currentUrlWithScore = await browser.getCurrentUrl(); expect(currentUrlWithScore).to.contain('_score'); await PageObjects.discover.clickFieldListItemAdd('_score'); @@ -334,7 +341,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); await PageObjects.common.navigateToApp('discover'); await PageObjects.discover.clickFieldListItemAdd('referer'); - await PageObjects.discover.clickFieldSort('referer'); + await PageObjects.discover.clickFieldSort('referer', 'Sort A-Z'); expect(await PageObjects.discover.getDocHeader()).to.have.string('Referer custom'); expect(await PageObjects.discover.getAllFieldNames()).to.contain('Referer custom'); const url = await browser.getCurrentUrl(); diff --git a/test/functional/apps/discover/_doc_navigation.ts b/test/functional/apps/discover/_doc_navigation.ts index e783d159cb2615..90d3c4eca423a6 100644 --- a/test/functional/apps/discover/_doc_navigation.ts +++ b/test/functional/apps/discover/_doc_navigation.ts @@ -17,12 +17,23 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'context']); const esArchiver = getService('esArchiver'); const retry = getService('retry'); + const kibanaServer = getService('kibanaServer'); describe('doc link in discover', function contextSize() { - beforeEach(async function () { + before(async () => { await esArchiver.loadIfNeeded('logstash_functional'); await esArchiver.loadIfNeeded('discover'); await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.uiSettings.update({ + 'doc_table:legacy': true, + 'discover:searchFieldsFromSource': true, + }); + }); + after(async () => { + await kibanaServer.uiSettings.replace({}); + }); + + beforeEach(async function () { await PageObjects.common.navigateToApp('discover'); await PageObjects.discover.waitForDocTableLoadingComplete(); }); diff --git a/test/functional/apps/discover/_doc_table.ts b/test/functional/apps/discover/_doc_table.ts index edcb0020001834..1fd26b561195ee 100644 --- a/test/functional/apps/discover/_doc_table.ts +++ b/test/functional/apps/discover/_doc_table.ts @@ -16,13 +16,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const docTable = getService('docTable'); const queryBar = getService('queryBar'); + const find = getService('find'); const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); const defaultSettings = { defaultIndex: 'logstash-*', }; + const testSubjects = getService('testSubjects'); describe('discover doc table', function describeIndexTests() { - const defaultRowsLimit = 50; const rowsHardLimit = 500; before(async function () { @@ -37,10 +38,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.common.navigateToApp('discover'); }); - it('should show the first 50 rows by default', async function () { + it('should show records by default', async function () { // with the default range the number of hits is ~14000 const rows = await PageObjects.discover.getDocTableRows(); - expect(rows.length).to.be(defaultRowsLimit); + expect(rows.length).to.be.greaterThan(0); }); it('should refresh the table content when changing time window', async function () { @@ -57,113 +58,130 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.timePicker.setDefaultAbsoluteRange(); }); - it(`should load up to ${rowsHardLimit} rows when scrolling at the end of the table`, async function () { - const initialRows = await PageObjects.discover.getDocTableRows(); - // click the Skip to the end of the table - await PageObjects.discover.skipToEndOfDocTable(); - // now count the rows - const finalRows = await PageObjects.discover.getDocTableRows(); - expect(finalRows.length).to.be.above(initialRows.length); - expect(finalRows.length).to.be(rowsHardLimit); - await PageObjects.discover.backToTop(); - }); - - it('should go the end of the table when using the accessible Skip button', async function () { - // click the Skip to the end of the table - await PageObjects.discover.skipToEndOfDocTable(); - // now check the footer text content - const footer = await PageObjects.discover.getDocTableFooter(); - log.debug(await footer.getVisibleText()); - expect(await footer.getVisibleText()).to.have.string(rowsHardLimit); - await PageObjects.discover.backToTop(); - }); + describe('legacy', async function () { + before(async () => { + await kibanaServer.uiSettings.update({ 'doc_table:legacy': true }); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + }); + after(async () => { + await kibanaServer.uiSettings.replace({}); + }); + it(`should load up to ${rowsHardLimit} rows when scrolling at the end of the table`, async function () { + const initialRows = await testSubjects.findAll('docTableRow'); + // click the Skip to the end of the table + await PageObjects.discover.skipToEndOfDocTable(); + // now count the rows + const finalRows = await testSubjects.findAll('docTableRow'); + expect(finalRows.length).to.be.above(initialRows.length); + expect(finalRows.length).to.be(rowsHardLimit); + await PageObjects.discover.backToTop(); + }); - describe('expand a document row', function () { - const rowToInspect = 1; - beforeEach(async function () { - // close the toggle if open - const details = await docTable.getDetailsRows(); - if (details.length) { - await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); - } + it('should go the end of the table when using the accessible Skip button', async function () { + // click the Skip to the end of the table + await PageObjects.discover.skipToEndOfDocTable(); + // now check the footer text content + const footer = await PageObjects.discover.getDocTableFooter(); + log.debug(await footer.getVisibleText()); + expect(await footer.getVisibleText()).to.have.string(rowsHardLimit); + await PageObjects.discover.backToTop(); }); - it('should expand the detail row when the toggle arrow is clicked', async function () { - await retry.try(async function () { - await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); - const detailsEl = await docTable.getDetailsRows(); - const defaultMessageEl = await detailsEl[0].findByTestSubject('docTableRowDetailsTitle'); - expect(defaultMessageEl).to.be.ok(); + describe('expand a document row', function () { + const rowToInspect = 1; + beforeEach(async function () { + // close the toggle if open + const details = await docTable.getDetailsRows(); + if (details.length) { + await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); + } }); - }); - it('should show the detail panel actions', async function () { - await retry.try(async function () { - await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); - // const detailsEl = await PageObjects.discover.getDocTableRowDetails(rowToInspect); - const [surroundingActionEl, singleActionEl] = await docTable.getRowActions({ - isAnchorRow: false, - rowIndex: rowToInspect - 1, + it('should expand the detail row when the toggle arrow is clicked', async function () { + await retry.try(async function () { + await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); + const detailsEl = await docTable.getDetailsRows(); + const defaultMessageEl = await detailsEl[0].findByTestSubject( + 'docTableRowDetailsTitle' + ); + expect(defaultMessageEl).to.be.ok(); + }); + }); + + it('should show the detail panel actions', async function () { + await retry.try(async function () { + await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); + // const detailsEl = await PageObjects.discover.getDocTableRowDetails(rowToInspect); + const [surroundingActionEl, singleActionEl] = await docTable.getRowActions({ + isAnchorRow: false, + rowIndex: rowToInspect - 1, + }); + expect(surroundingActionEl).to.be.ok(); + expect(singleActionEl).to.be.ok(); + // TODO: test something more meaninful here? }); - expect(surroundingActionEl).to.be.ok(); - expect(singleActionEl).to.be.ok(); - // TODO: test something more meaninful here? }); - }); - it('should not close the detail panel actions when data is re-requested', async function () { - await retry.try(async function () { - const nrOfFetches = await PageObjects.discover.getNrOfFetches(); - await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); - const detailsEl = await docTable.getDetailsRows(); - const defaultMessageEl = await detailsEl[0].findByTestSubject('docTableRowDetailsTitle'); - expect(defaultMessageEl).to.be.ok(); - await queryBar.submitQuery(); - const nrOfFetchesResubmit = await PageObjects.discover.getNrOfFetches(); - expect(nrOfFetchesResubmit).to.be.above(nrOfFetches); - const defaultMessageElResubmit = await detailsEl[0].findByTestSubject( - 'docTableRowDetailsTitle' - ); - - expect(defaultMessageElResubmit).to.be.ok(); + it('should not close the detail panel actions when data is re-requested', async function () { + await retry.try(async function () { + const nrOfFetches = await PageObjects.discover.getNrOfFetches(); + await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 }); + const detailsEl = await docTable.getDetailsRows(); + const defaultMessageEl = await detailsEl[0].findByTestSubject( + 'docTableRowDetailsTitle' + ); + expect(defaultMessageEl).to.be.ok(); + await queryBar.submitQuery(); + const nrOfFetchesResubmit = await PageObjects.discover.getNrOfFetches(); + expect(nrOfFetchesResubmit).to.be.above(nrOfFetches); + const defaultMessageElResubmit = await detailsEl[0].findByTestSubject( + 'docTableRowDetailsTitle' + ); + + expect(defaultMessageElResubmit).to.be.ok(); + }); }); }); - }); - describe('add and remove columns', function () { - const extraColumns = ['phpmemory', 'ip']; + describe('add and remove columns', function () { + const extraColumns = ['phpmemory', 'ip']; - afterEach(async function () { - for (const column of extraColumns) { - await PageObjects.discover.clickFieldListItemRemove(column); - await PageObjects.header.waitUntilLoadingHasFinished(); - } - }); + afterEach(async function () { + for (const column of extraColumns) { + await PageObjects.discover.clickFieldListItemRemove(column); + await PageObjects.header.waitUntilLoadingHasFinished(); + } + }); - it('should add more columns to the table', async function () { - for (const column of extraColumns) { - await PageObjects.discover.clearFieldSearchInput(); - await PageObjects.discover.findFieldByName(column); - await PageObjects.discover.clickFieldListItemAdd(column); - await PageObjects.header.waitUntilLoadingHasFinished(); - // test the header now - expect(await PageObjects.discover.getDocHeader()).to.have.string(column); - } - }); + it('should add more columns to the table', async function () { + for (const column of extraColumns) { + await PageObjects.discover.clearFieldSearchInput(); + await PageObjects.discover.findFieldByName(column); + await PageObjects.discover.clickFieldListItemAdd(column); + await PageObjects.header.waitUntilLoadingHasFinished(); + // test the header now + const docHeader = await find.byCssSelector('thead > tr:nth-child(1)'); + const docHeaderText = await docHeader.getVisibleText(); + expect(docHeaderText).to.have.string(column); + } + }); - it('should remove columns from the table', async function () { - for (const column of extraColumns) { - await PageObjects.discover.clearFieldSearchInput(); - await PageObjects.discover.findFieldByName(column); - log.debug(`add a ${column} column`); - await PageObjects.discover.clickFieldListItemAdd(column); + it('should remove columns from the table', async function () { + for (const column of extraColumns) { + await PageObjects.discover.clearFieldSearchInput(); + await PageObjects.discover.findFieldByName(column); + log.debug(`add a ${column} column`); + await PageObjects.discover.clickFieldListItemAdd(column); + await PageObjects.header.waitUntilLoadingHasFinished(); + } + // remove the second column + await PageObjects.discover.clickFieldListItemAdd(extraColumns[1]); await PageObjects.header.waitUntilLoadingHasFinished(); - } - // remove the second column - await PageObjects.discover.clickFieldListItemAdd(extraColumns[1]); - await PageObjects.header.waitUntilLoadingHasFinished(); - // test that the second column is no longer there - expect(await PageObjects.discover.getDocHeader()).to.not.have.string(extraColumns[1]); + // test that the second column is no longer there + const docHeader = await find.byCssSelector('thead > tr:nth-child(1)'); + expect(await docHeader.getVisibleText()).to.not.have.string(extraColumns[1]); + }); }); }); }); diff --git a/test/functional/apps/discover/_field_data.ts b/test/functional/apps/discover/_field_data.ts index 3583a8b12c4156..492925cf6b2df8 100644 --- a/test/functional/apps/discover/_field_data.ts +++ b/test/functional/apps/discover/_field_data.ts @@ -18,6 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const queryBar = getService('queryBar'); const browser = getService('browser'); const PageObjects = getPageObjects(['common', 'header', 'discover', 'visualize', 'timePicker']); + const find = getService('find'); describe('discover tab', function describeIndexTests() { this.tags('includeFirefox'); @@ -44,9 +45,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('the search term should be highlighted in the field data', async function () { // marks is the style that highlights the text in yellow + await queryBar.setQuery('php'); + await queryBar.submitQuery(); + await PageObjects.discover.clickFieldListItemAdd('extension'); const marks = await PageObjects.discover.getMarks(); - expect(marks.length).to.be(50); + expect(marks.length).to.be.greaterThan(0); expect(marks.indexOf('php')).to.be(0); + await PageObjects.discover.clickFieldListItemRemove('extension'); }); it('search type:apache should show the correct hit count', async function () { @@ -59,27 +64,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - it('doc view should show Time and _source columns', async function () { - const expectedHeader = 'Time _source'; - const Docheader = await PageObjects.discover.getDocHeader(); - expect(Docheader).to.be(expectedHeader); - }); - - it('doc view should sort ascending', async function () { - const expectedTimeStamp = 'Sep 20, 2015 @ 00:00:00.000'; - await PageObjects.discover.clickDocSortDown(); - - // we don't technically need this sleep here because the tryForTime will retry and the - // results will match on the 2nd or 3rd attempt, but that debug output is huge in this - // case and it can be avoided with just a few seconds sleep. - await PageObjects.common.sleep(2000); - await retry.try(async function tryingForTime() { - const rowData = await PageObjects.discover.getDocTableIndex(1); - - expect(rowData.startsWith(expectedTimeStamp)).to.be.ok(); - }); - }); - it('a bad syntax query should show an error message', async function () { const expectedError = 'Expected ":", "<", "<=", ">", ">=", AND, OR, end of input, ' + @@ -102,15 +86,47 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { { useActualUrl: true } ); await retry.try(async function tryingForTime() { - expect(await PageObjects.discover.getDocHeader()).to.be('Time relatedContent'); + expect(await PageObjects.discover.getDocHeader()).to.contain('relatedContent'); }); - const field = await PageObjects.discover.getDocTableField(1, 1); + const field = await PageObjects.discover.getDocTableField(1, 3); expect(field).to.include.string('"og:description":'); const marks = await PageObjects.discover.getMarks(); expect(marks.length).to.be(0); }); + + describe('legacy table tests', async function () { + before(async function () { + await kibanaServer.uiSettings.update({ 'doc_table:legacy': true }); + await PageObjects.common.navigateToApp('discover'); + }); + + after(async function () { + await kibanaServer.uiSettings.replace({}); + }); + it('doc view should show Time and _source columns', async function () { + const expectedHeader = 'Time _source'; + const docHeader = await find.byCssSelector('thead > tr:nth-child(1)'); + const docHeaderText = await docHeader.getVisibleText(); + expect(docHeaderText).to.be(expectedHeader); + }); + + it('doc view should sort ascending', async function () { + const expectedTimeStamp = 'Sep 20, 2015 @ 00:00:00.000'; + await find.clickByCssSelector('.fa-sort-down'); + + // we don't technically need this sleep here because the tryForTime will retry and the + // results will match on the 2nd or 3rd attempt, but that debug output is huge in this + // case and it can be avoided with just a few seconds sleep. + await PageObjects.common.sleep(2000); + await retry.try(async function tryingForTime() { + const row = await find.byCssSelector(`tr.kbnDocTable__row:nth-child(1)`); + const rowData = await row.getVisibleText(); + expect(rowData.startsWith(expectedTimeStamp)).to.be.ok(); + }); + }); + }); }); }); } diff --git a/test/functional/apps/discover/_field_data_with_fields_api.ts b/test/functional/apps/discover/_field_data_with_fields_api.ts index 168f718c386021..c2705311950113 100644 --- a/test/functional/apps/discover/_field_data_with_fields_api.ts +++ b/test/functional/apps/discover/_field_data_with_fields_api.ts @@ -18,6 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const queryBar = getService('queryBar'); const browser = getService('browser'); const PageObjects = getPageObjects(['common', 'header', 'discover', 'visualize', 'timePicker']); + const find = getService('find'); describe('discover tab with new fields API', function describeIndexTests() { this.tags('includeFirefox'); @@ -44,9 +45,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('the search term should be highlighted in the field data', async function () { // marks is the style that highlights the text in yellow + await PageObjects.discover.clickFieldListItemAdd('extension'); const marks = await PageObjects.discover.getMarks(); - expect(marks.length).to.be(100); + expect(marks.length).to.be.greaterThan(0); expect(marks.indexOf('php')).to.be(0); + await PageObjects.discover.clickFieldListItemRemove('extension'); }); it('search type:apache should show the correct hit count', async function () { @@ -60,24 +63,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('doc view should show Time and Document columns', async function () { - const expectedHeader = 'Time Document'; const Docheader = await PageObjects.discover.getDocHeader(); - expect(Docheader).to.be(expectedHeader); - }); - - it('doc view should sort ascending', async function () { - const expectedTimeStamp = 'Sep 20, 2015 @ 00:00:00.000'; - await PageObjects.discover.clickDocSortDown(); - - // we don't technically need this sleep here because the tryForTime will retry and the - // results will match on the 2nd or 3rd attempt, but that debug output is huge in this - // case and it can be avoided with just a few seconds sleep. - await PageObjects.common.sleep(2000); - await retry.try(async function tryingForTime() { - const rowData = await PageObjects.discover.getDocTableIndex(1); - - expect(rowData.startsWith(expectedTimeStamp)).to.be.ok(); - }); + expect(Docheader).to.contain('Time'); + expect(Docheader).to.contain('Document'); }); it('a bad syntax query should show an error message', async function () { @@ -102,15 +90,42 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { { useActualUrl: true } ); await retry.try(async function tryingForTime() { - expect(await PageObjects.discover.getDocHeader()).to.be('Time relatedContent'); + expect(await PageObjects.discover.getDocHeader()).to.contain('relatedContent'); }); - const field = await PageObjects.discover.getDocTableField(1, 1); - expect(field).to.include.string('relatedContent.url:'); + const field = await PageObjects.discover.getDocTableField(1, 3); + expect(field).to.include.string('relatedContent.url'); const marks = await PageObjects.discover.getMarks(); - expect(marks.length).to.be(172); - expect(marks.indexOf('election')).to.be(0); + expect(marks.length).to.be.above(0); + expect(marks).to.contain('election'); + }); + + describe('legacy table tests', async function () { + before(async function () { + await kibanaServer.uiSettings.update({ 'doc_table:legacy': true }); + await PageObjects.common.navigateToApp('discover'); + }); + + after(async function () { + await kibanaServer.uiSettings.replace({}); + }); + + it('doc view should sort ascending', async function () { + const expectedTimeStamp = 'Sep 20, 2015 @ 00:00:00.000'; + await find.clickByCssSelector('.fa-sort-down'); + + // we don't technically need this sleep here because the tryForTime will retry and the + // results will match on the 2nd or 3rd attempt, but that debug output is huge in this + // case and it can be avoided with just a few seconds sleep. + await PageObjects.common.sleep(2000); + await retry.try(async function tryingForTime() { + const row = await find.byCssSelector(`tr.kbnDocTable__row:nth-child(1)`); + const rowData = await row.getVisibleText(); + + expect(rowData.startsWith(expectedTimeStamp)).to.be.ok(); + }); + }); }); }); }); diff --git a/test/functional/apps/discover/_large_string.ts b/test/functional/apps/discover/_large_string.ts index 5dd5834ffe103c..27561ccf37877a 100644 --- a/test/functional/apps/discover/_large_string.ts +++ b/test/functional/apps/discover/_large_string.ts @@ -32,7 +32,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('verify the large string book present', async function () { const ExpectedDoc = - 'mybook:Project Gutenberg EBook of Hamlet, by William Shakespeare' + + 'mybookProject Gutenberg EBook of Hamlet, by William Shakespeare' + ' This eBook is for the use of anyone anywhere in the United States' + ' and most other parts of the world at no cost and with almost no restrictions whatsoever.' + ' You may copy it, give it away or re-use it under the terms of the' + diff --git a/test/functional/apps/discover/_runtime_fields_editor.ts b/test/functional/apps/discover/_runtime_fields_editor.ts index 7df697a2e7a3a4..9add5323db814e 100644 --- a/test/functional/apps/discover/_runtime_fields_editor.ts +++ b/test/functional/apps/discover/_runtime_fields_editor.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from './ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); const retry = getService('retry'); - const docTable = getService('docTable'); + const dataGrid = getService('dataGrid'); const testSubjects = getService('testSubjects'); const kibanaServer = getService('kibanaServer'); const esArchiver = getService('esArchiver'); @@ -103,15 +103,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('doc view includes runtime fields', async function () { // navigate to doc view - await docTable.clickRowToggle({ rowIndex: 0 }); + await dataGrid.clickRowToggle(); // click the open action await retry.try(async () => { - const rowActions = await docTable.getRowActions({ rowIndex: 0 }); + const rowActions = await dataGrid.getRowActions({ rowIndex: 0 }); if (!rowActions.length) { throw new Error('row actions empty, trying again'); } - await rowActions[1].click(); + await rowActions[0].click(); }); const hasDocHit = await testSubjects.exists('doc-hit'); diff --git a/test/functional/apps/home/_sample_data.ts b/test/functional/apps/home/_sample_data.ts index 12669bafcd780a..5a4bdfeb6b3e83 100644 --- a/test/functional/apps/home/_sample_data.ts +++ b/test/functional/apps/home/_sample_data.ts @@ -101,7 +101,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { log.debug('Checking area, bar and heatmap charts rendered'); await dashboardExpect.seriesElementCount(15); log.debug('Checking saved searches rendered'); - await dashboardExpect.savedSearchRowCount(50); + await dashboardExpect.savedSearchRowCount(11); log.debug('Checking input controls rendered'); await dashboardExpect.inputControlItemCount(3); log.debug('Checking tag cloud rendered'); diff --git a/test/functional/apps/management/_scripted_fields.js b/test/functional/apps/management/_scripted_fields.js index 13af3206a166dd..fdbc419c162412 100644 --- a/test/functional/apps/management/_scripted_fields.js +++ b/test/functional/apps/management/_scripted_fields.js @@ -50,7 +50,7 @@ export default function ({ getService, getPageObjects }) { await esArchiver.load('discover'); // delete .kibana index and then wait for Kibana to re-create it await kibanaServer.uiSettings.replace({}); - await kibanaServer.uiSettings.update({}); + await kibanaServer.uiSettings.update({ 'doc_table:legacy': true }); }); after(async function afterAll() { @@ -149,7 +149,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('Sep 18, 2015 @ 18:20:57.916\n18'); }); }); @@ -163,14 +163,14 @@ export default function ({ getService, getPageObjects }) { await testSubjects.click('docTableHeaderFieldSort_@timestamp'); await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('Sep 17, 2015 @ 10:53:14.181\n-1'); }); await testSubjects.click(`docTableHeaderFieldSort_${scriptedPainlessFieldName}`); await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('Sep 17, 2015 @ 06:32:29.479\n20'); }); }); @@ -238,7 +238,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('Sep 18, 2015 @ 18:20:57.916\ngood'); }); }); @@ -252,14 +252,14 @@ export default function ({ getService, getPageObjects }) { await testSubjects.click('docTableHeaderFieldSort_@timestamp'); await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('Sep 17, 2015 @ 09:48:40.594\nbad'); }); await testSubjects.click(`docTableHeaderFieldSort_${scriptedPainlessFieldName2}`); await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('Sep 17, 2015 @ 06:32:29.479\ngood'); }); }); @@ -327,7 +327,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('Sep 18, 2015 @ 18:20:57.916\ntrue'); }); }); @@ -354,14 +354,14 @@ export default function ({ getService, getPageObjects }) { await testSubjects.click('docTableHeaderFieldSort_@timestamp'); await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('updateExpectedResultHere\ntrue'); }); await testSubjects.click(`docTableHeaderFieldSort_${scriptedPainlessFieldName2}`); await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('updateExpectedResultHere\nfalse'); }); }); @@ -417,7 +417,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('Sep 18, 2015 @ 06:52:55.953\n2015-09-18 07:00'); }); }); @@ -432,14 +432,14 @@ export default function ({ getService, getPageObjects }) { await testSubjects.click('docTableHeaderFieldSort_@timestamp'); await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('updateExpectedResultHere\n2015-09-18 07:00'); }); await testSubjects.click(`docTableHeaderFieldSort_${scriptedPainlessFieldName2}`); await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async function () { - const rowData = await PageObjects.discover.getDocTableIndex(1); + const rowData = await PageObjects.discover.getDocTableIndexLegacy(1); expect(rowData).to.be('updateExpectedResultHere\n2015-09-18 07:00'); }); }); diff --git a/test/functional/page_objects/dashboard_page.ts b/test/functional/page_objects/dashboard_page.ts index 9c12296db138c6..b0610b36eb65f1 100644 --- a/test/functional/page_objects/dashboard_page.ts +++ b/test/functional/page_objects/dashboard_page.ts @@ -220,14 +220,15 @@ export function DashboardPageProvider({ getService, getPageObjects }: FtrProvide /** * Asserts that the toolbar pagination (count and arrows) is either displayed or not displayed. - * @param { displayed: boolean } + */ - public async expectToolbarPaginationDisplayed({ displayed = true }) { - const subjects = ['btnPrevPage', 'btnNextPage', 'toolBarPagerText']; - if (displayed) { - await Promise.all(subjects.map(async (subj) => await testSubjects.existOrFail(subj))); - } else { - await Promise.all(subjects.map(async (subj) => await testSubjects.missingOrFail(subj))); + public async expectToolbarPaginationDisplayed() { + const subjects = ['pagination-button-previous', 'pagination-button-next']; + + await Promise.all(subjects.map(async (subj) => await testSubjects.existOrFail(subj))); + const paginationListExists = await find.existsByCssSelector('.euiPagination__list'); + if (!paginationListExists) { + throw new Error(`expected discover data grid pagination list to exist`); } } diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index 986714d4e87243..4babc914a5f75f 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -20,6 +20,7 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider const docTable = getService('docTable'); const config = getService('config'); const defaultFindTimeout = config.get('timeouts.find'); + const dataGrid = getService('dataGrid'); class DiscoverPage { public async getChartTimespan() { @@ -84,7 +85,7 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider } public async getColumnHeaders() { - return await docTable.getHeaderFields('embeddedSavedSearchDocTable'); + return await dataGrid.getHeaderFields(); } public async openLoadSavedSearchPanel() { @@ -146,7 +147,7 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider await elasticChart.waitForRenderComplete(); const el = await elasticChart.getCanvas(); - await browser.getActions().move({ x: 0, y: 20, origin: el._webElement }).click().perform(); + await browser.getActions().move({ x: 0, y: 0, origin: el._webElement }).click().perform(); } public async brushHistogram() { @@ -186,26 +187,31 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider } public async getDocHeader() { - const docHeader = await find.byCssSelector('thead > tr:nth-child(1)'); - return await docHeader.getVisibleText(); + const docHeader = await dataGrid.getHeaders(); + return docHeader.join(); } public async getDocTableRows() { await header.waitUntilLoadingHasFinished(); - const rows = await testSubjects.findAll('docTableRow'); - return rows; + return await dataGrid.getBodyRows(); } public async getDocTableIndex(index: number) { + const row = await dataGrid.getRow({ rowIndex: index - 1 }); + const result = await Promise.all(row.map(async (cell) => await cell.getVisibleText())); + // Remove control columns + return result.slice(2).join(' '); + } + + public async getDocTableIndexLegacy(index: number) { const row = await find.byCssSelector(`tr.kbnDocTable__row:nth-child(${index})`); return await row.getVisibleText(); } - public async getDocTableField(index: number, cellIndex = 0) { - const fields = await find.allByCssSelector( - `tr.kbnDocTable__row:nth-child(${index}) [data-test-subj='docTableField']` - ); - return await fields[cellIndex].getVisibleText(); + public async getDocTableField(index: number, cellIdx: number = 2) { + const row = await dataGrid.getRow({ rowIndex: index - 1 }); + const result = await Promise.all(row.map(async (cell) => await cell.getVisibleText())); + return result[cellIdx]; } public async skipToEndOfDocTable() { @@ -231,11 +237,11 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider } public async clickDocSortDown() { - await find.clickByCssSelector('.fa-sort-down'); + await dataGrid.clickDocSortAsc(); } public async clickDocSortUp() { - await find.clickByCssSelector('.fa-sort-up'); + await dataGrid.clickDocSortDesc(); } public async isShowingDocViewer() { @@ -244,10 +250,8 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider public async getMarks() { const table = await docTable.getTable(); - const $ = await table.parseDomContent(); - return $('mark') - .toArray() - .map((mark) => $(mark).text()); + const marks = await table.findAllByTagName('mark'); + return await Promise.all(marks.map((mark) => mark.getVisibleText())); } public async toggleSidebarCollapse() { @@ -302,8 +306,8 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider return await testSubjects.click(`field-${field}`); } - public async clickFieldSort(field: string) { - return await testSubjects.click(`docTableHeaderFieldSort_${field}`); + public async clickFieldSort(field: string, text = 'Sort New-Old') { + await dataGrid.clickDocSortAsc(field, text); } public async clickFieldListItemToggle(field: string) { @@ -375,8 +379,7 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider } public async removeHeaderColumn(name: string) { - await testSubjects.moveMouseTo(`docTableHeader-${name}`); - await testSubjects.click(`docTableRemoveHeader-${name}`); + await dataGrid.clickRemoveColumn(name); } public async openSidebarFieldFilter() { diff --git a/test/functional/services/dashboard/expectations.ts b/test/functional/services/dashboard/expectations.ts index e4dc59ae71566c..329a8204cce0e1 100644 --- a/test/functional/services/dashboard/expectations.ts +++ b/test/functional/services/dashboard/expectations.ts @@ -47,14 +47,6 @@ export function DashboardExpectProvider({ getService, getPageObjects }: FtrProvi }); } - async docTableFieldCount(expectedCount: number) { - log.debug(`DashboardExpect.docTableFieldCount(${expectedCount})`); - await retry.try(async () => { - const docTableCells = await testSubjects.findAll('docTableField', findTimeout); - expect(docTableCells.length).to.be(expectedCount); - }); - } - async fieldSuggestions(expectedFields: string[]) { log.debug(`DashboardExpect.fieldSuggestions(${expectedFields})`); const fields = await filterBar.getFilterEditorFields(); diff --git a/test/functional/services/data_grid.ts b/test/functional/services/data_grid.ts index 87fa59b48a3249..8ca6c6e816aa53 100644 --- a/test/functional/services/data_grid.ts +++ b/test/functional/services/data_grid.ts @@ -23,6 +23,7 @@ export function DataGridProvider({ getService, getPageObjects }: FtrProviderCont const find = getService('find'); const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['common', 'header']); + const retry = getService('retry'); class DataGrid { async getDataGridTableData(): Promise { @@ -126,6 +127,9 @@ export function DataGridProvider({ getService, getPageObjects }: FtrProviderCont */ public async getDocTableRows() { const table = await this.getTable(); + if (!table) { + return []; + } const cells = await table.findAllByCssSelector('.euiDataGridRowCell'); const rows: WebElementWrapper[][] = []; @@ -183,14 +187,39 @@ export function DataGridProvider({ getService, getPageObjects }: FtrProviderCont return await detailsRow.findAllByTestSubject('~docTableRowAction'); } - public async clickDocSortAsc() { - await find.clickByCssSelector('.euiDataGridHeaderCell__button'); - await find.clickByButtonText('Sort New-Old'); + public async openColMenuByField(field: string) { + await retry.waitFor('header cell action being displayed', async () => { + // to prevent flakiness + await testSubjects.click(`dataGridHeaderCell-${field}`); + return await testSubjects.exists(`dataGridHeaderCellActionGroup-${field}`); + }); + } + + public async clickDocSortAsc(field?: string, sortText = 'Sort New-Old') { + if (field) { + await this.openColMenuByField(field); + } else { + await find.clickByCssSelector('.euiDataGridHeaderCell__button'); + } + await find.clickByButtonText(sortText); + } + + public async clickDocSortDesc(field?: string, sortText = 'Sort Old-New') { + if (field) { + await this.openColMenuByField(field); + } else { + await find.clickByCssSelector('.euiDataGridHeaderCell__button'); + } + await find.clickByButtonText(sortText); } - public async clickDocSortDesc() { - await find.clickByCssSelector('.euiDataGridHeaderCell__button'); - await find.clickByButtonText('Sort Old-New'); + public async clickRemoveColumn(field?: string) { + if (field) { + await this.openColMenuByField(field); + } else { + await find.clickByCssSelector('.euiDataGridHeaderCell__button'); + } + await find.clickByButtonText('Remove column'); } public async getDetailsRow(): Promise { const detailRows = await this.getDetailsRows(); @@ -234,6 +263,10 @@ export function DataGridProvider({ getService, getPageObjects }: FtrProviderCont await addInclusiveFilterButton.click(); await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); } + + public async hasNoResults() { + return await find.existsByCssSelector('.euiDataGrid__noResults'); + } } return new DataGrid(); diff --git a/test/plugin_functional/test_suites/data_plugin/session.ts b/test/plugin_functional/test_suites/data_plugin/session.ts index 0194a9c8e120b2..ae4f8ffdf40726 100644 --- a/test/plugin_functional/test_suites/data_plugin/session.ts +++ b/test/plugin_functional/test_suites/data_plugin/session.ts @@ -54,7 +54,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide it('Starts a new session on sort', async () => { await PageObjects.discover.clickFieldListItemAdd('speaker'); - await PageObjects.discover.clickFieldSort('speaker'); + await PageObjects.discover.clickFieldSort('speaker', 'Sort A-Z'); await PageObjects.header.waitUntilLoadingHasFinished(); const sessionIds = await getSessionIds(); expect(sessionIds.length).to.be(1); diff --git a/x-pack/test/functional/apps/dashboard/_async_dashboard.ts b/x-pack/test/functional/apps/dashboard/_async_dashboard.ts index 5b2632ef710e4d..88848401a4c9d4 100644 --- a/x-pack/test/functional/apps/dashboard/_async_dashboard.ts +++ b/x-pack/test/functional/apps/dashboard/_async_dashboard.ts @@ -179,7 +179,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { log.debug('Checking area, bar and heatmap charts rendered'); await dashboardExpect.seriesElementCount(15); log.debug('Checking saved searches rendered'); - await dashboardExpect.savedSearchRowCount(50); + await dashboardExpect.savedSearchRowCount(11); log.debug('Checking input controls rendered'); await dashboardExpect.inputControlItemCount(3); log.debug('Checking tag cloud rendered'); diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js index 6bbf1aabe9506e..51e41fe760ddd7 100644 --- a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js +++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js @@ -48,10 +48,10 @@ export default function ({ getService, getPageObjects }) { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); + await dashboardAddPanel.addSavedSearch(savedSearchName); await PageObjects.dashboard.addVisualizations( PageObjects.dashboard.getTestVisualizationNames() ); - await dashboardAddPanel.addSavedSearch(savedSearchName); await PageObjects.dashboard.saveDashboard(dashboardName); }); diff --git a/x-pack/test/functional/apps/security/doc_level_security_roles.js b/x-pack/test/functional/apps/security/doc_level_security_roles.js index 5ecfa80c240a43..db83872e5d9af5 100644 --- a/x-pack/test/functional/apps/security/doc_level_security_roles.js +++ b/x-pack/test/functional/apps/security/doc_level_security_roles.js @@ -81,7 +81,7 @@ export default function ({ getService, getPageObjects }) { }); const rowData = await PageObjects.discover.getDocTableIndex(1); expect(rowData).to.be( - 'name:ABC Company name.keyword:ABC Company region:EAST region.keyword:EAST _id:doc1 _index:dlstest _score:0 _type:_doc' + 'nameABC Companyname.keywordABC CompanyregionEASTregion.keywordEAST_iddoc1_indexdlstest_score0_type_doc' ); }); after('logout', async () => { diff --git a/x-pack/test/functional/apps/security/field_level_security.js b/x-pack/test/functional/apps/security/field_level_security.js index 67ac8f98117e54..83be2f6e1c113c 100644 --- a/x-pack/test/functional/apps/security/field_level_security.js +++ b/x-pack/test/functional/apps/security/field_level_security.js @@ -112,9 +112,7 @@ export default function ({ getService, getPageObjects }) { expect(hitCount).to.be('2'); }); const rowData = await PageObjects.discover.getDocTableIndex(1); - expect(rowData).to.be( - 'customer_name:ABC Company customer_name.keyword:ABC Company customer_region:WEST customer_region.keyword:WEST customer_ssn:444.555.6666 customer_ssn.keyword:444.555.6666 runtime_customer_ssn:444.555.6666 calculated at runtime _id:2 _index:flstest _score:0 _type:_doc' - ); + expect(rowData).to.contain('ssn'); }); it('user customer2 should not see ssn', async function () { @@ -126,9 +124,7 @@ export default function ({ getService, getPageObjects }) { expect(hitCount).to.be('2'); }); const rowData = await PageObjects.discover.getDocTableIndex(1); - expect(rowData).to.be( - 'customer_name:ABC Company customer_name.keyword:ABC Company customer_region:WEST customer_region.keyword:WEST _id:2 _index:flstest _score:0 _type:_doc' - ); + expect(rowData).not.to.contain('ssn'); }); after(async function () { diff --git a/x-pack/test/functional/apps/visualize/precalculated_histogram.ts b/x-pack/test/functional/apps/visualize/precalculated_histogram.ts index 459a497355e0d6..20111b8f4f1e02 100644 --- a/x-pack/test/functional/apps/visualize/precalculated_histogram.ts +++ b/x-pack/test/functional/apps/visualize/precalculated_histogram.ts @@ -27,8 +27,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('appears correctly in discover', async function () { await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.discover.clickFieldListItemAdd('histogram-content'); const rowData = await PageObjects.discover.getDocTableIndex(1); - expect(rowData.includes('"values":[0.3,1,3,4.2,4.8]')).to.be.ok(); + expect(rowData).to.contain('"values":[0.3,1,3,4.2,4.8]'); }); describe('works in visualizations', () => { diff --git a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session_relative_time.ts b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session_relative_time.ts index bb0e9d697063bd..dc107040ecd2e0 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session_relative_time.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session_relative_time.ts @@ -93,7 +93,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { log.debug('Checking area, bar and heatmap charts rendered'); await dashboardExpect.seriesElementCount(15); log.debug('Checking saved searches rendered'); - await dashboardExpect.savedSearchRowCount(50); + await dashboardExpect.savedSearchRowCount(11); log.debug('Checking input controls rendered'); await dashboardExpect.inputControlItemCount(3); log.debug('Checking tag cloud rendered'); 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 2bd539dab5bf30..b9397964fd16a8 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 @@ -14,9 +14,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const browser = getService('browser'); const inspector = getService('inspector'); - const docTable = getService('docTable'); const PageObjects = getPageObjects(['discover', 'common', 'timePicker', 'header', 'context']); const searchSessions = getService('searchSessions'); + const dataGrid = getService('dataGrid'); + const retry = getService('retry'); describe('discover async search', () => { before(async () => { @@ -66,9 +67,16 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('navigation to context cleans the session', async () => { await PageObjects.common.clearAllToasts(); - await docTable.clickRowToggle({ rowIndex: 0 }); - const rowActions = await docTable.getRowActions({ rowIndex: 0 }); - await rowActions[0].click(); + await dataGrid.clickRowToggle({ rowIndex: 0 }); + + await retry.try(async () => { + const rowActions = await dataGrid.getRowActions({ rowIndex: 0 }); + if (!rowActions.length) { + throw new Error('row actions empty, trying again'); + } + await rowActions[1].click(); + }); + await PageObjects.context.waitUntilContextLoadingHasFinished(); await searchSessions.missingOrFail(); });