diff --git a/test/functional/services/index.ts b/test/functional/services/index.ts index 0dd7f20debcbdf..02ca256aceb73f 100644 --- a/test/functional/services/index.ts +++ b/test/functional/services/index.ts @@ -43,7 +43,7 @@ import { ElasticChartProvider, VegaDebugInspectorViewProvider, } from './visualizations'; -import { ListingTableProvider } from './listing_table'; +import { ListingTableService } from './listing_table'; import { SavedQueryManagementComponentProvider } from './saved_query_management_component'; import { KibanaSupertestProvider } from './supertest'; import { MenuToggleProvider } from './menu_toggle'; @@ -63,7 +63,7 @@ export const services = { dashboardVisualizations: DashboardVisualizationProvider, dashboardExpect: DashboardExpectProvider, failureDebugging: FailureDebuggingProvider, - listingTable: ListingTableProvider, + listingTable: ListingTableService, dashboardAddPanel: DashboardAddPanelProvider, dashboardReplacePanel: DashboardReplacePanelProvider, dashboardPanelActions: DashboardPanelActionsProvider, diff --git a/test/functional/services/listing_table.ts b/test/functional/services/listing_table.ts index 0e1fa4a7b2117f..79678cf7a812b8 100644 --- a/test/functional/services/listing_table.ts +++ b/test/functional/services/listing_table.ts @@ -7,202 +7,199 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../ftr_provider_context'; +import { FtrService } from '../ftr_provider_context'; -type AppName = 'visualize' | 'dashboard' | 'map'; +type AppName = keyof typeof PREFIX_MAP; +const PREFIX_MAP = { visualize: 'vis', dashboard: 'dashboard', map: 'map' }; -export function ListingTableProvider({ getService, getPageObjects }: FtrProviderContext) { - const testSubjects = getService('testSubjects'); - const find = getService('find'); - const log = getService('log'); - const retry = getService('retry'); - const { common, header } = getPageObjects(['common', 'header']); - const prefixMap = { visualize: 'vis', dashboard: 'dashboard', map: 'map' }; +export class ListingTableService extends FtrService { + private readonly testSubjects = this.ctx.getService('testSubjects'); + private readonly find = this.ctx.getService('find'); + private readonly log = this.ctx.getService('log'); + private readonly retry = this.ctx.getService('retry'); + private readonly common = this.ctx.getPageObjects(['common']).common; + private readonly header = this.ctx.getPageObjects(['header']).header; - class ListingTable { - private async getSearchFilter() { - return await testSubjects.find('tableListSearchBox'); - } + private async getSearchFilter() { + return await this.testSubjects.find('tableListSearchBox'); + } - /** - * Returns search input value on landing page - */ - public async getSearchFilterValue() { - const searchFilter = await this.getSearchFilter(); - return await searchFilter.getAttribute('value'); - } + /** + * Returns search input value on landing page + */ + public async getSearchFilterValue() { + const searchFilter = await this.getSearchFilter(); + return await searchFilter.getAttribute('value'); + } - /** - * Clears search input on landing page - */ - public async clearSearchFilter() { - const searchFilter = await this.getSearchFilter(); - await searchFilter.clearValue(); - await searchFilter.click(); - } + /** + * Clears search input on landing page + */ + public async clearSearchFilter() { + const searchFilter = await this.getSearchFilter(); + await searchFilter.clearValue(); + await searchFilter.click(); + } - private async getAllItemsNamesOnCurrentPage(): Promise { - const visualizationNames = []; - const links = await find.allByCssSelector('.euiTableRow .euiLink'); - for (let i = 0; i < links.length; i++) { - visualizationNames.push(await links[i].getVisibleText()); - } - log.debug(`Found ${visualizationNames.length} visualizations on current page`); - return visualizationNames; + private async getAllItemsNamesOnCurrentPage(): Promise { + const visualizationNames = []; + const links = await this.find.allByCssSelector('.euiTableRow .euiLink'); + for (let i = 0; i < links.length; i++) { + visualizationNames.push(await links[i].getVisibleText()); } + this.log.debug(`Found ${visualizationNames.length} visualizations on current page`); + return visualizationNames; + } - public async waitUntilTableIsLoaded() { - return retry.try(async () => { - const isLoaded = await find.existsByDisplayedByCssSelector( - '[data-test-subj="itemsInMemTable"]:not(.euiBasicTable-loading)' - ); - - if (isLoaded) { - return true; - } else { - throw new Error('Waiting'); - } - }); - } + public async waitUntilTableIsLoaded() { + return this.retry.try(async () => { + const isLoaded = await this.find.existsByDisplayedByCssSelector( + '[data-test-subj="itemsInMemTable"]:not(.euiBasicTable-loading)' + ); - /** - * Navigates through all pages on Landing page and returns array of items names - */ - public async getAllItemsNames(): Promise { - log.debug('ListingTable.getAllItemsNames'); - let morePages = true; - let visualizationNames: string[] = []; - while (morePages) { - visualizationNames = visualizationNames.concat(await this.getAllItemsNamesOnCurrentPage()); - morePages = !( - (await testSubjects.getAttribute('pagination-button-next', 'disabled')) === 'true' - ); - if (morePages) { - await testSubjects.click('pagerNextButton'); - await header.waitUntilLoadingHasFinished(); - } + if (isLoaded) { + return true; + } else { + throw new Error('Waiting'); } - return visualizationNames; - } + }); + } - /** - * Returns items count on landing page - */ - public async expectItemsCount(appName: AppName, count: number) { - await retry.try(async () => { - const elements = await find.allByCssSelector( - `[data-test-subj^="${prefixMap[appName]}ListingTitleLink"]` - ); - expect(elements.length).to.equal(count); - }); + /** + * Navigates through all pages on Landing page and returns array of items names + */ + public async getAllItemsNames(): Promise { + this.log.debug('ListingTable.getAllItemsNames'); + let morePages = true; + let visualizationNames: string[] = []; + while (morePages) { + visualizationNames = visualizationNames.concat(await this.getAllItemsNamesOnCurrentPage()); + morePages = !( + (await this.testSubjects.getAttribute('pagination-button-next', 'disabled')) === 'true' + ); + if (morePages) { + await this.testSubjects.click('pagerNextButton'); + await this.header.waitUntilLoadingHasFinished(); + } } + return visualizationNames; + } - /** - * Types name into search field on Landing page and waits till search completed - * @param name item name - */ - public async searchForItemWithName(name: string, { escape = true }: { escape?: boolean } = {}) { - log.debug(`searchForItemWithName: ${name}`); - - await retry.try(async () => { - const searchFilter = await this.getSearchFilter(); - await searchFilter.clearValue(); - await searchFilter.click(); - - if (escape) { - name = name - // Note: this replacement of - to space is to preserve original logic but I'm not sure why or if it's needed. - .replace('-', ' ') - // Remove `[*]` from search as it is not supported by EUI Query's syntax. - .replace(/ *\[[^)]*\] */g, ''); - } - - await searchFilter.type(name); - await common.pressEnterKey(); - }); + /** + * Returns items count on landing page + */ + public async expectItemsCount(appName: AppName, count: number) { + await this.retry.try(async () => { + const elements = await this.find.allByCssSelector( + `[data-test-subj^="${PREFIX_MAP[appName]}ListingTitleLink"]` + ); + expect(elements.length).to.equal(count); + }); + } - await header.waitUntilLoadingHasFinished(); - } + /** + * Types name into search field on Landing page and waits till search completed + * @param name item name + */ + public async searchForItemWithName(name: string, { escape = true }: { escape?: boolean } = {}) { + this.log.debug(`searchForItemWithName: ${name}`); - /** - * Searches for item on Landing page and retruns items count that match `ListingTitleLink-${name}` pattern - */ - public async searchAndExpectItemsCount(appName: AppName, name: string, count: number) { - await this.searchForItemWithName(name); - await retry.try(async () => { - const links = await testSubjects.findAll( - `${prefixMap[appName]}ListingTitleLink-${name.replace(/ /g, '-')}` - ); - expect(links.length).to.equal(count); - }); - } + await this.retry.try(async () => { + const searchFilter = await this.getSearchFilter(); + await searchFilter.clearValue(); + await searchFilter.click(); - public async clickDeleteSelected() { - await testSubjects.click('deleteSelectedItems'); - } + if (escape) { + name = name + // Note: this replacement of - to space is to preserve original logic but I'm not sure why or if it's needed. + .replace('-', ' ') + // Remove `[*]` from search as it is not supported by EUI Query's syntax. + .replace(/ *\[[^)]*\] */g, ''); + } - public async clickItemCheckbox(id: string) { - await testSubjects.click(`checkboxSelectRow-${id}`); - } + await searchFilter.type(name); + await this.common.pressEnterKey(); + }); - /** - * Searches for item by name, selects checbox and deletes it - * @param name item name - * @param id row id - */ - public async deleteItem(name: string, id: string) { - await this.searchForItemWithName(name); - await this.clickItemCheckbox(id); - await this.clickDeleteSelected(); - await common.clickConfirmOnModal(); - } + await this.header.waitUntilLoadingHasFinished(); + } - /** - * Clicks item on Landing page by link name if it is present - */ - public async clickItemLink(appName: AppName, name: string) { - await testSubjects.click( - `${prefixMap[appName]}ListingTitleLink-${name.split(' ').join('-')}` + /** + * Searches for item on Landing page and retruns items count that match `ListingTitleLink-${name}` pattern + */ + public async searchAndExpectItemsCount(appName: AppName, name: string, count: number) { + await this.searchForItemWithName(name); + await this.retry.try(async () => { + const links = await this.testSubjects.findAll( + `${PREFIX_MAP[appName]}ListingTitleLink-${name.replace(/ /g, '-')}` ); - } + expect(links.length).to.equal(count); + }); + } - /** - * Checks 'SelectAll' checkbox on - */ - public async checkListingSelectAllCheckbox() { - const element = await testSubjects.find('checkboxSelectAll'); - const isSelected = await element.isSelected(); - if (!isSelected) { - log.debug(`checking checkbox "checkboxSelectAll"`); - await testSubjects.click('checkboxSelectAll'); - } - } + public async clickDeleteSelected() { + await this.testSubjects.click('deleteSelectedItems'); + } - /** - * Clicks NewItem button on Landing page - * @param promptBtnTestSubj testSubj locator for Prompt button - */ - public async clickNewButton(promptBtnTestSubj: string): Promise { - await retry.tryForTime(20000, async () => { - // newItemButton button is only visible when there are items in the listing table is displayed. - const isnNewItemButtonPresent = await testSubjects.exists('newItemButton', { - timeout: 10000, - }); - if (isnNewItemButtonPresent) { - await testSubjects.click('newItemButton'); - } else { - // no items exist, click createPromptButton to create new dashboard/visualization - await testSubjects.click(promptBtnTestSubj); - } - }); + public async clickItemCheckbox(id: string) { + await this.testSubjects.click(`checkboxSelectRow-${id}`); + } + + /** + * Searches for item by name, selects checbox and deletes it + * @param name item name + * @param id row id + */ + public async deleteItem(name: string, id: string) { + await this.searchForItemWithName(name); + await this.clickItemCheckbox(id); + await this.clickDeleteSelected(); + await this.common.clickConfirmOnModal(); + } + + /** + * Clicks item on Landing page by link name if it is present + */ + public async clickItemLink(appName: AppName, name: string) { + await this.testSubjects.click( + `${PREFIX_MAP[appName]}ListingTitleLink-${name.split(' ').join('-')}` + ); + } + + /** + * Checks 'SelectAll' checkbox on + */ + public async checkListingSelectAllCheckbox() { + const element = await this.testSubjects.find('checkboxSelectAll'); + const isSelected = await element.isSelected(); + if (!isSelected) { + this.log.debug(`checking checkbox "checkboxSelectAll"`); + await this.testSubjects.click('checkboxSelectAll'); } + } - public async onListingPage(appName: AppName) { - return await testSubjects.exists(`${appName}LandingPage`, { - timeout: 5000, + /** + * Clicks NewItem button on Landing page + * @param promptBtnTestSubj testSubj locator for Prompt button + */ + public async clickNewButton(promptBtnTestSubj: string): Promise { + await this.retry.tryForTime(20000, async () => { + // newItemButton button is only visible when there are items in the listing table is displayed. + const isnNewItemButtonPresent = await this.testSubjects.exists('newItemButton', { + timeout: 10000, }); - } + if (isnNewItemButtonPresent) { + await this.testSubjects.click('newItemButton'); + } else { + // no items exist, click createPromptButton to create new dashboard/visualization + await this.testSubjects.click(promptBtnTestSubj); + } + }); } - return new ListingTable(); + public async onListingPage(appName: AppName) { + return await this.testSubjects.exists(`${appName}LandingPage`, { + timeout: 5000, + }); + } }