mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
* 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:
parent
fd1b0fc657
commit
cb681edb4c
14 changed files with 349 additions and 179 deletions
|
@ -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);
|
||||
});
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
|
@ -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);
|
||||
}
|
|
@ -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}`);
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
|
@ -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();
|
||||
}
|
|
@ -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()));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue