mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[ftr] migrate "flyout" and "inspector" services to FtrService class (#100602)
Co-authored-by: spalger <spalger@users.noreply.github.com>
This commit is contained in:
parent
881d89fba7
commit
af59f68e8b
3 changed files with 259 additions and 267 deletions
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue