Skip to content

Commit

Permalink
[7.x] [ftr/menuToggle] provide helper for enhanced menu toggle handli…
Browse files Browse the repository at this point in the history
…ng (#81709) (#81800)

Co-authored-by: spalger <spalger@users.noreply.github.com>
# Conflicts:
#	test/functional/services/common/test_subjects.ts
  • Loading branch information
Spencer authored Oct 27, 2020
1 parent f3e6671 commit 4267321
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 76 deletions.
48 changes: 14 additions & 34 deletions test/functional/page_objects/time_picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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'
Expand All @@ -207,7 +187,7 @@ export function TimePickerProvider({ getService, getPageObjects }: FtrProviderCo
'superDatePickerToggleRefreshButton'
);
if (!keepQuickSelectOpen) {
await this.closeQuickSelectTimeMenu();
await quickSelectTimeMenuToggle.close();
}

return {
Expand Down Expand Up @@ -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() {
Expand All @@ -300,7 +280,7 @@ export function TimePickerProvider({ getService, getPageObjects }: FtrProviderCo
await testSubjects.click('superDatePickerToggleRefreshButton');
}

await this.closeQuickSelectTimeMenu();
await quickSelectTimeMenuToggle.close();
}

public async setHistoricalDataRange() {
Expand Down
28 changes: 24 additions & 4 deletions test/functional/services/common/test_subjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,30 @@ export function TestSubjectsProvider({ getService }: FtrProviderContext) {
});
}

public async getAttribute(selector: string, attribute: string): Promise<string> {
return await retry.try(async () => {
log.debug(`TestSubjects.getAttribute(${selector}, ${attribute})`);
const element = await this.find(selector);
public async getAttribute(
selector: string,
attribute: string,
options?:
| number
| {
findTimeout?: number;
tryTimeout?: number;
}
): Promise<string> {
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);
});
}
Expand Down
2 changes: 2 additions & 0 deletions test/functional/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -93,4 +94,5 @@ export const services = {
elasticChart: ElasticChartProvider,
supertest: KibanaSupertestProvider,
managementMenu: ManagementMenuProvider,
MenuToggle: MenuToggleProvider,
};
77 changes: 77 additions & 0 deletions test/functional/services/menu_toggle.ts
Original file line number Diff line number Diff line change
@@ -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);
}
});
}
};
}
7 changes: 5 additions & 2 deletions x-pack/test/functional/apps/maps/embeddable/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down Expand Up @@ -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();
Expand Down
58 changes: 22 additions & 36 deletions x-pack/test/functional/page_objects/gis_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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('_');
Expand Down Expand Up @@ -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());
Expand All @@ -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),
Expand Down

0 comments on commit 4267321

Please sign in to comment.