test: fix flaky Alerts OSelect dropdowns (click trigger, not root div) (#12869)
## Problem The scheduled **main** Playwright Regression run failed in the **Alerts-Regression** shard ([run 28097849118](https://github.com/openobserve/openobserve/actions/runs/28097849118/job/83192928864)) with 2 tests failing on the **same** locator `[data-test$="-popover"] [data-test$="-option"]` (dropdown options never found): - `alerts-bugs.spec.js` › "Template should not appear twice in override template input" (`@bug-10110`) - `alerts-regression.spec.js` › "Bug #9967: PromQL alert creation" (`@bug-9967`) ## Root cause The alert form selects were migrated to the **OSelect** (reka-ui popover) component. OSelect forwards the consumer's `data-test` onto an **inner `<button data-test="...-trigger">`**, while the root element is a plain `<div>`. Both tests clicked the **root `<div>`**, which does **not** toggle the reka popover — `aria-expanded` stays `false`, the popover never opens, and the option locator times out. This is not caused by #12855; it reproduces on an older build too. The codebase already had the correct pattern elsewhere (group-by select clicks `[data-test$="-trigger"]`). ## Fix - New shared helper `openOSelectDropdown(page, rootLocator)` (`tests/ui-testing/pages/alertsPages/oselectHelpers.js`) that clicks the inner `-trigger` and **retries until `aria-expanded="true"`** — the reka trigger can open-then-close on a single Playwright click. - `alertsPage.openAdvancedTemplateOverrideSelect()` uses the helper; the spec now calls that page-object method (no raw locator in the spec). - Routed **all 8** destination-dropdown open sites in `alertCreationWizard.js` through the same helper (DRY; the same latent bug affected every one). ## Validation (local, against running o2) | Spec | Result | |------|--------| | `alerts-bugs.spec.js` | **4 passed** | | `alerts-regression.spec.js` | **5 passed** (incl. Bug #9967 PromQL) | Both originally-failing tests are green; no regressions across the changed destination sites. Passed a Sentinel code-quality review (0 critical). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b0f4b0e46f
commit
0afbe40fe4
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
import { expect } from '@playwright/test';
|
||||
import testLogger from '../../playwright-tests/utils/test-logger.js';
|
||||
import { openOSelectDropdown } from './oselectHelpers.js';
|
||||
|
||||
export class AlertCreationWizard {
|
||||
constructor(page, commonActions, locators) {
|
||||
|
|
@ -153,7 +154,7 @@ export class AlertCreationWizard {
|
|||
// Destination selection with fallback
|
||||
const destinationDropdown = this.page.locator('[data-test="alert-destinations-select"]');
|
||||
await destinationDropdown.waitFor({ state: 'visible', timeout: 10000 });
|
||||
await destinationDropdown.click();
|
||||
await openOSelectDropdown(this.page, destinationDropdown);
|
||||
await this.page.waitForTimeout(1000);
|
||||
|
||||
// Destination dropdown is OSelect (Reka Listbox) post-migration.
|
||||
|
|
@ -265,7 +266,7 @@ export class AlertCreationWizard {
|
|||
// Destination selection with fallback
|
||||
const destinationSection = this.page.locator('[data-test="alert-destinations-select"]');
|
||||
await destinationSection.waitFor({ state: 'visible', timeout: 10000 });
|
||||
await destinationSection.click();
|
||||
await openOSelectDropdown(this.page, destinationSection);
|
||||
await this.page.waitForTimeout(1000);
|
||||
|
||||
const visibleDestMenuDefItems = this.page.locator('[data-test$="-popover"] [data-test$="-option"]');
|
||||
|
|
@ -449,7 +450,7 @@ export class AlertCreationWizard {
|
|||
// Destination selection using v3 data-test locator
|
||||
const destinationDropdown = this.page.locator('[data-test="alert-destinations-select"]');
|
||||
await destinationDropdown.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await destinationDropdown.click();
|
||||
await openOSelectDropdown(this.page, destinationDropdown);
|
||||
await this.page.waitForTimeout(1000);
|
||||
|
||||
const visibleDestMenuSqlItems = this.page.locator('[data-test$="-popover"] [data-test$="-option"]');
|
||||
|
|
@ -619,7 +620,7 @@ export class AlertCreationWizard {
|
|||
// Select destination for REAL-TIME alerts
|
||||
const destinationDropdown = this.page.locator('[data-test="alert-destinations-select"]');
|
||||
await destinationDropdown.waitFor({ state: 'visible', timeout: 10000 });
|
||||
await destinationDropdown.click();
|
||||
await openOSelectDropdown(this.page, destinationDropdown);
|
||||
await this.page.waitForTimeout(1000);
|
||||
|
||||
// Use popover selector for destination
|
||||
|
|
@ -804,7 +805,7 @@ export class AlertCreationWizard {
|
|||
|
||||
const destinationDropdown = this.page.locator('[data-test="alert-destinations-select"]');
|
||||
await destinationDropdown.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await destinationDropdown.click();
|
||||
await openOSelectDropdown(this.page, destinationDropdown);
|
||||
await this.page.waitForTimeout(1000);
|
||||
|
||||
// Use popover selector for destination
|
||||
|
|
@ -1294,7 +1295,7 @@ export class AlertCreationWizard {
|
|||
|
||||
const destinationDropdown = this.page.locator('[data-test="alert-destinations-select"]');
|
||||
await destinationDropdown.waitFor({ state: 'visible', timeout: 10000 });
|
||||
await destinationDropdown.click();
|
||||
await openOSelectDropdown(this.page, destinationDropdown);
|
||||
await this.page.waitForTimeout(1000);
|
||||
|
||||
// Use popover selector for destination
|
||||
|
|
@ -1547,7 +1548,7 @@ export class AlertCreationWizard {
|
|||
// Destination (v3 uses data-test locator)
|
||||
const destinationDropdown = this.page.locator('[data-test="alert-destinations-select"]');
|
||||
await destinationDropdown.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await destinationDropdown.click();
|
||||
await openOSelectDropdown(this.page, destinationDropdown);
|
||||
await this.page.waitForTimeout(1000);
|
||||
|
||||
const visibleDestMenuAggItems = this.page.locator('[data-test$="-popover"] [data-test$="-option"]');
|
||||
|
|
@ -1747,7 +1748,7 @@ export class AlertCreationWizard {
|
|||
// Select destination (v3 uses data-test locator)
|
||||
const destinationDropdown = this.page.locator('[data-test="alert-destinations-select"]');
|
||||
await destinationDropdown.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await destinationDropdown.click();
|
||||
await openOSelectDropdown(this.page, destinationDropdown);
|
||||
await this.page.waitForTimeout(1000);
|
||||
|
||||
const visibleDestMenuPromqlItems = this.page.locator('[data-test$="-popover"] [data-test$="-option"]');
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { expect } from '@playwright/test';
|
|||
import fs from 'fs';
|
||||
import { CommonActions } from '../commonActions';
|
||||
import { AlertCreationWizard } from './alertCreationWizard.js';
|
||||
import { openOSelectDropdown } from './oselectHelpers.js';
|
||||
import { AlertManagement } from './alertManagement.js';
|
||||
import { AlertBulkOperations } from './alertBulkOperations.js';
|
||||
const testLogger = require('../../playwright-tests/utils/test-logger.js');
|
||||
|
|
@ -836,6 +837,13 @@ export class AlertsPage {
|
|||
return this.page.locator(this.locators.advancedTemplateOverrideSelect).first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the Advanced-tab template override OSelect dropdown.
|
||||
*/
|
||||
async openAdvancedTemplateOverrideSelect() {
|
||||
await openOSelectDropdown(this.page, this.getAdvancedTemplateOverrideSelect());
|
||||
}
|
||||
|
||||
// ==================== FOLDER OPERATIONS ====================
|
||||
|
||||
generateRandomString() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Helpers for interacting with the OSelect (reka-ui popover) component used
|
||||
* across the alert forms.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reliably open an OSelect dropdown given its root locator.
|
||||
*
|
||||
* OSelect forwards the consumer's `data-test` onto an inner `<button>`-trigger;
|
||||
* clicking the root wrapper does NOT toggle the reka-ui popover. The trigger can
|
||||
* also open-then-close on a single Playwright click, so we click until the
|
||||
* popover reports open (`aria-expanded="true"`).
|
||||
*
|
||||
* @param {import('@playwright/test').Page} page
|
||||
* @param {import('@playwright/test').Locator} rootLocator OSelect root, e.g. [data-test="...-select"]
|
||||
* @param {{ retries?: number, settleMs?: number }} [options]
|
||||
*/
|
||||
export async function openOSelectDropdown(page, rootLocator, { retries = 5, settleMs = 400 } = {}) {
|
||||
const trigger = rootLocator.locator('[data-test$="-trigger"]').first();
|
||||
await trigger.waitFor({ state: 'visible', timeout: 5000 });
|
||||
for (let i = 0; i < retries; i++) {
|
||||
if ((await trigger.getAttribute('aria-expanded')) === 'true') return;
|
||||
await trigger.click();
|
||||
await page.waitForTimeout(settleMs);
|
||||
}
|
||||
}
|
||||
|
|
@ -216,8 +216,8 @@ test.describe("Alerts Regression Bugs — Batch 1", () => {
|
|||
await expect(templateOverrideSelect, 'Template override select should be visible').toBeVisible({ timeout: 3000 });
|
||||
testLogger.info('✓ Template override field found');
|
||||
|
||||
// Open the select dropdown and pick a template
|
||||
await templateOverrideSelect.click();
|
||||
// Open the select dropdown and pick a template (page object clicks the OSelect trigger).
|
||||
await pm.alertsPage.openAdvancedTemplateOverrideSelect();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const templateOption = pm.alertsPage.getFirstMenuItem();
|
||||
|
|
|
|||
Loading…
Reference in New Issue