[kbn-journeys] wait for charts inside located div (#179360)

## Summary

Fix for the flaky infra_hosts_view journey:

```
...
[01:01:17]       │ debg waitForRender: 7 out of 5 are loaded...
[01:01:17]       │ debg waitForRender: 7 out of 5 are loaded...
[01:01:18]       │ debg waitForRender: 7 out of 5 are loaded...
[01:01:18]       │ debg waitForRender: 7 out of 5 are loaded...
[01:01:19]       │ debg waitForRender: 7 out of 5 are loaded...
...
[01:01:20]       └- ✖ fail: Journey[infra_hosts_view] Navigate to Hosts view and load 500 hosts
[01:01:20]       │   Error: timed out waiting for rendering of 5 elements with selector .echChartStatus is completed
[01:01:20]       │       at onFailure (retry_for_truthy.ts:39:13)
[01:01:20]       │       at retryForSuccess (retry_for_success.ts:84:7)
[01:01:20]       │       at retryForTruthy (retry_for_truthy.ts:27:3)
[01:01:20]       │       at RetryService.waitForWithTimeout (retry.ts:73:5)
[01:01:20]       │       at KibanaPage.waitForRender (kibana_page.ts:54:5)
[01:01:20]       │       at KibanaPage.waitForCharts (kibana_page.ts:103:5)
[01:01:20]       │       at Object.fn (infra_hosts_view.ts:32:5)
[01:01:20]       │       at journey_ftr_harness.ts:499:15
[01:01:20]       │       at JourneyFtrHarness.withSpan (journey_ftr_harness.ts:350:22)
[01:01:20]       │       at Context.<anonymous> (journey_ftr_harness.ts:497:11)
[01:01:20]       │       at Object.apply (wrap_function.js:73:16)
```

![image](dfeeb8e0-9dc3-4845-a345-2df464ebf055)


The failure is due to playwright was able to find 7 charts instead of 5
(expected)
It turned out the Infra page has 5 metric charts + 2 Control inputs + 12
Lens embeddables: seems like some of rendering is async and depends on
screen viewport size.
PR is adding `parentLocator` to `waitForRender` function as opt-in
argument that helps to locate charts inside the specified parent
element.

How to test: 
perf run: `node scripts/run_performance.js --journey-path
x-pack/performance/journeys_e2e/infra_hosts_view.ts`
test run: `node scripts/functional_tests.js --config
x-pack/performance/journeys_e2e/infra_hosts_view.ts`
This commit is contained in:
Dzmitry Lemechko 2024-03-26 11:07:14 +01:00 committed by GitHub
parent 9805fc5c35
commit 81c7dd4f24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 39 additions and 11 deletions

View file

@ -71,8 +71,8 @@ export class JourneyFtrHarness {
// journey can be run to collect EBT/APM metrics or just as a functional test
// TEST_INGEST_ES_DATA is defined via scripts/run_perfomance.js run only
private readonly isPerformanceRun = process.env.TEST_PERFORMANCE_PHASE || false;
private readonly shouldIngestEsData = !!process.env.TEST_INGEST_ES_DATA;
private readonly isPerformanceRun = !!process.env.TEST_PERFORMANCE_PHASE;
private readonly shouldIngestEsData = process.env.TEST_INGEST_ES_DATA === 'true' || false;
// Update the Telemetry and APM global labels to link traces with journey
private async updateTelemetryAndAPMLabels(labels: { [k: string]: string }) {

View file

@ -8,11 +8,12 @@
import { subj } from '@kbn/test-subj-selector';
import { ToolingLog } from '@kbn/tooling-log';
import { Page } from 'playwright';
import { ElementHandle, Page } from 'playwright';
import { Retry } from '..';
interface WaitForRenderArgs {
expectedItemsCount: number;
parentLocator?: string;
itemLocator: string;
checkAttribute: string;
timeout: number;
@ -46,19 +47,35 @@ export class KibanaPage {
async waitForRender({
expectedItemsCount,
parentLocator,
itemLocator,
checkAttribute,
timeout,
}: WaitForRenderArgs) {
// we can't use `page.waitForFunction` because of CSP while testing on Cloud
await this.retry.waitForWithTimeout(
`rendering of ${expectedItemsCount} elements with selector ${itemLocator} is completed`,
`rendering of ${expectedItemsCount} elements with selector ${itemLocator} ${
parentLocator ? `and ${parentLocator} parent selector` : ''
} is completed`,
timeout,
async () => {
const renderingItems = await this.page.$$(itemLocator);
if (renderingItems.length === expectedItemsCount) {
const loadingItems: ElementHandle[] = [];
if (parentLocator) {
const parentElement = await this.page.$(parentLocator);
if (parentElement) {
loadingItems.push(...(await parentElement.$$(itemLocator)));
} else {
this.log.debug(`waitForRender: Can't locate ${parentLocator} element`);
return false;
}
} else {
loadingItems.push(...(await this.page.$$(itemLocator)));
}
// check if loading items count is matching the input
if (loadingItems.length === expectedItemsCount) {
// check if all loaded items are rendered
const renderStatuses = await Promise.all(
renderingItems.map(async (item) => {
loadingItems.map(async (item) => {
return (await item.getAttribute(checkAttribute)) === 'true';
})
);
@ -70,7 +87,7 @@ export class KibanaPage {
} else {
// not all components are loaded yet
this.log.debug(
`waitForRender: ${renderingItems.length} out of ${expectedItemsCount} are loaded...`
`waitForRender: ${loadingItems.length} out of ${expectedItemsCount} are loaded...`
);
return false;
}
@ -94,15 +111,18 @@ export class KibanaPage {
}
async waitForCharts({
parentLocator,
count,
timeout = this.defaultTimeout,
}: {
parentLocator?: string;
count: number;
timeout?: number;
}) {
await this.waitForRender({
expectedItemsCount: count,
itemLocator: '.echChartStatus',
parentLocator,
itemLocator: 'div.echChartStatus',
checkAttribute: 'data-ech-render-complete',
timeout,
});

View file

@ -29,7 +29,11 @@ export const journey = new Journey({
// wait for table to be loaded
await page.waitForSelector(subj('hostsView-table-loaded'));
// wait for metric charts to be loaded
await kibanaPage.waitForCharts({ count: 5, timeout: 60000 });
await kibanaPage.waitForCharts({
parentLocator: subj('hostsViewKPIGrid'),
count: 5,
timeout: 60000,
});
})
.step('Go to single host asset details view', async ({ page, kibanaPage }) => {
// get the links to asset details page
@ -37,5 +41,9 @@ export const journey = new Journey({
// click on the first host in the table to see asset details
await hostsTableLinks.first().click();
// wait for metric charts on the asset details view to be loaded
await kibanaPage.waitForCharts({ count: 4, timeout: 60000 });
await kibanaPage.waitForCharts({
parentLocator: subj('infraAssetDetailsKPIGrid'),
count: 4,
timeout: 60000,
});
});