Functional tests: convert more test/services to TS (#45176) (#45386)

* convert more test/services to TS

* Update test/functional/services/combo_box.ts

Co-Authored-By: Tre' <wayne.seymour@elastic.co>

* Update test/functional/services/combo_box.ts

Co-Authored-By: Tre' <wayne.seymour@elastic.co>

* Update test/functional/services/combo_box.ts

Co-Authored-By: Tre' <wayne.seymour@elastic.co>

* fix lint error
This commit is contained in:
Dmitry Lemeshko 2019-09-11 17:47:26 +02:00 committed by GitHub
parent fd1b0fc657
commit cb681edb4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 349 additions and 179 deletions

View file

@ -124,7 +124,7 @@ export default function ({ getService, getPageObjects }) {
];
await inspector.open();
await await inspector.setTablePageSize('50');
await await inspector.setTablePageSize(50);
await inspector.expectTableData(expectedTableData);
});

View file

@ -35,25 +35,32 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
// wrapper around EuiComboBox interactions
class ComboBox {
/**
* set value inside combobox
* Finds combobox element and sets specified value
*
* @param comboBoxSelector test subject selector
* @param value
* @param comboBoxSelector data-test-subj selector
* @param value option text
*/
public async set(comboBoxSelector: string, value: string): Promise<void> {
log.debug(`comboBox.set, comboBoxSelector: ${comboBoxSelector}`);
const comboBox = await testSubjects.find(comboBoxSelector);
await this.setElement(comboBox, value);
}
private async clickOption(isMouseClick: boolean, element: WebElementWrapper) {
/**
* Clicks option in combobox dropdown
*
* @param isMouseClick if 'true', click will be done with mouse
* @param element element that wraps up option
*/
private async clickOption(isMouseClick: boolean, element: WebElementWrapper): Promise<void> {
return isMouseClick ? await element.clickMouseButton() : await element.click();
}
/**
* set value inside combobox element
* Sets value for specified combobox element
*
* @param comboBoxElement
* @param comboBoxElement element that wraps up EuiComboBox
* @param value
*/
public async setElement(
@ -69,7 +76,7 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
}
comboBoxElement.scrollIntoViewIfNecessary();
await this._filterOptionsList(comboBoxElement, value);
await this.setFilterValue(comboBoxElement, value);
await this.openOptionsList(comboBoxElement);
if (value !== undefined) {
@ -93,30 +100,42 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
}
/**
* This method set custom value to comboBox.
* Finds combobox element and sets custom value
* It applies changes by pressing Enter key. Sometimes it may lead to auto-submitting a form.
*
* @param comboBoxSelector test subject selector
* @param value
* @param comboBoxSelector data-test-subj selector
* @param value option text
*/
async setCustom(comboBoxSelector: string, value: string) {
public async setCustom(comboBoxSelector: string, value: string): Promise<void> {
log.debug(`comboBox.setCustom, comboBoxSelector: ${comboBoxSelector}, value: ${value}`);
const comboBoxElement = await testSubjects.find(comboBoxSelector);
await this._filterOptionsList(comboBoxElement, value);
await this.setFilterValue(comboBoxElement, value);
await PageObjects.common.pressEnterKey();
await this.closeOptionsList(comboBoxElement);
}
async filterOptionsList(comboBoxSelector: string, filterValue: string) {
/**
* Finds combobox element and sets filter value
*
* @param comboBoxSelector data-test-subj selector
* @param filterValue text
*/
public async filterOptionsList(comboBoxSelector: string, filterValue: string): Promise<void> {
log.debug(
`comboBox.filterOptionsList, comboBoxSelector: ${comboBoxSelector}, filter: ${filterValue}`
);
const comboBox = await testSubjects.find(comboBoxSelector);
await this._filterOptionsList(comboBox, filterValue);
await this.setFilterValue(comboBox, filterValue);
await this.closeOptionsList(comboBox);
}
private async _filterOptionsList(
/**
* Sets new filter value in specified combobox element
*
* @param comboBoxElement element that wraps up EuiComboBox
* @param filterValue text
*/
private async setFilterValue(
comboBoxElement: WebElementWrapper,
filterValue: string
): Promise<void> {
@ -127,10 +146,20 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
await this.waitForOptionsListLoading(comboBoxElement);
}
/**
* Waits options list to be loaded
*
* @param comboBoxElement element that wraps up EuiComboBox
*/
private async waitForOptionsListLoading(comboBoxElement: WebElementWrapper): Promise<void> {
await comboBoxElement.waitForDeletedByCssSelector('.euiLoadingSpinner');
}
/**
* Returns options list as a single string
*
* @param comboBoxSelector data-test-subj selector
*/
public async getOptionsList(comboBoxSelector: string): Promise<string> {
log.debug(`comboBox.getOptionsList, comboBoxSelector: ${comboBoxSelector}`);
const comboBox = await testSubjects.find(comboBoxSelector);
@ -148,37 +177,33 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
return optionsText;
}
/**
* Finds combobox element and checks if it has selected options
*
* @param comboBoxSelector data-test-subj selector
*/
public async doesComboBoxHaveSelectedOptions(comboBoxSelector: string): Promise<boolean> {
log.debug(`comboBox.doesComboBoxHaveSelectedOptions, comboBoxSelector: ${comboBoxSelector}`);
const comboBox = await testSubjects.find(comboBoxSelector);
const selectedOptions = await comboBox.findAllByClassName(
'euiComboBoxPill',
WAIT_FOR_EXISTS_TIME
);
return selectedOptions.length > 0;
}
public async getComboBoxSelectedOptions(comboBoxSelector: string): Promise<string[]> {
log.debug(`comboBox.getComboBoxSelectedOptions, comboBoxSelector: ${comboBoxSelector}`);
return await retry.try(async () => {
const comboBox = await testSubjects.find(comboBoxSelector);
const selectedOptions = await comboBox.findAllByClassName(
'euiComboBoxPill',
WAIT_FOR_EXISTS_TIME
);
if (selectedOptions.length === 0) {
return [];
}
return Promise.all(
selectedOptions.map(async optionElement => {
return await optionElement.getVisibleText();
})
);
});
const $ = await comboBox.parseDomContent();
return $('.euiComboBoxPill').toArray().length > 0;
}
/**
* clearing value from combobox
* Returns selected options
* @param comboBoxSelector data-test-subj selector
*/
public async getComboBoxSelectedOptions(comboBoxSelector: string): Promise<string[]> {
log.debug(`comboBox.getComboBoxSelectedOptions, comboBoxSelector: ${comboBoxSelector}`);
const comboBox = await testSubjects.find(comboBoxSelector);
const $ = await comboBox.parseDomContent();
return $('.euiComboBoxPill')
.toArray()
.map(option => $(option).text());
}
/**
* Finds combobox element and clears value in the input field by clicking clear button
*
* @param comboBoxSelector data-test-subj selector
*/
@ -212,9 +237,9 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
}
/**
* closing option list for combobox
* Closes options list
*
* @param comboBoxElement
* @param comboBoxElement element that wraps up EuiComboBox
*/
public async closeOptionsList(comboBoxElement: WebElementWrapper): Promise<void> {
const isOptionsListOpen = await testSubjects.exists('comboBoxOptionsList');
@ -225,9 +250,9 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
}
/**
* opened list of options for combobox
* Opens options list
*
* @param comboBoxElement
* @param comboBoxElement element that wraps up EuiComboBox
*/
public async openOptionsList(comboBoxElement: WebElementWrapper): Promise<void> {
const isOptionsListOpen = await testSubjects.exists('comboBoxOptionsList');
@ -240,10 +265,10 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
}
/**
* check if option is already selected
* Checks if specified option is already selected
*
* @param comboBoxElement
* @param value
* @param comboBoxElement element that wraps up EuiComboBox
* @param value option text
*/
public async isOptionSelected(
comboBoxElement: WebElementWrapper,

View file

@ -17,20 +17,23 @@
* under the License.
*/
export function EmbeddingProvider({ getService, getPageObjects }) {
import { FtrProviderContext } from '../ftr_provider_context';
export function EmbeddingProvider({ getService, getPageObjects }: FtrProviderContext) {
const browser = getService('browser');
const log = getService('log');
const PageObjects = getPageObjects(['header']);
class Embedding {
async openInEmbeddedMode() {
/**
* Opens current page in embeded mode
*/
public async openInEmbeddedMode(): Promise<void> {
const currentUrl = await browser.getCurrentUrl();
log.debug(`Opening in embedded mode: ${currentUrl}`);
await browser.get(`${currentUrl}&embed=true`);
await PageObjects.header.waitUntilLoadingHasFinished();
}
}
return new Embedding();

View file

@ -17,48 +17,70 @@
* under the License.
*/
export function FilterBarProvider({ getService, getPageObjects }) {
const testSubjects = getService('testSubjects');
import { FtrProviderContext } from '../ftr_provider_context';
export function FilterBarProvider({ getService, getPageObjects }: FtrProviderContext) {
const comboBox = getService('comboBox');
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['common', 'header']);
class FilterBar {
hasFilter(key, value, enabled = true) {
/**
* Checks if specified filter exists
*
* @param key field name
* @param value filter value
* @param enabled filter status
*/
public async hasFilter(key: string, value: string, enabled: boolean = true): Promise<boolean> {
const filterActivationState = enabled ? 'enabled' : 'disabled';
return testSubjects.exists(
return await testSubjects.exists(
`filter & filter-key-${key} & filter-value-${value} & filter-${filterActivationState}`,
{
allowHidden: true
allowHidden: true,
}
);
}
async removeFilter(key) {
/**
* Removes specified filter
*
* @param key field name
*/
public async removeFilter(key: string): Promise<void> {
await testSubjects.click(`filter & filter-key-${key}`);
await testSubjects.click(`deleteFilter`);
await PageObjects.header.awaitGlobalLoadingIndicatorHidden();
}
async removeAllFilters() {
/**
* Removes all filters
*/
public async removeAllFilters(): Promise<void> {
await testSubjects.click('showFilterActions');
await testSubjects.click('removeAllFilters');
await PageObjects.header.waitUntilLoadingHasFinished();
await PageObjects.common.waitUntilUrlIncludes('filters:!()');
}
async toggleFilterEnabled(key) {
/**
* Changes filter active status
*
* @param key field name
*/
public async toggleFilterEnabled(key: string): Promise<void> {
await testSubjects.click(`filter & filter-key-${key}`);
await testSubjects.click(`disableFilter`);
await PageObjects.header.awaitGlobalLoadingIndicatorHidden();
}
async toggleFilterPinned(key) {
public async toggleFilterPinned(key: string): Promise<void> {
await testSubjects.click(`filter & filter-key-${key}`);
await testSubjects.click(`pinFilter`);
await PageObjects.header.awaitGlobalLoadingIndicatorHidden();
}
async getFilterCount() {
public async getFilterCount(): Promise<number> {
const filters = await testSubjects.findAll('filter');
return filters.length;
}
@ -81,12 +103,14 @@ export function FilterBarProvider({ getService, getPageObjects }) {
* // Add a filter containing multiple values
* filterBar.addFilter('extension', 'is one of', ['jpg', 'png']);
*/
async addFilter(field, operator, ...values) {
public async addFilter(field: string, operator: string, ...values: any): Promise<void> {
await testSubjects.click('addFilter');
await comboBox.set('filterFieldSuggestionList', field);
await comboBox.set('filterOperatorList', operator);
const params = await testSubjects.find('filterParams');
const paramsComboBoxes = await params.findAllByCssSelector('[data-test-subj~="filterParamsComboBox"]');
const paramsComboBoxes = await params.findAllByCssSelector(
'[data-test-subj~="filterParamsComboBox"]'
);
const paramFields = await params.findAllByTagName('input');
for (let i = 0; i < values.length; i++) {
let fieldValues = values[i];
@ -98,8 +122,7 @@ export function FilterBarProvider({ getService, getPageObjects }) {
for (let j = 0; j < fieldValues.length; j++) {
await comboBox.setElement(paramsComboBoxes[i], fieldValues[j]);
}
}
else if (paramFields && paramFields.length > 0) {
} else if (paramFields && paramFields.length > 0) {
for (let j = 0; j < fieldValues.length; j++) {
await paramFields[i].type(fieldValues[j]);
}
@ -109,36 +132,60 @@ export function FilterBarProvider({ getService, getPageObjects }) {
await PageObjects.header.awaitGlobalLoadingIndicatorHidden();
}
async clickEditFilter(key, value) {
/**
* Activates filter editing
* @param key field name
* @param value field value
*/
public async clickEditFilter(key: string, value: string): Promise<void> {
await testSubjects.click(`filter & filter-key-${key} & filter-value-${value}`);
await testSubjects.click(`editFilter`);
await PageObjects.header.awaitGlobalLoadingIndicatorHidden();
}
async getFilterEditorSelectedPhrases() {
/**
* Returns available phrases in the filter
*/
public async getFilterEditorSelectedPhrases(): Promise<string[]> {
return await comboBox.getComboBoxSelectedOptions('filterParamsComboBox');
}
async getFilterEditorFields() {
/**
* Returns available fields in the filter
*/
public async getFilterEditorFields(): Promise<string[]> {
const optionsString = await comboBox.getOptionsList('filterFieldSuggestionList');
return optionsString.split('\n');
}
async ensureFieldEditorModalIsClosed() {
/**
* Closes field editor modal window
*/
public async ensureFieldEditorModalIsClosed(): Promise<void> {
const cancelSaveFilterModalButtonExists = await testSubjects.exists('cancelSaveFilter');
if (cancelSaveFilterModalButtonExists) {
await testSubjects.click('cancelSaveFilter');
}
}
async getIndexPatterns() {
/**
* Returns comma-separated list of index patterns
*/
public async getIndexPatterns(): Promise<string> {
await testSubjects.click('addFilter');
const indexPatterns = await comboBox.getOptionsList('filterIndexPatternsSelect');
await this.ensureFieldEditorModalIsClosed();
return indexPatterns.trim().split('\n').join(',');
return indexPatterns
.trim()
.split('\n')
.join(',');
}
async selectIndexPattern(indexPatternTitle) {
/**
* Adds new index pattern filter
* @param indexPatternTitle
*/
public async selectIndexPattern(indexPatternTitle: string): Promise<void> {
await testSubjects.click('addFilter');
await comboBox.set('filterIndexPatternsSelect', indexPatternTitle);
}

View file

@ -364,7 +364,7 @@ export async function FindProvider({ getService }: FtrProviderContext) {
public async clickByButtonText(
buttonText: string,
element = driver,
element: WebDriver | WebElement | WebElementWrapper = driver,
timeout: number = defaultFindTimeout
): Promise<void> {
log.debug(`Find.clickByButtonText('${buttonText}') with timeout=${timeout}`);

View file

@ -17,42 +17,47 @@
* under the License.
*/
export function FlyoutProvider({ getService }) {
import { FtrProviderContext } 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');
class Flyout {
async close(testSubj) {
log.debug('Closing flyout', testSubj);
const flyoutElement = await testSubjects.find(testSubj);
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(testSubj));
await retry.waitFor('flyout closed', async () => !(await testSubjects.exists(dataTestSubj)));
}
async ensureClosed(testSubj) {
if (await testSubjects.exists(testSubj)) {
await this.close(testSubj);
public async ensureClosed(dataTestSubj: string): Promise<void> {
if (await testSubjects.exists(dataTestSubj)) {
await this.close(dataTestSubj);
}
}
async ensureAllClosed() {
public async ensureAllClosed(): Promise<void> {
const flyoutElements = await find.allByCssSelector('.euiFlyout');
if (!flyoutElements.length) {
return;
}
await Promise.all(flyoutElements.map(async (flyoutElement) => {
const closeBtn = await flyoutElement.findByCssSelector('[aria-label*="Close"]');
await closeBtn.click();
}));
await Promise.all(
flyoutElements.map(async flyoutElement => {
const closeBtn = await flyoutElement.findByCssSelector('[aria-label*="Close"]');
await closeBtn.click();
})
);
await retry.waitFor('all flyouts to be closed', async () => (
(await find.allByCssSelector('.euiFlyout')).length === 0
));
await retry.waitFor(
'all flyouts to be closed',
async () => (await find.allByCssSelector('.euiFlyout')).length === 0
);
}
}

View file

@ -18,39 +18,42 @@
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
export function GlobalNavProvider({ getService }) {
export function GlobalNavProvider({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
return new class GlobalNav {
async moveMouseToLogo() {
class GlobalNav {
public async moveMouseToLogo(): Promise<void> {
await testSubjects.moveMouseTo('headerGlobalNav logo');
}
async clickLogo() {
public async clickLogo(): Promise<void> {
return await testSubjects.click('headerGlobalNav logo');
}
async exists() {
public async exists(): Promise<boolean> {
return await testSubjects.exists('headerGlobalNav');
}
async getFirstBreadcrumb() {
public async getFirstBreadcrumb(): Promise<string> {
return await testSubjects.getVisibleText('headerGlobalNav breadcrumbs first&breadcrumb');
}
async getLastBreadcrumb() {
public async getLastBreadcrumb(): Promise<string> {
return await testSubjects.getVisibleText('headerGlobalNav breadcrumbs last&breadcrumb');
}
async badgeExistsOrFail(expectedLabel) {
public async badgeExistsOrFail(expectedLabel: string): Promise<void> {
await testSubjects.existOrFail('headerBadge');
const actualLabel = await testSubjects.getAttribute('headerBadge', 'data-test-badge-label');
expect(actualLabel.toUpperCase()).to.equal(expectedLabel.toUpperCase());
}
async badgeMissingOrFail() {
public async badgeMissingOrFail(): Promise<void> {
await testSubjects.missingOrFail('headerBadge');
}
};
}
return new GlobalNav();
}

View file

@ -29,36 +29,26 @@ import {
DashboardVisualizationProvider,
// @ts-ignore not TS yet
} from './dashboard';
// @ts-ignore not TS yet
import { DocTableProvider } from './doc_table';
// @ts-ignore not TS yet
import { EmbeddingProvider } from './embedding';
// @ts-ignore not TS yet
import { FailureDebuggingProvider } from './failure_debugging';
// @ts-ignore not TS yet
import { FilterBarProvider } from './filter_bar';
import { FindProvider } from './find';
// @ts-ignore not TS yet
import { FlyoutProvider } from './flyout';
// @ts-ignore not TS yet
import { GlobalNavProvider } from './global_nav';
// @ts-ignore not TS yet
import { InspectorProvider } from './inspector';
// @ts-ignore not TS yet
import { QueryBarProvider } from './query_bar';
import { RemoteProvider } from './remote';
// @ts-ignore not TS yet
import { RenderableProvider } from './renderable';
import { ScreenshotsProvider } from './screenshots';
// @ts-ignore not TS yet
import { SnapshotsProvider } from './snapshots';
// @ts-ignore not TS yet
import { TableProvider } from './table';
import { TestSubjectsProvider } from './test_subjects';
import { ToastsProvider } from './toasts';
// @ts-ignore not TS yet
import { PieChartProvider } from './visualizations';
// @ts-ignore not TS yet
import { VisualizeListingTableProvider } from './visualize_listing_table';
// @ts-ignore not TS yet
import { SavedQueryManagementComponentProvider } from './saved_query_management_component';

View file

@ -18,8 +18,9 @@
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
export function InspectorProvider({ getService }) {
export function InspectorProvider({ getService }: FtrProviderContext) {
const log = getService('log');
const retry = getService('retry');
const renderable = getService('renderable');
@ -27,27 +28,36 @@ export function InspectorProvider({ getService }) {
const testSubjects = getService('testSubjects');
const find = getService('find');
return new class Inspector {
async getIsEnabled() {
class Inspector {
private async getIsEnabled(): Promise<boolean> {
const ariaDisabled = await testSubjects.getAttribute('openInspectorButton', 'disabled');
return ariaDisabled !== 'true';
}
async expectIsEnabled() {
/**
* Asserts that inspector is enabled
*/
public async expectIsEnabled(): Promise<void> {
await retry.try(async () => {
const isEnabled = await this.getIsEnabled();
expect(isEnabled).to.be(true);
});
}
async expectIsNotEnabled() {
/**
* Asserts that inspector is disabled
*/
public async expectIsNotEnabled(): Promise<void> {
await retry.try(async () => {
const isEnabled = await this.getIsEnabled();
expect(isEnabled).to.be(false);
});
}
async open() {
/**
* Opens inspector panel
*/
public async open(): Promise<void> {
log.debug('Inspector.open');
const isOpen = await testSubjects.exists('inspectorPanel');
if (!isOpen) {
@ -58,7 +68,10 @@ export function InspectorProvider({ getService }) {
}
}
async close() {
/**
* Closes inspector panel
*/
public async close(): Promise<void> {
log.debug('Close Inspector');
let isOpen = await testSubjects.exists('inspectorPanel');
if (isOpen) {
@ -72,13 +85,21 @@ export function InspectorProvider({ getService }) {
}
}
async expectTableData(expectedData) {
/**
* Asserts data on inspector panel
* @param expectedData
*/
public async expectTableData(expectedData: string[][]): Promise<void> {
await log.debug(`Inspector.expectTableData(${expectedData.join(',')})`);
const data = await this.getTableData();
expect(data).to.eql(expectedData);
}
async setTablePageSize(size) {
/**
* 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
@ -88,27 +109,43 @@ export function InspectorProvider({ getService }) {
await find.clickByButtonText(`${size} rows`, tableSizesPopover);
}
async getTableData() {
/**
* 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');
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();
}
if (euiTableCellContent.length > 0) {
return $(cell)
.find('.euiTableCellContent')
.text()
.trim();
} else {
return $(cell)
.text()
.trim();
}
});
});
});
}
async getTableHeaders() {
/**
* 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 () => {
@ -116,21 +153,37 @@ export function InspectorProvider({ getService }) {
return await inspectorPanel.findByTagName('thead');
});
const $ = await dataTableHeader.parseDomContent();
return $('th span.euiTableCellContent__text').toArray()
.map(cell => $(cell).text().trim());
return $('th span.euiTableCellContent__text')
.toArray()
.map(cell =>
$(cell)
.text()
.trim()
);
}
async expectTableHeaders(expected) {
/**
* 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);
});
}
async filterForTableCell(column, row) {
/**
* Filters table for value by clicking specified cell
* @param column column index
* @param row row index
*/
public async filterForTableCell(column: string, row: string): 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})`);
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();
@ -138,10 +191,17 @@ export function InspectorProvider({ getService }) {
await renderable.waitForRender();
}
async filterOutTableCell(column, row) {
/**
* Filters out table by clicking specified cell
* @param column column index
* @param row row index
*/
public async filterOutTableCell(column: string, row: string): 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})`);
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();
@ -149,28 +209,43 @@ export function InspectorProvider({ getService }) {
await renderable.waitForRender();
}
async openInspectorView(viewId) {
/**
* 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);
}
async openInspectorRequestsView() {
/**
* Opens inspector requests view
*/
public async openInspectorRequestsView(): Promise<void> {
await this.openInspectorView('inspectorViewChooserRequests');
}
async getRequestNames() {
/**
* 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(',');
return requestNames
.trim()
.split('\n')
.join(',');
}
const singleRequest = await testSubjects.find('inspectorRequestName');
return await singleRequest.getVisibleText();
}
};
}
return new Inspector();
}

View file

@ -17,7 +17,9 @@
* under the License.
*/
export function QueryBarProvider({ getService, getPageObjects }) {
import { FtrProviderContext } from '../ftr_provider_context';
export function QueryBarProvider({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const retry = getService('retry');
const log = getService('log');
@ -25,12 +27,11 @@ export function QueryBarProvider({ getService, getPageObjects }) {
const find = getService('find');
class QueryBar {
async getQueryString() {
async getQueryString(): Promise<string> {
return await testSubjects.getAttribute('queryInput', 'value');
}
async setQuery(query) {
public async setQuery(query: string): Promise<void> {
log.debug(`QueryBar.setQuery(${query})`);
// Extra caution used because of flaky test here: https://github.com/elastic/kibana/issues/16978 doesn't seem
// to be actually setting the query in the query input based off
@ -44,22 +45,23 @@ export function QueryBarProvider({ getService, getPageObjects }) {
await input.type(query);
const currentQuery = await this.getQueryString();
if (currentQuery !== query) {
throw new Error(`Failed to set query input to ${query}, instead query is ${currentQuery}`);
throw new Error(
`Failed to set query input to ${query}, instead query is ${currentQuery}`
);
}
});
}
async submitQuery() {
public async submitQuery(): Promise<void> {
log.debug('QueryBar.submitQuery');
await testSubjects.click('queryInput');
await PageObjects.common.pressEnterKey();
await PageObjects.header.waitUntilLoadingHasFinished();
}
async clickQuerySubmitButton() {
public async clickQuerySubmitButton(): Promise<void> {
await testSubjects.click('querySubmitButton');
}
}
return new QueryBar();

View file

@ -17,17 +17,18 @@
* under the License.
*/
import { FtrProviderContext } from '../ftr_provider_context';
const RENDER_COMPLETE_SELECTOR = '[data-render-complete="true"]';
const RENDER_COMPLETE_PENDING_SELECTOR = '[data-render-complete="false"]';
const DATA_LOADING_SELECTOR = '[data-loading]';
export function RenderableProvider({ getService }) {
export function RenderableProvider({ getService }: FtrProviderContext) {
const log = getService('log');
const retry = getService('retry');
const find = getService('find');
return new class Renderable {
class Renderable {
/**
* This method waits for a certain number of objects to finish rendering and loading, which is indicated
* by a couple tags. The RENDER_COMPLETE_SELECTOR indicates that it's done initially loading up. Some
@ -35,7 +36,7 @@ export function RenderableProvider({ getService }) {
* return if any of those tags are found.
* @param count {Number} Number of RENDER_COMPLETE_SELECTORs to wait for.
*/
async waitForRender(count = 1) {
public async waitForRender(count: number = 1): Promise<void> {
log.debug(`Renderable.waitForRender for ${count} elements`);
await retry.try(async () => {
const completedElements = await find.allByCssSelector(RENDER_COMPLETE_SELECTOR);
@ -46,8 +47,10 @@ export function RenderableProvider({ getService }) {
const title = await pendingElement.getAttribute('data-title');
pendingElementNames.push(title);
}
throw new Error(`${completedElements.length} elements completed rendering, still waiting on a total of ${count}
specifically:\n${pendingElementNames.join('\n')}`);
throw new Error(`${
completedElements.length
} elements completed rendering, still waiting on a total of ${count}
specifically:\n${pendingElementNames.join('\n')}`);
}
const stillLoadingElements = await find.allByCssSelector(DATA_LOADING_SELECTOR, 1000);
@ -56,5 +59,7 @@ export function RenderableProvider({ getService }) {
}
});
}
};
}
return new Renderable();
}

View file

@ -17,25 +17,36 @@
* under the License.
*/
export function TableProvider({ getService }) {
import { FtrProviderContext } from '../ftr_provider_context';
import { WebElementWrapper } from './lib/web_element_wrapper';
export function TableProvider({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
// const retry = getService('retry');
class Table {
/**
* Finds table and returns data in the nested array format
* @param dataTestSubj data-test-subj selector
*/
async getDataFromTestSubj(testSubj) {
const table = await testSubjects.find(testSubj);
public async getDataFromTestSubj(dataTestSubj: string): Promise<string[][]> {
const table = await testSubjects.find(dataTestSubj);
return await this.getDataFromElement(table);
}
async getDataFromElement(table) {
// Convert the data into a nested array format:
// [ [cell1_in_row1, cell2_in_row1], [cell1_in_row2, cell2_in_row2] ]
/**
* Converts the table data into nested array
* [ [cell1_in_row1, cell2_in_row1], [cell1_in_row2, cell2_in_row2] ]
* @param table
*/
public async getDataFromElement(table: WebElementWrapper): Promise<string[][]> {
const rows = await table.findAllByTagName('tr');
return await Promise.all(rows.map(async row => {
const cells = await row.findAllByTagName('td');
return await Promise.all(cells.map(async cell => await cell.getVisibleText()));
}));
return await Promise.all(
rows.map(async row => {
const cells = await row.findAllByTagName('td');
return await Promise.all(cells.map(async cell => await cell.getVisibleText()));
})
);
}
}

View file

@ -17,14 +17,16 @@
* under the License.
*/
export function VisualizeListingTableProvider({ getService, getPageObjects }) {
import { FtrProviderContext } from '../ftr_provider_context';
export function VisualizeListingTableProvider({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const find = getService('find');
const log = getService('log');
const PageObjects = getPageObjects(['dashboard', 'visualize', 'header', 'discover']);
const { header } = getPageObjects(['header']);
class VisualizeListingTable {
async getAllVisualizationNamesOnCurrentPage() {
public async getAllVisualizationNamesOnCurrentPage(): Promise<string[]> {
const visualizationNames = [];
const links = await find.allByCssSelector('.kuiLink');
for (let i = 0; i < links.length; i++) {
@ -34,16 +36,18 @@ export function VisualizeListingTableProvider({ getService, getPageObjects }) {
return visualizationNames;
}
async getAllVisualizationNames() {
public async getAllVisualizationNames(): Promise<string[]> {
log.debug('VisualizeListingTable.getAllVisualizationNames');
let morePages = true;
let visualizationNames = [];
let visualizationNames: string[] = [];
while (morePages) {
visualizationNames = visualizationNames.concat(await this.getAllVisualizationNamesOnCurrentPage());
morePages = !(await testSubjects.getAttribute('pagerNextButton', 'disabled') === 'true');
visualizationNames = visualizationNames.concat(
await this.getAllVisualizationNamesOnCurrentPage()
);
morePages = !((await testSubjects.getAttribute('pagerNextButton', 'disabled')) === 'true');
if (morePages) {
await testSubjects.click('pagerNextButton');
await PageObjects.header.waitUntilLoadingHasFinished();
await header.waitUntilLoadingHasFinished();
}
}
return visualizationNames;

View file

@ -83,7 +83,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
await PageObjects.visualize.waitForVisualizationRenderingStabilized();
await inspector.open();
await inspector.setTablePageSize('50');
await inspector.setTablePageSize(50);
await inspector.expectTableData(expectedData);
});
});