[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. * Side Public License, v 1.
*/ */
import { FtrProviderContext } from '../ftr_provider_context'; import { FtrService } from '../ftr_provider_context';
export function FlyoutProvider({ getService }: FtrProviderContext) { export class FlyoutService extends FtrService {
const testSubjects = getService('testSubjects'); private readonly testSubjects = this.ctx.getService('testSubjects');
const find = getService('find'); private readonly find = this.ctx.getService('find');
const log = getService('log'); private readonly log = this.ctx.getService('log');
const retry = getService('retry'); private readonly retry = this.ctx.getService('retry');
class Flyout { public async close(dataTestSubj: string): Promise<void> {
public async close(dataTestSubj: string): Promise<void> { this.log.debug('Closing flyout', dataTestSubj);
log.debug('Closing flyout', dataTestSubj); const flyoutElement = await this.testSubjects.find(dataTestSubj);
const flyoutElement = await testSubjects.find(dataTestSubj); const closeBtn = await flyoutElement.findByCssSelector('[aria-label*="Close"]');
const closeBtn = await flyoutElement.findByCssSelector('[aria-label*="Close"]'); await closeBtn.click();
await closeBtn.click(); await this.retry.waitFor(
await retry.waitFor( 'flyout closed',
'flyout closed', async () => !(await this.testSubjects.exists(dataTestSubj, { timeout: 1000 }))
async () => !(await testSubjects.exists(dataTestSubj, { timeout: 1000 })) );
); }
}
public async ensureClosed(dataTestSubj: string): Promise<void> { public async ensureClosed(dataTestSubj: string): Promise<void> {
if (await testSubjects.exists(dataTestSubj, { timeout: 1000 })) { if (await this.testSubjects.exists(dataTestSubj, { timeout: 1000 })) {
await this.close(dataTestSubj); 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
);
} }
} }
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 { DocTableService } from './doc_table';
import { EmbeddingProvider } from './embedding'; import { EmbeddingProvider } from './embedding';
import { FilterBarService } from './filter_bar'; import { FilterBarService } from './filter_bar';
import { FlyoutProvider } from './flyout'; import { FlyoutService } from './flyout';
import { GlobalNavService } from './global_nav'; import { GlobalNavService } from './global_nav';
import { InspectorProvider } from './inspector'; import { InspectorService } from './inspector';
import { FieldEditorService } from './field_editor'; import { FieldEditorService } from './field_editor';
import { ManagementMenuService } from './management'; import { ManagementMenuService } from './management';
import { QueryBarProvider } from './query_bar'; import { QueryBarProvider } from './query_bar';
@ -67,14 +67,14 @@ export const services = {
dashboardAddPanel: DashboardAddPanelService, dashboardAddPanel: DashboardAddPanelService,
dashboardReplacePanel: DashboardReplacePanelService, dashboardReplacePanel: DashboardReplacePanelService,
dashboardPanelActions: DashboardPanelActionsService, dashboardPanelActions: DashboardPanelActionsService,
flyout: FlyoutProvider, flyout: FlyoutService,
comboBox: ComboBoxProvider, comboBox: ComboBoxProvider,
dataGrid: DataGridService, dataGrid: DataGridService,
embedding: EmbeddingProvider, embedding: EmbeddingProvider,
renderable: RenderableProvider, renderable: RenderableProvider,
browser: BrowserProvider, browser: BrowserProvider,
pieChart: PieChartService, pieChart: PieChartService,
inspector: InspectorProvider, inspector: InspectorService,
fieldEditor: FieldEditorService, fieldEditor: FieldEditorService,
vegaDebugInspector: VegaDebugInspectorViewService, vegaDebugInspector: VegaDebugInspectorViewService,
appsMenu: AppsMenuProvider, appsMenu: AppsMenuProvider,

View file

@ -7,234 +7,230 @@
*/ */
import expect from '@kbn/expect'; import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context'; import { FtrService } from '../ftr_provider_context';
export function InspectorProvider({ getService }: FtrProviderContext) { export class InspectorService extends FtrService {
const log = getService('log'); private readonly log = this.ctx.getService('log');
const retry = getService('retry'); private readonly retry = this.ctx.getService('retry');
const renderable = getService('renderable'); private readonly renderable = this.ctx.getService('renderable');
const flyout = getService('flyout'); private readonly flyout = this.ctx.getService('flyout');
const testSubjects = getService('testSubjects'); private readonly testSubjects = this.ctx.getService('testSubjects');
const find = getService('find'); private readonly find = this.ctx.getService('find');
class Inspector { private async getIsEnabled(): Promise<boolean> {
private async getIsEnabled(): Promise<boolean> { const ariaDisabled = await this.testSubjects.getAttribute('openInspectorButton', 'disabled');
const ariaDisabled = await testSubjects.getAttribute('openInspectorButton', 'disabled'); return ariaDisabled !== 'true';
return ariaDisabled !== 'true'; }
}
/** /**
* Asserts that inspector is enabled * Asserts that inspector is enabled
*/ */
public async expectIsEnabled(): Promise<void> { public async expectIsEnabled(): Promise<void> {
await retry.try(async () => { await this.retry.try(async () => {
const isEnabled = await this.getIsEnabled(); const isEnabled = await this.getIsEnabled();
expect(isEnabled).to.be(true); 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');
}
} }