Skip to content

Commit

Permalink
[ftr] migrate "listingTable" service to FtrService class
Browse files Browse the repository at this point in the history
  • Loading branch information
spalger committed May 25, 2021
1 parent a0ddca8 commit b8a15eb
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 173 deletions.
4 changes: 2 additions & 2 deletions test/functional/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -63,7 +63,7 @@ export const services = {
dashboardVisualizations: DashboardVisualizationProvider,
dashboardExpect: DashboardExpectProvider,
failureDebugging: FailureDebuggingProvider,
listingTable: ListingTableProvider,
listingTable: ListingTableService,
dashboardAddPanel: DashboardAddPanelProvider,
dashboardReplacePanel: DashboardReplacePanelProvider,
dashboardPanelActions: DashboardPanelActionsProvider,
Expand Down
339 changes: 168 additions & 171 deletions test/functional/services/listing_table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string[]> {
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<string[]> {
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<string[]> {
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<string[]> {
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<void> {
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<void> {
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,
});
}
}

0 comments on commit b8a15eb

Please sign in to comment.