[ftr] migrate "flyout" and "inspector" services to FtrService class (#100602) (#100739)

Co-authored-by: spalger <spalger@users.noreply.github.com>

Co-authored-by: Spencer <email@spalger.com>
Co-authored-by: spalger <spalger@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2021-05-26 18:52:52 -04:00 committed by GitHub
parent 0055a4aaea
commit b6a231621c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 259 additions and 267 deletions

View file

@ -6,50 +6,46 @@
* Side Public License, v 1.
*/
import { FtrProviderContext } from '../ftr_provider_context';
import { FtrService } from '../ftr_provider_context';
export function FlyoutProvider({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const find = getService('find');
const log = getService('log');
const retry = getService('retry');
export class FlyoutService 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');
class Flyout {
public async close(dataTestSubj: string): Promise<void> {
log.debug('Closing flyout', dataTestSubj);
const flyoutElement = await testSubjects.find(dataTestSubj);
const closeBtn = await flyoutElement.findByCssSelector('[aria-label*="Close"]');
await closeBtn.click();
await retry.waitFor(
'flyout closed',
async () => !(await testSubjects.exists(dataTestSubj, { timeout: 1000 }))
);
}
public async close(dataTestSubj: string): Promise<void> {
this.log.debug('Closing flyout', dataTestSubj);
const flyoutElement = await this.testSubjects.find(dataTestSubj);
const closeBtn = await flyoutElement.findByCssSelector('[aria-label*="Close"]');
await closeBtn.click();
await this.retry.waitFor(
'flyout closed',
async () => !(await this.testSubjects.exists(dataTestSubj, { timeout: 1000 }))
);
}
public async ensureClosed(dataTestSubj: string): Promise<void> {
if (await testSubjects.exists(dataTestSubj, { timeout: 1000 })) {
await this.close(dataTestSubj);
}
}
public async ensureAllClosed(): Promise<void> {
const flyoutElements = await find.allByCssSelector('.euiFlyout');
if (!flyoutElements.length) {
return;
}
for (let i = 0; i < flyoutElements.length; i++) {
const closeBtn = await flyoutElements[i].findByCssSelector('[aria-label*="Close"]');
await closeBtn.click();
}
await retry.waitFor(
'all flyouts to be closed',
async () => (await find.allByCssSelector('.euiFlyout')).length === 0
);
public async ensureClosed(dataTestSubj: string): Promise<void> {
if (await this.testSubjects.exists(dataTestSubj, { timeout: 1000 })) {
await this.close(dataTestSubj);
}
}
return new Flyout();
public async ensureAllClosed(): Promise<void> {
const flyoutElements = await this.find.allByCssSelector('.euiFlyout');
if (!flyoutElements.length) {
return;
}
for (let i = 0; i < flyoutElements.length; i++) {
const closeBtn = await flyoutElements[i].findByCssSelector('[aria-label*="Close"]');
await closeBtn.click();
}
await this.retry.waitFor(
'all flyouts to be closed',
async () => (await this.find.allByCssSelector('.euiFlyout')).length === 0
);
}
}

View file

@ -28,9 +28,9 @@ import {
import { DocTableService } from './doc_table';
import { EmbeddingProvider } from './embedding';
import { FilterBarService } from './filter_bar';
import { FlyoutProvider } from './flyout';
import { FlyoutService } from './flyout';
import { GlobalNavService } from './global_nav';
import { InspectorProvider } from './inspector';
import { InspectorService } from './inspector';
import { FieldEditorService } from './field_editor';
import { ManagementMenuService } from './management';
import { QueryBarProvider } from './query_bar';
@ -67,14 +67,14 @@ export const services = {
dashboardAddPanel: DashboardAddPanelService,
dashboardReplacePanel: DashboardReplacePanelService,
dashboardPanelActions: DashboardPanelActionsService,
flyout: FlyoutProvider,
flyout: FlyoutService,
comboBox: ComboBoxProvider,
dataGrid: DataGridService,
embedding: EmbeddingProvider,
renderable: RenderableProvider,
browser: BrowserProvider,
pieChart: PieChartService,
inspector: InspectorProvider,
inspector: InspectorService,
fieldEditor: FieldEditorService,
vegaDebugInspector: VegaDebugInspectorViewService,
appsMenu: AppsMenuProvider,

View file

@ -7,234 +7,230 @@
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
import { FtrService } from '../ftr_provider_context';
export function InspectorProvider({ getService }: FtrProviderContext) {
const log = getService('log');
const retry = getService('retry');
const renderable = getService('renderable');
const flyout = getService('flyout');
const testSubjects = getService('testSubjects');
const find = getService('find');
export class InspectorService extends FtrService {
private readonly log = this.ctx.getService('log');
private readonly retry = this.ctx.getService('retry');
private readonly renderable = this.ctx.getService('renderable');
private readonly flyout = this.ctx.getService('flyout');
private readonly testSubjects = this.ctx.getService('testSubjects');
private readonly find = this.ctx.getService('find');
class Inspector {
private async getIsEnabled(): Promise<boolean> {
const ariaDisabled = await testSubjects.getAttribute('openInspectorButton', 'disabled');
return ariaDisabled !== 'true';
}
private async getIsEnabled(): Promise<boolean> {
const ariaDisabled = await this.testSubjects.getAttribute('openInspectorButton', 'disabled');
return ariaDisabled !== 'true';
}
/**
* Asserts that inspector is enabled
*/
public async expectIsEnabled(): Promise<void> {
await retry.try(async () => {
const isEnabled = await this.getIsEnabled();
expect(isEnabled).to.be(true);
/**
* Asserts that inspector is enabled
*/
public async expectIsEnabled(): Promise<void> {
await this.retry.try(async () => {
const isEnabled = await this.getIsEnabled();
expect(isEnabled).to.be(true);
});
}
/**
* Asserts that inspector is disabled
*/
public async expectIsNotEnabled(): Promise<void> {
await this.retry.try(async () => {
const isEnabled = await this.getIsEnabled();
expect(isEnabled).to.be(false);
});
}
/**
* Opens inspector panel
*/
public async open(): Promise<void> {
this.log.debug('Inspector.open');
const isOpen = await this.testSubjects.exists('inspectorPanel');
if (!isOpen) {
await this.retry.try(async () => {
await this.testSubjects.click('openInspectorButton');
await this.testSubjects.exists('inspectorPanel');
});
}
/**
* Asserts that inspector is disabled
*/
public async expectIsNotEnabled(): Promise<void> {
await retry.try(async () => {
const isEnabled = await this.getIsEnabled();
expect(isEnabled).to.be(false);
});
}
/**
* Opens inspector panel
*/
public async open(): Promise<void> {
log.debug('Inspector.open');
const isOpen = await testSubjects.exists('inspectorPanel');
if (!isOpen) {
await retry.try(async () => {
await testSubjects.click('openInspectorButton');
await testSubjects.exists('inspectorPanel');
});
}
}
/**
* Closes inspector panel
*/
public async close(): Promise<void> {
log.debug('Close Inspector');
let isOpen = await testSubjects.exists('inspectorPanel');
if (isOpen) {
await retry.try(async () => {
await flyout.close('inspectorPanel');
isOpen = await testSubjects.exists('inspectorPanel');
if (isOpen) {
throw new Error('Failed to close inspector');
}
});
}
}
/**
* Asserts data on inspector panel
* @param expectedData
*/
public async expectTableData(expectedData: string[][]): Promise<void> {
log.debug(`Inspector.expectTableData(${expectedData.join(',')})`);
const data = await this.getTableData();
expect(data).to.eql(expectedData);
}
/**
* Sets table page size
* @param size rows count
*/
public async setTablePageSize(size: number): Promise<void> {
const panel = await testSubjects.find('inspectorPanel');
await find.clickByButtonText('Rows per page: 20', panel);
// The buttons for setting table page size are in a popover element. This popover
// element appears as if it's part of the inspectorPanel but it's really attached
// to the body element by a portal.
const tableSizesPopover = await find.byCssSelector('.euiPanel .euiContextMenuPanel');
await find.clickByButtonText(`${size} rows`, tableSizesPopover);
}
/**
* Returns table data in nested array format
*/
public async getTableData(): Promise<string[][]> {
// TODO: we should use datat-test-subj=inspectorTable as soon as EUI supports it
const inspectorPanel = await testSubjects.find('inspectorPanel');
const tableBody = await retry.try(async () => inspectorPanel.findByTagName('tbody'));
const $ = await tableBody.parseDomContent();
return $('tr')
.toArray()
.map((tr) => {
return $(tr)
.find('td')
.toArray()
.map((cell) => {
// if this is an EUI table, filter down to the specific cell content
// otherwise this will include mobile-specific header information
const euiTableCellContent = $(cell).find('.euiTableCellContent');
if (euiTableCellContent.length > 0) {
return $(cell).find('.euiTableCellContent').text().trim();
} else {
return $(cell).text().trim();
}
});
});
}
/**
* Returns table headers
*/
public async getTableHeaders(): Promise<string[]> {
log.debug('Inspector.getTableHeaders');
// TODO: we should use datat-test-subj=inspectorTable as soon as EUI supports it
const dataTableHeader = await retry.try(async () => {
const inspectorPanel = await testSubjects.find('inspectorPanel');
return await inspectorPanel.findByTagName('thead');
});
const $ = await dataTableHeader.parseDomContent();
return $('th span.euiTableCellContent__text')
.toArray()
.map((cell) => $(cell).text().trim());
}
/**
* Asserts table headers
* @param expected expected headers
*/
public async expectTableHeaders(expected: string[]): Promise<void> {
await retry.try(async () => {
const headers = await this.getTableHeaders();
expect(headers).to.eql(expected);
});
}
/**
* Filters table for value by clicking specified cell
* @param column column index
* @param row row index
*/
public async filterForTableCell(column: string | number, row: string | number): Promise<void> {
await retry.try(async () => {
const table = await testSubjects.find('inspectorTable');
const cell = await table.findByCssSelector(
`tbody tr:nth-child(${row}) td:nth-child(${column})`
);
await cell.moveMouseTo();
const filterBtn = await testSubjects.findDescendant('filterForInspectorCellValue', cell);
await filterBtn.click();
});
await renderable.waitForRender();
}
/**
* Filters out table by clicking specified cell
* @param column column index
* @param row row index
*/
public async filterOutTableCell(column: string | number, row: string | number): Promise<void> {
await retry.try(async () => {
const table = await testSubjects.find('inspectorTable');
const cell = await table.findByCssSelector(
`tbody tr:nth-child(${row}) td:nth-child(${column})`
);
await cell.moveMouseTo();
const filterBtn = await testSubjects.findDescendant('filterOutInspectorCellValue', cell);
await filterBtn.click();
});
await renderable.waitForRender();
}
/**
* Opens inspector view
* @param viewId
*/
public async openInspectorView(viewId: string): Promise<void> {
log.debug(`Open Inspector view ${viewId}`);
await testSubjects.click('inspectorViewChooser');
await testSubjects.click(viewId);
}
/**
* Opens inspector requests view
*/
public async openInspectorRequestsView(): Promise<void> {
await this.openInspectorView('inspectorViewChooserRequests');
}
/**
* Returns request name as the comma-separated string
*/
public async getRequestNames(): Promise<string> {
await this.openInspectorRequestsView();
const requestChooserExists = await testSubjects.exists('inspectorRequestChooser');
if (requestChooserExists) {
await testSubjects.click('inspectorRequestChooser');
const menu = await testSubjects.find('inspectorRequestChooserMenuPanel');
const requestNames = await menu.getVisibleText();
return requestNames.trim().split('\n').join(',');
}
const singleRequest = await testSubjects.find('inspectorRequestName');
return await singleRequest.getVisibleText();
}
public getOpenRequestStatisticButton() {
return testSubjects.find('inspectorRequestDetailStatistics');
}
public getOpenRequestDetailRequestButton() {
return testSubjects.find('inspectorRequestDetailRequest');
}
public getOpenRequestDetailResponseButton() {
return testSubjects.find('inspectorRequestDetailResponse');
}
}
return new Inspector();
/**
* Closes inspector panel
*/
public async close(): Promise<void> {
this.log.debug('Close Inspector');
let isOpen = await this.testSubjects.exists('inspectorPanel');
if (isOpen) {
await this.retry.try(async () => {
await this.flyout.close('inspectorPanel');
isOpen = await this.testSubjects.exists('inspectorPanel');
if (isOpen) {
throw new Error('Failed to close inspector');
}
});
}
}
/**
* Asserts data on inspector panel
* @param expectedData
*/
public async expectTableData(expectedData: string[][]): Promise<void> {
this.log.debug(`Inspector.expectTableData(${expectedData.join(',')})`);
const data = await this.getTableData();
expect(data).to.eql(expectedData);
}
/**
* Sets table page size
* @param size rows count
*/
public async setTablePageSize(size: number): Promise<void> {
const panel = await this.testSubjects.find('inspectorPanel');
await this.find.clickByButtonText('Rows per page: 20', panel);
// The buttons for setting table page size are in a popover element. This popover
// element appears as if it's part of the inspectorPanel but it's really attached
// to the body element by a portal.
const tableSizesPopover = await this.find.byCssSelector('.euiPanel .euiContextMenuPanel');
await this.find.clickByButtonText(`${size} rows`, tableSizesPopover);
}
/**
* Returns table data in nested array format
*/
public async getTableData(): Promise<string[][]> {
// TODO: we should use datat-test-subj=inspectorTable as soon as EUI supports it
const inspectorPanel = await this.testSubjects.find('inspectorPanel');
const tableBody = await this.retry.try(async () => inspectorPanel.findByTagName('tbody'));
const $ = await tableBody.parseDomContent();
return $('tr')
.toArray()
.map((tr) => {
return $(tr)
.find('td')
.toArray()
.map((cell) => {
// if this is an EUI table, filter down to the specific cell content
// otherwise this will include mobile-specific header information
const euiTableCellContent = $(cell).find('.euiTableCellContent');
if (euiTableCellContent.length > 0) {
return $(cell).find('.euiTableCellContent').text().trim();
} else {
return $(cell).text().trim();
}
});
});
}
/**
* Returns table headers
*/
public async getTableHeaders(): Promise<string[]> {
this.log.debug('Inspector.getTableHeaders');
// TODO: we should use datat-test-subj=inspectorTable as soon as EUI supports it
const dataTableHeader = await this.retry.try(async () => {
const inspectorPanel = await this.testSubjects.find('inspectorPanel');
return await inspectorPanel.findByTagName('thead');
});
const $ = await dataTableHeader.parseDomContent();
return $('th span.euiTableCellContent__text')
.toArray()
.map((cell) => $(cell).text().trim());
}
/**
* Asserts table headers
* @param expected expected headers
*/
public async expectTableHeaders(expected: string[]): Promise<void> {
await this.retry.try(async () => {
const headers = await this.getTableHeaders();
expect(headers).to.eql(expected);
});
}
/**
* Filters table for value by clicking specified cell
* @param column column index
* @param row row index
*/
public async filterForTableCell(column: string | number, row: string | number): Promise<void> {
await this.retry.try(async () => {
const table = await this.testSubjects.find('inspectorTable');
const cell = await table.findByCssSelector(
`tbody tr:nth-child(${row}) td:nth-child(${column})`
);
await cell.moveMouseTo();
const filterBtn = await this.testSubjects.findDescendant('filterForInspectorCellValue', cell);
await filterBtn.click();
});
await this.renderable.waitForRender();
}
/**
* Filters out table by clicking specified cell
* @param column column index
* @param row row index
*/
public async filterOutTableCell(column: string | number, row: string | number): Promise<void> {
await this.retry.try(async () => {
const table = await this.testSubjects.find('inspectorTable');
const cell = await table.findByCssSelector(
`tbody tr:nth-child(${row}) td:nth-child(${column})`
);
await cell.moveMouseTo();
const filterBtn = await this.testSubjects.findDescendant('filterOutInspectorCellValue', cell);
await filterBtn.click();
});
await this.renderable.waitForRender();
}
/**
* Opens inspector view
* @param viewId
*/
public async openInspectorView(viewId: string): Promise<void> {
this.log.debug(`Open Inspector view ${viewId}`);
await this.testSubjects.click('inspectorViewChooser');
await this.testSubjects.click(viewId);
}
/**
* Opens inspector requests view
*/
public async openInspectorRequestsView(): Promise<void> {
await this.openInspectorView('inspectorViewChooserRequests');
}
/**
* Returns request name as the comma-separated string
*/
public async getRequestNames(): Promise<string> {
await this.openInspectorRequestsView();
const requestChooserExists = await this.testSubjects.exists('inspectorRequestChooser');
if (requestChooserExists) {
await this.testSubjects.click('inspectorRequestChooser');
const menu = await this.testSubjects.find('inspectorRequestChooserMenuPanel');
const requestNames = await menu.getVisibleText();
return requestNames.trim().split('\n').join(',');
}
const singleRequest = await this.testSubjects.find('inspectorRequestName');
return await singleRequest.getVisibleText();
}
public getOpenRequestStatisticButton() {
return this.testSubjects.find('inspectorRequestDetailStatistics');
}
public getOpenRequestDetailRequestButton() {
return this.testSubjects.find('inspectorRequestDetailRequest');
}
public getOpenRequestDetailResponseButton() {
return this.testSubjects.find('inspectorRequestDetailResponse');
}
}