diff --git a/test/functional/services/data_grid.ts b/test/functional/services/data_grid.ts index ee50185db8c68..a00587c978977 100644 --- a/test/functional/services/data_grid.ts +++ b/test/functional/services/data_grid.ts @@ -7,7 +7,7 @@ */ import { chunk } from 'lodash'; -import { FtrProviderContext } from '../ftr_provider_context'; +import { FtrService } from '../ftr_provider_context'; import { WebElementWrapper } from './lib/web_element_wrapper'; interface TabbedGridData { @@ -19,261 +19,254 @@ interface SelectOptions { rowIndex: number; } -export function DataGridProvider({ getService, getPageObjects }: FtrProviderContext) { - const find = getService('find'); - const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'header']); - const retry = getService('retry'); - - class DataGrid { - async getDataGridTableData(): Promise { - const table = await find.byCssSelector('.euiDataGrid'); - const $ = await table.parseDomContent(); - - const columns = $('.euiDataGridHeaderCell__content') - .toArray() - .map((cell) => $(cell).text()); - const cells = $.findTestSubjects('dataGridRowCell') - .toArray() - .map((cell) => $(cell).text()); - - const rows = chunk(cells, columns.length); - - return { - columns, - rows, - }; - } - - /** - * Converts the data grid data into nested array - * [ [cell1_in_row1, cell2_in_row1], [cell1_in_row2, cell2_in_row2] ] - * @param element table - */ - public async getDataFromElement( - element: WebElementWrapper, - cellDataTestSubj: string - ): Promise { - const $ = await element.parseDomContent(); - const columnNumber = $('.euiDataGridHeaderCell__content').length; - const cells = $.findTestSubjects('dataGridRowCell') - .toArray() - .map((cell) => - $(cell) - .findTestSubject(cellDataTestSubj) - .text() - .replace(/ /g, '') - .trim() - ); - - return chunk(cells, columnNumber); - } - - /** - * Returns an array of data grid headers names - */ - public async getHeaders() { - const header = await testSubjects.find('dataGridWrapper > dataGridHeader'); - const $ = await header.parseDomContent(); - return $('.euiDataGridHeaderCell__content') - .toArray() - .map((cell) => $(cell).text()); - } +export class DataGridService extends FtrService { + private readonly find = this.ctx.getService('find'); + private readonly testSubjects = this.ctx.getService('testSubjects'); + private readonly PageObjects = this.ctx.getPageObjects(['common', 'header']); + private readonly retry = this.ctx.getService('retry'); + + async getDataGridTableData(): Promise { + const table = await this.find.byCssSelector('.euiDataGrid'); + const $ = await table.parseDomContent(); + + const columns = $('.euiDataGridHeaderCell__content') + .toArray() + .map((cell) => $(cell).text()); + const cells = $.findTestSubjects('dataGridRowCell') + .toArray() + .map((cell) => $(cell).text()); + + const rows = chunk(cells, columns.length); + + return { + columns, + rows, + }; + } - /** - * Returns a grid cell element by row & column indexes. - * The row offset equals 1 since the first row of data grid is the header row. - * @param rowIndex data row index starting from 1 (1 means 1st row) - * @param columnIndex column index starting from 1 (1 means 1st column) - */ - public async getCellElement(rowIndex: number, columnIndex: number) { - const table = await find.byCssSelector('.euiDataGrid'); - const $ = await table.parseDomContent(); - const columnNumber = $('.euiDataGridHeaderCell__content').length; - return await find.byCssSelector( - `[data-test-subj="dataGridWrapper"] [data-test-subj="dataGridRowCell"]:nth-of-type(${ - columnNumber * (rowIndex - 1) + columnIndex + 1 - })` + /** + * Converts the data grid data into nested array + * [ [cell1_in_row1, cell2_in_row1], [cell1_in_row2, cell2_in_row2] ] + * @param element table + */ + public async getDataFromElement( + element: WebElementWrapper, + cellDataTestSubj: string + ): Promise { + const $ = await element.parseDomContent(); + const columnNumber = $('.euiDataGridHeaderCell__content').length; + const cells = $.findTestSubjects('dataGridRowCell') + .toArray() + .map((cell) => + $(cell) + .findTestSubject(cellDataTestSubj) + .text() + .replace(/ /g, '') + .trim() ); - } - public async getDocCount(): Promise { - const grid = await find.byCssSelector('[data-document-number]'); - return Number(await grid.getAttribute('data-document-number')); - } + return chunk(cells, columnNumber); + } - public async getFields() { - const cells = await find.allByCssSelector('.euiDataGridRowCell'); - - const rows: string[][] = []; - let rowIdx = -1; - for (const cell of cells) { - if (await cell.elementHasClass('euiDataGridRowCell--firstColumn')) { - // first column contains expand icon - rowIdx++; - rows[rowIdx] = []; - } - if (!(await cell.elementHasClass('euiDataGridRowCell--controlColumn'))) { - rows[rowIdx].push(await cell.getVisibleText()); - } - } - return rows; - } + /** + * Returns an array of data grid headers names + */ + public async getHeaders() { + const header = await this.testSubjects.find('dataGridWrapper > dataGridHeader'); + const $ = await header.parseDomContent(); + return $('.euiDataGridHeaderCell__content') + .toArray() + .map((cell) => $(cell).text()); + } - public async getTable(selector: string = 'docTable') { - return await testSubjects.find(selector); - } + /** + * Returns a grid cell element by row & column indexes. + * The row offset equals 1 since the first row of data grid is the header row. + * @param rowIndex data row index starting from 1 (1 means 1st row) + * @param columnIndex column index starting from 1 (1 means 1st column) + */ + public async getCellElement(rowIndex: number, columnIndex: number) { + const table = await this.find.byCssSelector('.euiDataGrid'); + const $ = await table.parseDomContent(); + const columnNumber = $('.euiDataGridHeaderCell__content').length; + return await this.find.byCssSelector( + `[data-test-subj="dataGridWrapper"] [data-test-subj="dataGridRowCell"]:nth-of-type(${ + columnNumber * (rowIndex - 1) + columnIndex + 1 + })` + ); + } - public async getBodyRows(): Promise { - return this.getDocTableRows(); - } + public async getDocCount(): Promise { + const grid = await this.find.byCssSelector('[data-document-number]'); + return Number(await grid.getAttribute('data-document-number')); + } - /** - * Returns an array of rows (which are array of cells) - */ - public async getDocTableRows() { - const table = await this.getTable(); - if (!table) { - return []; + public async getFields() { + const cells = await this.find.allByCssSelector('.euiDataGridRowCell'); + + const rows: string[][] = []; + let rowIdx = -1; + for (const cell of cells) { + if (await cell.elementHasClass('euiDataGridRowCell--firstColumn')) { + // first column contains expand icon + rowIdx++; + rows[rowIdx] = []; } - const cells = await table.findAllByCssSelector('.euiDataGridRowCell'); - - const rows: WebElementWrapper[][] = []; - let rowIdx = -1; - for (const cell of cells) { - if (await cell.elementHasClass('euiDataGridRowCell--firstColumn')) { - rowIdx++; - rows[rowIdx] = []; - } - rows[rowIdx].push(cell); + if (!(await cell.elementHasClass('euiDataGridRowCell--controlColumn'))) { + rows[rowIdx].push(await cell.getVisibleText()); } - return rows; - } - - /** - * Returns an array of cells for that row - */ - public async getRow(options: SelectOptions): Promise { - return (await this.getBodyRows())[options.rowIndex]; } + return rows; + } - public async clickRowToggle( - options: SelectOptions = { isAnchorRow: false, rowIndex: 0 } - ): Promise { - const row = await this.getRow(options); - const toggle = await row[0]; - await toggle.click(); - } + public async getTable(selector: string = 'docTable') { + return await this.testSubjects.find(selector); + } - public async getDetailsRows(): Promise { - return await testSubjects.findAll('docTableDetailsFlyout'); - } + public async getBodyRows(): Promise { + return this.getDocTableRows(); + } - public async closeFlyout() { - await testSubjects.click('euiFlyoutCloseButton'); + /** + * Returns an array of rows (which are array of cells) + */ + public async getDocTableRows() { + const table = await this.getTable(); + if (!table) { + return []; } - - public async getHeaderFields(): Promise { - const result = await find.allByCssSelector('.euiDataGridHeaderCell__content'); - const textArr = []; - let idx = 0; - for (const cell of result) { - if (idx > 1) { - textArr.push(await cell.getVisibleText()); - } - idx++; + const cells = await table.findAllByCssSelector('.euiDataGridRowCell'); + + const rows: WebElementWrapper[][] = []; + let rowIdx = -1; + for (const cell of cells) { + if (await cell.elementHasClass('euiDataGridRowCell--firstColumn')) { + rowIdx++; + rows[rowIdx] = []; } - return Promise.resolve(textArr); + rows[rowIdx].push(cell); } + return rows; + } - public async getRowActions( - options: SelectOptions = { isAnchorRow: false, rowIndex: 0 } - ): Promise { - const detailsRow = (await this.getDetailsRows())[options.rowIndex]; - return await detailsRow.findAllByTestSubject('~docTableRowAction'); - } + /** + * Returns an array of cells for that row + */ + public async getRow(options: SelectOptions): Promise { + return (await this.getBodyRows())[options.rowIndex]; + } - 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 clickRowToggle( + options: SelectOptions = { isAnchorRow: false, rowIndex: 0 } + ): Promise { + const row = await this.getRow(options); + const toggle = await row[0]; + await toggle.click(); + } - 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 getDetailsRows(): Promise { + return await this.testSubjects.findAll('docTableDetailsFlyout'); + } - 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 closeFlyout() { + await this.testSubjects.click('euiFlyoutCloseButton'); + } - public async clickRemoveColumn(field?: string) { - if (field) { - await this.openColMenuByField(field); - } else { - await find.clickByCssSelector('.euiDataGridHeaderCell__button'); + public async getHeaderFields(): Promise { + const result = await this.find.allByCssSelector('.euiDataGridHeaderCell__content'); + const textArr = []; + let idx = 0; + for (const cell of result) { + if (idx > 1) { + textArr.push(await cell.getVisibleText()); } - await find.clickByButtonText('Remove column'); - } - public async getDetailsRow(): Promise { - const detailRows = await this.getDetailsRows(); - return detailRows[0]; - } - public async addInclusiveFilter( - detailsRow: WebElementWrapper, - fieldName: string - ): Promise { - const tableDocViewRow = await this.getTableDocViewRow(detailsRow, fieldName); - const addInclusiveFilterButton = await this.getAddInclusiveFilterButton(tableDocViewRow); - await addInclusiveFilterButton.click(); - await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); + idx++; } + return Promise.resolve(textArr); + } - public async getAddInclusiveFilterButton( - tableDocViewRow: WebElementWrapper - ): Promise { - return await tableDocViewRow.findByTestSubject(`~addInclusiveFilterButton`); - } + public async getRowActions( + options: SelectOptions = { isAnchorRow: false, rowIndex: 0 } + ): Promise { + const detailsRow = (await this.getDetailsRows())[options.rowIndex]; + return await detailsRow.findAllByTestSubject('~docTableRowAction'); + } - public async getTableDocViewRow( - detailsRow: WebElementWrapper, - fieldName: string - ): Promise { - return await detailsRow.findByTestSubject(`~tableDocViewRow-${fieldName}`); - } + public async openColMenuByField(field: string) { + await this.retry.waitFor('header cell action being displayed', async () => { + // to prevent flakiness + await this.testSubjects.click(`dataGridHeaderCell-${field}`); + return await this.testSubjects.exists(`dataGridHeaderCellActionGroup-${field}`); + }); + } - public async getRemoveInclusiveFilterButton( - tableDocViewRow: WebElementWrapper - ): Promise { - return await tableDocViewRow.findByTestSubject(`~removeInclusiveFilterButton`); + public async clickDocSortAsc(field?: string, sortText = 'Sort New-Old') { + if (field) { + await this.openColMenuByField(field); + } else { + await this.find.clickByCssSelector('.euiDataGridHeaderCell__button'); } + await this.find.clickByButtonText(sortText); + } - public async removeInclusiveFilter( - detailsRow: WebElementWrapper, - fieldName: string - ): Promise { - const tableDocViewRow = await this.getTableDocViewRow(detailsRow, fieldName); - const addInclusiveFilterButton = await this.getRemoveInclusiveFilterButton(tableDocViewRow); - await addInclusiveFilterButton.click(); - await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); + public async clickDocSortDesc(field?: string, sortText = 'Sort Old-New') { + if (field) { + await this.openColMenuByField(field); + } else { + await this.find.clickByCssSelector('.euiDataGridHeaderCell__button'); } + await this.find.clickByButtonText(sortText); + } - public async hasNoResults() { - return await find.existsByCssSelector('.euiDataGrid__noResults'); + public async clickRemoveColumn(field?: string) { + if (field) { + await this.openColMenuByField(field); + } else { + await this.find.clickByCssSelector('.euiDataGridHeaderCell__button'); } + await this.find.clickByButtonText('Remove column'); + } + public async getDetailsRow(): Promise { + const detailRows = await this.getDetailsRows(); + return detailRows[0]; + } + public async addInclusiveFilter(detailsRow: WebElementWrapper, fieldName: string): Promise { + const tableDocViewRow = await this.getTableDocViewRow(detailsRow, fieldName); + const addInclusiveFilterButton = await this.getAddInclusiveFilterButton(tableDocViewRow); + await addInclusiveFilterButton.click(); + await this.PageObjects.header.awaitGlobalLoadingIndicatorHidden(); + } + + public async getAddInclusiveFilterButton( + tableDocViewRow: WebElementWrapper + ): Promise { + return await tableDocViewRow.findByTestSubject(`~addInclusiveFilterButton`); } - return new DataGrid(); + public async getTableDocViewRow( + detailsRow: WebElementWrapper, + fieldName: string + ): Promise { + return await detailsRow.findByTestSubject(`~tableDocViewRow-${fieldName}`); + } + + public async getRemoveInclusiveFilterButton( + tableDocViewRow: WebElementWrapper + ): Promise { + return await tableDocViewRow.findByTestSubject(`~removeInclusiveFilterButton`); + } + + public async removeInclusiveFilter( + detailsRow: WebElementWrapper, + fieldName: string + ): Promise { + const tableDocViewRow = await this.getTableDocViewRow(detailsRow, fieldName); + const addInclusiveFilterButton = await this.getRemoveInclusiveFilterButton(tableDocViewRow); + await addInclusiveFilterButton.click(); + await this.PageObjects.header.awaitGlobalLoadingIndicatorHidden(); + } + + public async hasNoResults() { + return await this.find.existsByCssSelector('.euiDataGrid__noResults'); + } } diff --git a/test/functional/services/index.ts b/test/functional/services/index.ts index f37b0b544fd66..f5415e34c29e8 100644 --- a/test/functional/services/index.ts +++ b/test/functional/services/index.ts @@ -37,7 +37,7 @@ import { QueryBarProvider } from './query_bar'; import { RemoteProvider } from './remote'; import { RenderableProvider } from './renderable'; import { ToastsProvider } from './toasts'; -import { DataGridProvider } from './data_grid'; +import { DataGridService } from './data_grid'; import { PieChartProvider, ElasticChartProvider, @@ -69,7 +69,7 @@ export const services = { dashboardPanelActions: DashboardPanelActionsProvider, flyout: FlyoutProvider, comboBox: ComboBoxProvider, - dataGrid: DataGridProvider, + dataGrid: DataGridService, embedding: EmbeddingProvider, renderable: RenderableProvider, browser: BrowserProvider,