[ftr/menuToggle] provide helper for enhanced menu toggle handling (#81709)

Co-authored-by: spalger <spalger@users.noreply.github.com>
This commit is contained in:
Spencer 2020-10-27 09:09:41 -07:00 committed by GitHub
parent 5dfa45d666
commit 441890ccb3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 140 additions and 76 deletions

View file

@ -35,12 +35,18 @@ export type CommonlyUsed =
export function TimePickerProvider({ getService, getPageObjects }: FtrProviderContext) {
const log = getService('log');
const retry = getService('retry');
const find = getService('find');
const browser = getService('browser');
const testSubjects = getService('testSubjects');
const { header } = getPageObjects(['header']);
const kibanaServer = getService('kibanaServer');
const MenuToggle = getService('MenuToggle');
const quickSelectTimeMenuToggle = new MenuToggle({
name: 'QuickSelectTime Menu',
menuTestSubject: 'superDatePickerQuickMenu',
toggleButtonTestSubject: 'superDatePickerToggleQuickMenuButton',
});
class TimePicker {
defaultStartTime = 'Sep 19, 2015 @ 06:31:44.000';
@ -158,34 +164,8 @@ export function TimePickerProvider({ getService, getPageObjects }: FtrProviderCo
return await find.existsByCssSelector('.euiDatePickerRange--readOnly');
}
public async isQuickSelectMenuOpen() {
return await testSubjects.exists('superDatePickerQuickMenu');
}
public async openQuickSelectTimeMenu() {
log.debug('openQuickSelectTimeMenu');
const isMenuOpen = await this.isQuickSelectMenuOpen();
if (!isMenuOpen) {
log.debug('opening quick select menu');
await retry.try(async () => {
await testSubjects.click('superDatePickerToggleQuickMenuButton');
});
}
}
public async closeQuickSelectTimeMenu() {
log.debug('closeQuickSelectTimeMenu');
const isMenuOpen = await this.isQuickSelectMenuOpen();
if (isMenuOpen) {
log.debug('closing quick select menu');
await retry.try(async () => {
await testSubjects.click('superDatePickerToggleQuickMenuButton');
});
}
}
public async getRefreshConfig(keepQuickSelectOpen = false) {
await this.openQuickSelectTimeMenu();
await quickSelectTimeMenuToggle.open();
const interval = await testSubjects.getAttribute(
'superDatePickerRefreshIntervalInput',
'value'
@ -207,7 +187,7 @@ export function TimePickerProvider({ getService, getPageObjects }: FtrProviderCo
'superDatePickerToggleRefreshButton'
);
if (!keepQuickSelectOpen) {
await this.closeQuickSelectTimeMenu();
await quickSelectTimeMenuToggle.close();
}
return {
@ -270,26 +250,26 @@ export function TimePickerProvider({ getService, getPageObjects }: FtrProviderCo
}
public async startAutoRefresh(intervalS = 3) {
await this.openQuickSelectTimeMenu();
await quickSelectTimeMenuToggle.open();
await this.inputValue('superDatePickerRefreshIntervalInput', intervalS.toString());
const refreshConfig = await this.getRefreshConfig(true);
if (refreshConfig.isPaused) {
log.debug('start auto refresh');
await testSubjects.click('superDatePickerToggleRefreshButton');
}
await this.closeQuickSelectTimeMenu();
await quickSelectTimeMenuToggle.close();
}
public async pauseAutoRefresh() {
log.debug('pauseAutoRefresh');
const refreshConfig = await this.getRefreshConfig(true);
if (!refreshConfig.isPaused) {
log.debug('pause auto refresh');
await testSubjects.click('superDatePickerToggleRefreshButton');
await this.closeQuickSelectTimeMenu();
}
await this.closeQuickSelectTimeMenu();
await quickSelectTimeMenuToggle.close();
}
public async resumeAutoRefresh() {
@ -300,7 +280,7 @@ export function TimePickerProvider({ getService, getPageObjects }: FtrProviderCo
await testSubjects.click('superDatePickerToggleRefreshButton');
}
await this.closeQuickSelectTimeMenu();
await quickSelectTimeMenuToggle.close();
}
public async setHistoricalDataRange() {

View file

@ -170,11 +170,27 @@ export function TestSubjectsProvider({ getService }: FtrProviderContext) {
public async getAttribute(
selector: string,
attribute: string,
timeout?: number
options?:
| number
| {
findTimeout?: number;
tryTimeout?: number;
}
): Promise<string> {
return await retry.try(async () => {
log.debug(`TestSubjects.getAttribute(${selector}, ${attribute})`);
const element = await this.find(selector, timeout);
const findTimeout =
(typeof options === 'number' ? options : options?.findTimeout) ??
config.get('timeouts.find');
const tryTimeout =
(typeof options !== 'number' ? options?.tryTimeout : undefined) ??
config.get('timeouts.try');
log.debug(
`TestSubjects.getAttribute(${selector}, ${attribute}, tryTimeout=${tryTimeout}, findTimeout=${findTimeout})`
);
return await retry.tryForTime(tryTimeout, async () => {
const element = await this.find(selector, findTimeout);
return await element.getAttribute(attribute);
});
}

View file

@ -57,6 +57,7 @@ import {
import { ListingTableProvider } from './listing_table';
import { SavedQueryManagementComponentProvider } from './saved_query_management_component';
import { KibanaSupertestProvider } from './supertest';
import { MenuToggleProvider } from './menu_toggle';
export const services = {
...commonServiceProviders,
@ -93,4 +94,5 @@ export const services = {
elasticChart: ElasticChartProvider,
supertest: KibanaSupertestProvider,
managementMenu: ManagementMenuProvider,
MenuToggle: MenuToggleProvider,
};

View file

@ -0,0 +1,77 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { FtrProviderContext } from '../ftr_provider_context';
export function MenuToggleProvider({ getService }: FtrProviderContext) {
const log = getService('log');
const retry = getService('retry');
const testSubjects = getService('testSubjects');
interface Options {
name: string;
menuTestSubject: string;
toggleButtonTestSubject: string;
}
return class MenuToggle {
private readonly name: string;
private readonly menuTestSubject: string;
private readonly toggleButtonTestSubject: string;
constructor(options: Options) {
this.name = options.name;
this.menuTestSubject = options.menuTestSubject;
this.toggleButtonTestSubject = options.toggleButtonTestSubject;
}
async open() {
await this.setState(true);
}
async close() {
await this.setState(false);
}
private async setState(expectedState: boolean) {
log.debug(
`setting menu open state [name=${this.name}] [state=${expectedState ? 'open' : 'closed'}]`
);
await retry.try(async () => {
// if the menu is clearly in the expected state already, bail out quickly if so
const isOpen = await testSubjects.exists(this.menuTestSubject, { timeout: 1000 });
if (isOpen === expectedState) {
return;
}
// toggle the view state by clicking the button
await testSubjects.click(this.toggleButtonTestSubject);
if (expectedState === true) {
// wait for up to 10 seconds for the menu to show up, otherwise fail and retry
await testSubjects.existOrFail(this.menuTestSubject, { timeout: 10000 });
} else {
// wait for the form to hide, otherwise fail and retry
await testSubjects.waitForDeleted(this.menuTestSubject);
}
});
}
};
}

View file

@ -15,6 +15,7 @@ export default function ({ getPageObjects, getService }) {
const inspector = getService('inspector');
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const retry = getService('retry');
describe('embed in dashboard', () => {
before(async () => {
@ -50,9 +51,11 @@ export default function ({ getPageObjects, getService }) {
it('should populate inspector with requests for map embeddable', async () => {
await dashboardPanelActions.openInspectorByTitle('join example');
const joinExampleRequestNames = await inspector.getRequestNames();
await retry.try(async () => {
const joinExampleRequestNames = await inspector.getRequestNames();
expect(joinExampleRequestNames).to.equal('geo_shapes*,meta_for_geo_shapes*.shape_name');
});
await inspector.close();
expect(joinExampleRequestNames).to.equal('geo_shapes*,meta_for_geo_shapes*.shape_name');
await dashboardPanelActions.openInspectorByTitle('geo grid vector grid example');
const gridExampleRequestNames = await inspector.getRequestNames();

View file

@ -20,6 +20,13 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
const comboBox = getService('comboBox');
const renderable = getService('renderable');
const browser = getService('browser');
const MenuToggle = getService('MenuToggle');
const setViewPopoverToggle = new MenuToggle({
name: 'SetView Popover',
menuTestSubject: 'mapSetViewForm',
toggleButtonTestSubject: 'toggleSetViewVisibilityButton',
});
function escapeLayerName(layerName: string) {
return layerName.split(' ').join('_');
@ -234,41 +241,11 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
return buttons.length;
}
async isSetViewPopoverOpen() {
return await testSubjects.exists('mapSetViewForm', { timeout: 500 });
}
async openSetViewPopover() {
const isOpen = await this.isSetViewPopoverOpen();
if (!isOpen) {
await retry.try(async () => {
await testSubjects.click('toggleSetViewVisibilityButton');
const isOpenAfterClick = await this.isSetViewPopoverOpen();
if (!isOpenAfterClick) {
throw new Error('set view popover not opened');
}
});
}
}
async closeSetViewPopover() {
const isOpen = await this.isSetViewPopoverOpen();
if (isOpen) {
await retry.try(async () => {
await testSubjects.click('toggleSetViewVisibilityButton');
const isOpenAfterClick = await this.isSetViewPopoverOpen();
if (isOpenAfterClick) {
throw new Error('set view popover not closed');
}
});
}
}
async setView(lat: number, lon: number, zoom: number) {
log.debug(
`Set view lat: ${lat.toString()}, lon: ${lon.toString()}, zoom: ${zoom.toString()}`
);
await this.openSetViewPopover();
await setViewPopoverToggle.open();
await testSubjects.setValue('latitudeInput', lat.toString());
await testSubjects.setValue('longitudeInput', lon.toString());
await testSubjects.setValue('zoomInput', zoom.toString());
@ -278,11 +255,20 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
async getView() {
log.debug('Get view');
await this.openSetViewPopover();
const lat = await testSubjects.getAttribute('latitudeInput', 'value');
const lon = await testSubjects.getAttribute('longitudeInput', 'value');
const zoom = await testSubjects.getAttribute('zoomInput', 'value');
await this.closeSetViewPopover();
await setViewPopoverToggle.open();
// this method is regularly called within a retry, so we need to reduce the timeouts
// of the retries done within the getAttribute method in order to ensure that they fail
// early enough to retry getView()
const getAttributeOptions = {
tryTimeout: 5000,
findTimeout: 1000,
};
const lat = await testSubjects.getAttribute('latitudeInput', 'value', getAttributeOptions);
const lon = await testSubjects.getAttribute('longitudeInput', 'value', getAttributeOptions);
const zoom = await testSubjects.getAttribute('zoomInput', 'value', getAttributeOptions);
await setViewPopoverToggle.close();
return {
lat: parseFloat(lat),
lon: parseFloat(lon),