From 8da11deec7d1898a01866f3ea697ec0bab5fbb35 Mon Sep 17 00:00:00 2001 From: Shrinath Rao Date: Thu, 23 Jul 2026 16:04:55 +0530 Subject: [PATCH] test(logs): heal Bug 9724 JSON-tab-default flake with retrying data-state assertion (#13407) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What Heals the flaky **Logs-Regression** spec `Log detail sidebar opens with JSON tab by default (Bug #9724)`, which failed the scheduled main regression run [29990712453](https://github.com/openobserve/openobserve/actions/runs/29990712453) (and its re-run) on all retries. ## Root cause `logsPage.verifyJsonTabSelectedByDefault()` read the Reka `OTab` (`TabsTrigger`) `data-state` attribute with a **one-shot** `.evaluate(el => el.getAttribute('data-state') === 'active')`. `DetailTable.vue` is loaded via `defineAsyncComponent`, and its tabs moved to Reka UI in the design-token migration (13173). On drawer open, the trigger can render a tick before Reka's reactive `data-state` settles to `active`. A raw `getAttribute` read does **not** auto-retry, so under CI load it captured the pre-settle value and failed. JSON **is** the genuine product default (`DetailTable.vue` `tab = ref(initialTab || "json")`, `SearchResult.vue` `detailTableInitialTab = "json"`) — this is a load flake, not a product regression. ## Fix Replace the one-shot reads with the auto-retrying `expect(tab).toHaveAttribute('data-state', 'active', { timeout: 10000 })` pattern already used elsewhere in the same page object (regex-pattern / builder-type toggles), across all three tab-verify helpers: - `verifyJsonTabSelectedByDefault()` - `verifyTableTabSelected()` - `verifyJsonTabSelected()` Test-only change; no product code touched. ## Verification Local run against `localhost:5080`: ``` npx playwright test playwright-tests/RegressionSet/Logs/logs-regression.spec.js \ -g "Bug #9724" --project=chromium --repeat-each=3 # 3 passed (16.9s) ``` The single spec exercises all three healed helpers (default-JSON at steps 3 + reopen, Table tab at step 6, JSON switch-back at step 7). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 --- tests/ui-testing/pages/logsPages/logsPage.js | 22 +++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/ui-testing/pages/logsPages/logsPage.js b/tests/ui-testing/pages/logsPages/logsPage.js index 1ef899f610..d9d8882a17 100644 --- a/tests/ui-testing/pages/logsPages/logsPage.js +++ b/tests/ui-testing/pages/logsPages/logsPage.js @@ -3405,9 +3405,13 @@ export class LogsPage { const jsonTab = this.page.locator(this.logDetailJsonTab); await expect(jsonTab).toBeVisible(); - // Check if JSON tab is selected (has data-state="active" for Reka OTab) - const isJsonTabActive = await jsonTab.evaluate(el => el.getAttribute('data-state') === 'active'); - expect(isJsonTabActive, 'JSON tab should be selected by default (Bug #9724)').toBe(true); + // The Reka OTab (TabsTrigger) carries data-state="active" when selected. The + // DetailTable drawer is an async component, so on open the trigger can render a + // tick before Reka's reactive data-state settles to "active". A one-shot + // getAttribute read does NOT retry and flakes under CI load, so poll with + // toHaveAttribute, which auto-retries until the attribute settles (Bug #9724). + await expect(jsonTab, 'JSON tab should be selected by default (Bug #9724)') + .toHaveAttribute('data-state', 'active', { timeout: 10000 }); // Verify JSON content is visible await expect(this.page.locator(this.logDetailJsonContent)).toBeVisible(); @@ -3452,8 +3456,10 @@ export class LogsPage { */ async verifyTableTabSelected() { const tableTab = this.page.locator(this.logDetailTableTab); - const isTableTabActive = await tableTab.evaluate(el => el.getAttribute('data-state') === 'active'); - expect(isTableTabActive, 'Table tab should be selected').toBe(true); + // Poll data-state via toHaveAttribute (auto-retries) rather than a one-shot + // getAttribute read, so the Reka tab-switch reactive update can settle under CI load. + await expect(tableTab, 'Table tab should be selected') + .toHaveAttribute('data-state', 'active', { timeout: 10000 }); await expect(this.page.locator(this.logDetailTableContent)).toBeVisible(); testLogger.info('✓ Table tab is selected and content is visible'); } @@ -3464,8 +3470,10 @@ export class LogsPage { */ async verifyJsonTabSelected() { const jsonTab = this.page.locator(this.logDetailJsonTab); - const isJsonTabActive = await jsonTab.evaluate(el => el.getAttribute('data-state') === 'active'); - expect(isJsonTabActive, 'JSON tab should be selected').toBe(true); + // Poll data-state via toHaveAttribute (auto-retries) rather than a one-shot + // getAttribute read, so the Reka tab-switch reactive update can settle under CI load. + await expect(jsonTab, 'JSON tab should be selected') + .toHaveAttribute('data-state', 'active', { timeout: 10000 }); await expect(this.page.locator(this.logDetailJsonContent)).toBeVisible(); testLogger.info('✓ JSON tab is selected and content is visible'); }