[scout/security] improve alerting table wait (#216262)

## Summary

This PR improves waiting for Alerts table to be loaded.

Relying on the first alert might cause flakiness in the future test
cases, I changed the rule name to be unique for test run and search
alert based on its rule name, not the first row.

If the alert is missing or it has a wrong name, the test will fail with
clear message:

```
    Error: Alert with rule 'xys' is not displayed

    Timed out 10000ms waiting for expect(locator).toBeVisible()

    Locator: locator('div.euiDataGridRow').filter({ hasText: 'xys' })
    Expected: visible
    Received: <element(s) not found>
    Call log:
      - Alert with rule 'xys' is not displayed with timeout 10000ms
      - waiting for locator('div.euiDataGridRow').filter({ hasText: 'xys' })
```

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Dzmitry Lemechko 2025-04-03 16:37:39 +02:00 committed by GitHub
parent eaf467f53c
commit d1707cc872
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 33 additions and 42 deletions

View file

@ -5,48 +5,33 @@
* 2.0.
*/
import { ScoutPage, Locator } from '@kbn/scout';
import { ScoutPage, Locator, expect } from '@kbn/scout';
const PAGE_URL = 'security/alerts';
const EXPAND_EVENT = 'expand-event';
export class AlertsTablePage {
public expandAlertBtn: Locator;
public alertRow: Locator;
public alertsTable: Locator;
constructor(private readonly page: ScoutPage) {
this.expandAlertBtn = this.page.testSubj.locator(EXPAND_EVENT);
this.alertRow = this.page.locator('div.euiDataGridRow');
this.alertsTable = this.page.testSubj.locator('alertsTable');
}
async navigate() {
await this.page.gotoApp(PAGE_URL);
return this.page.gotoApp(PAGE_URL);
}
async expandFirstAlertDetailsFlyout() {
const maxAttempts = 100;
let attempts = 0;
async expandAlertDetailsFlyout(ruleName: string) {
await this.page.waitForLoadingIndicatorHidden();
await this.alertsTable.waitFor({ state: 'visible' });
// Filter alert by unique rule name
const row = this.alertRow.filter({ hasText: ruleName });
await expect(
row,
`Alert with rule '${ruleName}' is not displayed in the alerts table`
).toBeVisible();
while ((await this.expandAlertBtn.count()) === 0) {
if (attempts >= maxAttempts) {
throw new Error('Timed out waiting for alert buttons to appear');
}
await this.page.waitForTimeout(100);
attempts++;
}
const buttons = await this.expandAlertBtn.all();
if (buttons.length > 0) {
await buttons[0].click();
} else {
throw new Error('No expand alert details buttons found');
}
}
async getCurrentUrl() {
const url = this.page.url();
return url;
}
async reload() {
return this.page.reload();
return row.locator(`[data-test-subj='expand-event']`).click();
}
}

View file

@ -11,34 +11,40 @@ import { CUSTOM_QUERY_RULE } from '@kbn/scout-security/src/playwright/constants/
const RIGHT = 'right';
spaceTest.describe('Expandable flyout state sync', { tag: ['@ess', '@svlSecurity '] }, () => {
spaceTest.beforeEach(async ({ browserAuth, apiServices }) => {
await apiServices.detectionRule.deleteAll();
await apiServices.detectionRule.createCustomQueryRule(CUSTOM_QUERY_RULE);
let ruleName: string;
spaceTest.beforeEach(async ({ browserAuth, apiServices, scoutSpace }) => {
ruleName = `${CUSTOM_QUERY_RULE.name}_${scoutSpace.id}_${Date.now()}`;
await apiServices.detectionRule.createCustomQueryRule({ ...CUSTOM_QUERY_RULE, name: ruleName });
await browserAuth.loginAsPlatformEngineer();
});
spaceTest('should test flyout url sync', async ({ pageObjects }) => {
spaceTest.afterEach(async ({ apiServices }) => {
await apiServices.detectionRule.deleteAll();
});
spaceTest('should test flyout url sync', async ({ pageObjects, page }) => {
await pageObjects.alertsTablePage.navigate();
const urlBeforeAlertDetails = await pageObjects.alertsTablePage.getCurrentUrl();
const urlBeforeAlertDetails = page.url();
expect(urlBeforeAlertDetails).not.toContain(RIGHT);
await pageObjects.alertsTablePage.expandFirstAlertDetailsFlyout();
await pageObjects.alertsTablePage.expandAlertDetailsFlyout(ruleName);
const urlAfterAlertDetails = await pageObjects.alertsTablePage.getCurrentUrl();
const urlAfterAlertDetails = page.url();
expect(urlAfterAlertDetails).toContain(RIGHT);
const headerTitle = pageObjects.alertDetailsRightPanelPage.detailsFlyoutHeaderTitle;
await expect(headerTitle).toHaveText(CUSTOM_QUERY_RULE.name);
await expect(headerTitle).toHaveText(ruleName);
await pageObjects.alertsTablePage.reload();
await page.reload();
await page.waitForLoadingIndicatorHidden();
const urlAfterReload = await pageObjects.alertsTablePage.getCurrentUrl();
const urlAfterReload = page.url();
expect(urlAfterReload).toContain(RIGHT);
await pageObjects.alertDetailsRightPanelPage.closeFlyout();
const urlAfterClosingFlyout = await pageObjects.alertsTablePage.getCurrentUrl();
const urlAfterClosingFlyout = page.url();
expect(urlAfterClosingFlyout).not.toContain(RIGHT);
});
});