Skip to content

Commit

Permalink
Fix flakiness on custom time range saved searches (#165454)
Browse files Browse the repository at this point in the history
A bunch of tests on dashboards are customising some of the panels
settings and providing custom time ranges:

<img width="409" alt="image"
src="https://github.com/elastic/kibana/assets/25349407/c869c1a3-f7db-4ccd-ad00-c5403f2b4201">

Currently, the logic is not waiting for the quick toggle animation to
complete, before proceeding to select a time range.
This can cause a flaky behavior if the logic tries to customize the
range before the button is actually available, as seen on [this failed
test](https://s3.amazonaws.com/buildkiteartifacts.com/e0f3970e-3a75-4621-919f-e6c773e2bb12/0fda5127-f57f-42fb-8e5a-146b3d535916/018a4c44-5497-48b6-8521-a8a79a2f63b4/018a4c46-0e7a-4b69-9a3d-9c54c27165b0/target/test_failures/018a4c46-0e7a-4b69-9a3d-9c54c27165b0_4fcbc47e71644919129e320eea8bb3bc.html?response-content-type=text%2Fhtml&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAQPCP3C7LZWZ5UB5F%2F20230901%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230901T094837Z&X-Amz-Expires=600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEB0aCXVzLWVhc3QtMSJGMEQCIGCyKcVLGPUawZubNzZdt5oZNb5v0saiIuPqXwI7rmwlAiAsOj%2Fiep94v%2BYZJtLY3Gw0m%2FmK5mJw2IcIBdNKFXgK%2BCr6Awjm%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAAaDDAzMjM3OTcwNTMwMyIMXOd1Hm6ks%2FNE37V0Ks4DgMUso7syv87hnPcC%2BB1soxvFFnj4JnNZc6ZgkLUe93z99iPFBUsqH%2BRbUTfSbjVOEJYBKGYuvp32xvSWsYNVPXKmcej18LC0yNi%2BBzoG2X%2Bj80g%2BbGMm6YfTncjPhOE0CHHqOWXts9nQ8WpDy8XOl0zfMtuiPjzOXHo9lvw2mgYDZIJIMV72FYB9JGg8FPbLQtD3rysLGNE0VDKgl5LCnYwhY1pwRCRHnVW41QfV0pwK%2FbjNf9HjdK31LQvMY%2FGPuB3M6O2CUZLsvLGfWBeGYHtkqb0hrL9ijO1Uo28ZSS1FytPftEdF0e1kAC9C5zD56HtYm55aktOWtaaC0XPWLdWWGUq%2FKQzhxSCiXK6ovATU3zI3yPNoZs92YBYmIPMOpEI40dCCpksjPwAMCiQd%2F9gMNKP5Qp5CbYd2Khy%2FeXaT8J7HOZCueN63O0j%2FtX1tbwfznhbr74lAcRQjueRYmwboZaGSDZUQ33lSSmyZk1V9WF9eJyt88oHvIx0q9bIjvOlW05DiNKfEFWYwfBywdGuvRU6eGMs1QcDNu33Lb%2BhymudM2JZmQKIjZOcb2l3Fzctp614owH4JcRlmF4%2BIa4xHeBdRlTMysS8bTIsgMK7axacGOqYBzIpC1wgZWJ1kZ0agLWCNaMIdUl%2B4xrr7w%2Fz0843WWMhRrvbJhDTHqk5UclF%2FSROAMe0FH2XEXiQ65ILyUPlrUMels5tfQ3Pp%2FJWPi9NsQJUQ1n9uLN%2BFPDOoMo8Uxg4%2FkG2O7yTkrIdArfA6pWN9I21gFMW%2BFZy9BMYltt5T65ZKOyYAIFGpLhgfBySIBCUMgwR1kusfDhf1%2FRTvtDKD2sJKN5a0IA%3D%3D&X-Amz-SignedHeaders=host&X-Amz-Signature=35fabe908aa7514e4a92de0ed12973af85ccfb439984fc3bdd7ef3bb8fe3419b).
(part of this [failed CI
build](https://buildkite.com/elastic/kibana-pull-request/builds/155285#018a4c46-0e7a-4b69-9a3d-9c54c27165b0))

The goal of this PR is to add a small waiting period, to make sure the
toggle animation has completed, and that the time range controls are
visible and clickable.

I used the opportunity to cleanup some "await delay millis" calls,
reusing existing logic instead.

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
gsoldevila and kibanamachine authored Sep 25, 2023
1 parent 823a1d5 commit b98b6d0
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 44 deletions.
3 changes: 3 additions & 0 deletions test/functional/services/dashboard/add_panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ export class DashboardAddPanelService extends FtrService {
await this.testSubjects.click(`savedObjectTitle${embeddableName.split(' ').join('-')}`);
await this.testSubjects.exists('addObjectToDashboardSuccess');
await this.closeAddPanel();

// close "Added successfully" toast
await this.common.clearAllToasts();
return embeddableName;
}

Expand Down
68 changes: 56 additions & 12 deletions test/functional/services/dashboard/panel_settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

import { FtrProviderContext } from '../../ftr_provider_context';
import { CommonlyUsed } from '../../page_objects/time_picker';
import { WebElementWrapper } from '../lib/web_element_wrapper';

export function DashboardCustomizePanelProvider({ getService }: FtrProviderContext) {
export function DashboardCustomizePanelProvider({ getService, getPageObject }: FtrProviderContext) {
const log = getService('log');
const retry = getService('retry');
const toasts = getService('toasts');
Expand Down Expand Up @@ -39,6 +40,48 @@ export function DashboardCustomizePanelProvider({ getService }: FtrProviderConte
await testSubjects.missingOrFail(this.TOGGLE_TIME_RANGE_TEST_SUBJ);
}

public async findCustomTimeRangeToggleButton(): Promise<WebElementWrapper> {
log.debug('findCustomTimeRangeToggleButton');
let button: WebElementWrapper | undefined;
await retry.waitFor('custom time range toggle button', async () => {
button = await testSubjects.find(this.TOGGLE_TIME_RANGE_TEST_SUBJ);
return Boolean(button);
});
return button!;
}

public async enableCustomTimeRange() {
log.debug('enableCustomTimeRange');
const toggle = await this.findCustomTimeRangeToggleButton();

await retry.try(async () => {
if ((await toggle.getAttribute('aria-checked')) === 'false') {
await toggle.click();
await retry.waitForWithTimeout(
'custom time range to be enabled',
1000,
async () => (await toggle.getAttribute('aria-checked')) === 'true'
);
}
});
}

public async disableCustomTimeRange() {
log.debug('disableCustomTimeRange');
const toggle = await this.findCustomTimeRangeToggleButton();

await retry.try(async () => {
if ((await toggle.getAttribute('aria-checked')) === 'true') {
await toggle.click();
await retry.waitForWithTimeout(
'custom time range to be disabled',
1000,
async () => (await toggle.getAttribute('aria-checked')) === 'false'
);
}
});
}

public async findFlyout() {
log.debug('findFlyout');
return await testSubjects.find(this.FLYOUT_TEST_SUBJ);
Expand All @@ -50,15 +93,21 @@ export function DashboardCustomizePanelProvider({ getService }: FtrProviderConte
return await flyout.findByCssSelector(`[data-test-subj="${testSubject}"]`);
}

public async findToggleQuickMenuButton() {
log.debug('findToggleQuickMenuButton');
public async findDatePickerQuickMenuButton() {
log.debug('findDatePickerQuickMenuButton');
return await this.findFlyoutTestSubject('superDatePickerToggleQuickMenuButton');
}

public async clickToggleQuickMenuButton() {
log.debug('clickToggleQuickMenuButton');
const button = await this.findToggleQuickMenuButton();
await button.click();
public async openDatePickerQuickMenu() {
log.debug('openDatePickerQuickMenu');
let button: WebElementWrapper | undefined;
await retry.waitFor('superDatePickerToggleQuickMenuButton to be present', async () => {
button = await this.findDatePickerQuickMenuButton();
return Boolean(button);
});
if (button) {
await button.click();
}
}

public async clickCommonlyUsedTimeRange(time: CommonlyUsed) {
Expand Down Expand Up @@ -111,10 +160,5 @@ export function DashboardCustomizePanelProvider({ getService }: FtrProviderConte
await testSubjects.waitForDeleted('cancelCustomizePanelButton');
});
}

public async clickToggleShowCustomTimeRange() {
log.debug('clickToggleShowCustomTimeRange');
await testSubjects.click(this.TOGGLE_TIME_RANGE_TEST_SUBJ);
}
})();
}
12 changes: 6 additions & 6 deletions x-pack/test/functional/apps/dashboard/group2/panel_time_range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
it('can add a custom time range to a panel', async () => {
await PageObjects.lens.createAndAddLensFromDashboard({});
await dashboardPanelActions.customizePanel();
await dashboardCustomizePanel.clickToggleShowCustomTimeRange();
await dashboardCustomizePanel.clickToggleQuickMenuButton();
await dashboardCustomizePanel.enableCustomTimeRange();
await dashboardCustomizePanel.openDatePickerQuickMenu();
await dashboardCustomizePanel.clickCommonlyUsedTimeRange('Last_30 days');
await dashboardCustomizePanel.clickSaveButton();
await PageObjects.dashboard.waitForRenderComplete();
Expand All @@ -56,7 +56,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {

it('can remove a custom time range from a panel', async () => {
await dashboardBadgeActions.clickTimeRangeBadgeAction();
await dashboardCustomizePanel.clickToggleShowCustomTimeRange();
await dashboardCustomizePanel.disableCustomTimeRange();
await dashboardCustomizePanel.clickSaveButton();
await PageObjects.dashboard.waitForRenderComplete();
await dashboardBadgeActions.expectMissingTimeRangeBadgeAction();
Expand All @@ -68,8 +68,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
it('can add a custom time range to panel', async () => {
await dashboardPanelActions.saveToLibrary('My by reference visualization');
await dashboardPanelActions.customizePanel();
await dashboardCustomizePanel.clickToggleShowCustomTimeRange();
await dashboardCustomizePanel.clickToggleQuickMenuButton();
await dashboardCustomizePanel.enableCustomTimeRange();
await dashboardCustomizePanel.openDatePickerQuickMenu();
await dashboardCustomizePanel.clickCommonlyUsedTimeRange('Last_30 days');
await dashboardCustomizePanel.clickSaveButton();
await PageObjects.dashboard.waitForRenderComplete();
Expand All @@ -80,7 +80,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {

it('can remove a custom time range from a panel', async () => {
await dashboardBadgeActions.clickTimeRangeBadgeAction();
await dashboardCustomizePanel.clickToggleShowCustomTimeRange();
await dashboardCustomizePanel.disableCustomTimeRange();
await dashboardCustomizePanel.clickSaveButton();
await PageObjects.dashboard.waitForRenderComplete();
await dashboardBadgeActions.expectMissingTimeRangeBadgeAction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await dashboard.gotoDashboardEditMode(drilldowns.DASHBOARD_WITH_PIE_CHART_NAME);

await panelActions.customizePanel();
await dashboardCustomizePanel.clickToggleShowCustomTimeRange();
await dashboardCustomizePanel.disableCustomTimeRange();
await dashboardCustomizePanel.clickSaveButton();
await dashboard.saveDashboard('Dashboard with Pie Chart');
});
Expand Down Expand Up @@ -80,8 +80,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await dashboard.gotoDashboardEditMode(drilldowns.DASHBOARD_WITH_PIE_CHART_NAME);

await panelActions.customizePanel();
await dashboardCustomizePanel.clickToggleShowCustomTimeRange();
await dashboardCustomizePanel.clickToggleQuickMenuButton();
await dashboardCustomizePanel.enableCustomTimeRange();
await dashboardCustomizePanel.openDatePickerQuickMenu();
await dashboardCustomizePanel.clickCommonlyUsedTimeRange('Last_90 days');
await dashboardCustomizePanel.clickSaveButton();

Expand Down
7 changes: 3 additions & 4 deletions x-pack/test/functional/apps/discover/saved_searches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.common.unsetTime();
});

// FLAKY: https://github.com/elastic/kibana/issues/104578
describe.skip('Customize time range', () => {
describe('Customize time range', () => {
it('should be possible to customize time range for saved searches on dashboards', async () => {
await PageObjects.dashboard.navigateToApp();
await PageObjects.dashboard.clickNewDashboard();
Expand All @@ -55,8 +54,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
expect(await dataGrid.getDocCount()).to.be(500);

await panelActions.customizePanel();
await dashboardCustomizePanel.clickToggleShowCustomTimeRange();
await dashboardCustomizePanel.clickToggleQuickMenuButton();
await dashboardCustomizePanel.enableCustomTimeRange();
await dashboardCustomizePanel.openDatePickerQuickMenu();
await dashboardCustomizePanel.clickCommonlyUsedTimeRange('Last_90 days');
await dashboardCustomizePanel.clickSaveButton();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await dashboard.waitForRenderComplete();
const originalEmbeddableCount = await canvas.getEmbeddableCount();
await dashboardPanelActions.customizePanel();
await dashboardCustomizePanel.clickToggleShowCustomTimeRange();
await dashboardCustomizePanel.clickToggleQuickMenuButton();
await dashboardCustomizePanel.enableCustomTimeRange();
await dashboardCustomizePanel.openDatePickerQuickMenu();
await dashboardCustomizePanel.clickCommonlyUsedTimeRange('Last_30 days');
await dashboardCustomizePanel.clickSaveButton();
await dashboard.waitForRenderComplete();
Expand Down Expand Up @@ -80,8 +80,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await dashboard.waitForRenderComplete();
const originalEmbeddableCount = await canvas.getEmbeddableCount();
await dashboardPanelActions.customizePanel();
await dashboardCustomizePanel.clickToggleShowCustomTimeRange();
await dashboardCustomizePanel.clickToggleQuickMenuButton();
await dashboardCustomizePanel.enableCustomTimeRange();
await dashboardCustomizePanel.openDatePickerQuickMenu();
await dashboardCustomizePanel.clickCommonlyUsedTimeRange('Last_30 days');
await dashboardCustomizePanel.clickSaveButton();
await dashboard.waitForRenderComplete();
Expand Down
4 changes: 2 additions & 2 deletions x-pack/test/functional/apps/uptime/overview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export const UPTIME_HEARTBEAT_DATA = 'x-pack/test/functional/es_archives/uptime/full_heartbeat';

export default ({ getPageObjects, getService }: FtrProviderContext) => {
const { uptime } = getPageObjects(['uptime']);
const { uptime, common } = getPageObjects(['uptime', 'common']);
const retry = getService('retry');
const esArchiver = getService('esArchiver');

Expand Down Expand Up @@ -104,7 +104,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
await uptime.setMonitorListPageSize(50);
// the pagination parameter should be cleared after a size change
await new Promise((resolve) => setTimeout(resolve, 1000));
await common.sleep(1000);
await retry.try(async () => {
await uptime.pageUrlContains('pagination', false);
});
Expand Down
7 changes: 3 additions & 4 deletions x-pack/test/functional/page_objects/navigational_search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ interface SearchResult {
label: string;
}

const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

export class NavigationalSearchPageObject extends FtrService {
private readonly find = this.ctx.getService('find');
private readonly testSubjects = this.ctx.getService('testSubjects');
private readonly common = this.ctx.getPageObject('common');

async focus() {
const field = await this.testSubjects.find('nav-search-input');
Expand Down Expand Up @@ -69,7 +68,7 @@ export class NavigationalSearchPageObject extends FtrService {
// without heavy flakiness in this situation.
// there is NO ui indication of any kind to detect when all the emissions are done,
// so we are forced to fallback to awaiting a given amount of time once the first options are displayed.
await delay(waitUntil);
await this.common.sleep(waitUntil);
}

async getDisplayedResults() {
Expand All @@ -79,7 +78,7 @@ export class NavigationalSearchPageObject extends FtrService {

async isNoResultsPlaceholderDisplayed(checkAfter: number = 3000) {
// see comment in `waitForResultsLoaded`
await delay(checkAfter);
await this.common.sleep(checkAfter);
return this.testSubjects.exists('nav-search-no-results');
}

Expand Down
2 changes: 1 addition & 1 deletion x-pack/test/functional/services/cases/single_case_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export function CasesSingleViewServiceProvider({ getService, getPageObject }: Ft
'[data-test-subj="euiMarkdownEditorToolbarButton"][aria-label="Visualization"]'
);
await addVisualizationButton.moveMouseTo();
await new Promise((resolve) => setTimeout(resolve, 500)); // give tooltip time to open
await common.sleep(500); // give tooltip time to open
},

async assertCaseTitle(expectedTitle: string) {
Expand Down
7 changes: 3 additions & 4 deletions x-pack/test/functional/services/data_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@
import type { MappingProperty } from '@elastic/elasticsearch/lib/api/types';
import type { FtrProviderContext } from '../ftr_provider_context';

const waitFor = (time: number = 1000) => new Promise((r) => setTimeout(r, time));

/**
* High level interface to operate with Elasticsearch data stream and TSDS.
*/
export function DataStreamProvider({ getService }: FtrProviderContext) {
export function DataStreamProvider({ getService, getPageObject }: FtrProviderContext) {
const es = getService('es');
const log = getService('log');
const retry = getService('retry');
const common = getPageObject('common');

const downsampleDefaultOptions = {
isStream: true,
Expand Down Expand Up @@ -65,7 +64,7 @@ export function DataStreamProvider({ getService }: FtrProviderContext) {
waitTime / 1000
}s before running the downsampling to avoid a null_pointer_exception`
);
await waitFor(waitTime);
await common.sleep(waitTime);

try {
log.info(`downsampling "${sourceIndex}" index...`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
import { FtrProviderContext } from '../ftr_provider_context';
import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper';

export function InfraSourceConfigurationFormProvider({ getService }: FtrProviderContext) {
export function InfraSourceConfigurationFormProvider({
getService,
getPageObject,
}: FtrProviderContext) {
const retry = getService('retry');
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const common = getPageObject('common');

return {
/**
Expand Down Expand Up @@ -94,15 +98,15 @@ export function InfraSourceConfigurationFormProvider({ getService }: FtrProvider
const movementDifference = destinationIndex - sourceIndex;
await moveLogColumnHandle.pressKeys(browser.keys.SPACE);
for (let i = 0; i < Math.abs(movementDifference); i++) {
await new Promise((res) => setTimeout(res, KEY_PRESS_DELAY_MS));
await common.sleep(KEY_PRESS_DELAY_MS);
if (movementDifference > 0) {
await moveLogColumnHandle.pressKeys(browser.keys.ARROW_DOWN);
} else {
await moveLogColumnHandle.pressKeys(browser.keys.ARROW_UP);
}
}
await moveLogColumnHandle.pressKeys(browser.keys.SPACE);
await new Promise((res) => setTimeout(res, KEY_PRESS_DELAY_MS));
await common.sleep(KEY_PRESS_DELAY_MS);
},

/**
Expand Down
2 changes: 1 addition & 1 deletion x-pack/test/functional/services/uptime/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function UptimeNavigationProvider({ getService, getPageObjects }: FtrProv
return {
async refreshApp() {
await browser.refresh();
await new Promise((resolve) => setTimeout(resolve, 1000));
await PageObjects.common.sleep(1000);
await PageObjects.header.waitUntilLoadingHasFinished();
},

Expand Down

0 comments on commit b98b6d0

Please sign in to comment.