Files
openobserve/tests/ui-testing/playwright-tests/GeneralTests/languageTranslation.spec.js
T
Vamsi Karthik RandClaude Opus 4.8 fddf2cf264 test(e2e): stabilize alpha1 SDR, GeneralTests & Metrics shards (stream/pattern-readiness + langTranslation OOM + Reka-table & editor races) (#13259)
## What

Stabilizes the **SDR**, **GeneralTests** and **Metrics** shards of the
alpha1 cloud
E2E suite (`playwright_alpha1.yml`) to green — the last three shards
remaining after
the rest of the suite was greened. Rebased on `main`.

The original failing run had, across these shards: **SDR** 1 hard fail +
1 flake,
**GeneralTests** 21 fails + 2 flakes, **Metrics** a load-sensitive
query-persistence
flake. Root causes were cloud data/UI-readiness races (freshly-created
streams &
regex patterns lagging their list/table; browser OOM under parallelism;
revamped Reka
UI re-rendering mid-interaction), all fixed with deterministic waits on
real signals.

**No `waitForTimeout` as a fix, no `force:true`, no `.first()`/`.nth()`
band-aids, no
retry-count bumps to hide failures, no weakened assertions. No
worker-count,
parallelism, playwright-config or CI/yml changes** — test code only.

## Root cause & fixes

**SDR**

1. **`scrollIntoViewIfNeeded` 45s timeout** (`multipleSDRPatterns`,
`queryTimeDrop`).
The revamped Reka streams/schema table re-renders rows mid-animation, so
the
scroll's stability polling spun to the 45s action timeout even though
the element
was visible. Guard with `expect(el).toBeVisible()` + an instant native
`scrollIntoView`; removed the trailing sleeps.
(`streamAssociationPage.js`)

2. **Stream Detail `click()` 45s timeout.** One-shot JS-then-Playwright
click raced the
re-rendering row. Replaced with a `toPass` retry that re-resolves the
button fresh,
   fires a native DOM click, and verifies the detail sidebar opened.

3. **Regex-pattern create→list eventual consistency** (6 combined tests:
`ingestionTime*`,
`queryTime*`). Create is accepted (`verifyPatternCreatedSuccess` passes)
before it
   propagates to the list read-replica, so the UI text-count check threw
"not found in list". Gate on the backend source of truth:
`waitForPatternCreated`
   polls `GET /re_patterns` until present then confirms the UI rendered;
`waitForPatternDeleted` fixes the symmetric "Unable to delete … Reason:
unknown"
   delete race. (`sdrPatternsPage.js`)

4. **Freshly-ingested stream lags the `/streams` table**
(`multipleSDRPatterns` @slow).
`openStreamDetail` reloads + re-searches until the stream's row appears
(bounded),
instead of a one-shot 5s wait. (Local-caught gotcha:
`isVisible({timeout})` does
   **not** auto-wait — switched to `waitFor({state:'visible'})`.)

5. Transient cloud-gateway **connection timeouts** on `page.request`
pattern calls wrapped
   in a connection-error-only retry.

**GeneralTests**

6. **cipherKeys ×6 — tab never visible.** Cipher Keys shares the exact
`visible: isEnt`
gate as Regex Patterns (`settings/index.vue`), and SDR's regex
management passes on
this same cloud env — so the tab **does** render; the test was clicking
the Settings
menu, which lands on the SectionHub where per-tab data-tests aren't
rendered. Fixed
by a **direct `goto('/web/settings/cipher_keys')`**, mirroring the
working regex page.
   (Not skipped — that would have masked a real, fixable nav bug.)

7. **enrichment ×7 — `pipeline-section-tab-enrichmentTables` 45s
force-click.** The tab
only mounts after the pipelines page header renders; the
flyout→pipelines→section-tab
nav is fragile under load. Replaced with direct SPA nav to the
enrichment-tables route
+ `goto` fallback + a `toPass` settle-retry Add-button click.
(`pipelinesPage.js`)

8. **languageTranslation ×8 + landingPage ×1 — browser OOM cascade**
("Target page/context/
browser has been closed"). 10 exhaustive ~27-page full-app crawls ran
`mode:parallel`
under `--workers=5`; a worker's browser was OOM-killed and every test
after it
cascaded. **Kept parallel** (serializing overran the shard timeout) —
the crawl now
navigates `waitUntil:'domcontentloaded'` + a bounded settle instead of
waiting up to
10–30s for `networkidle` on chart/websocket-heavy pages, cutting each
heavy page's
peak-memory dwell ~10s→~3s (so 5 concurrent crawls no longer spike
together) and making
each crawl ~3–4× faster. Added fail-fast on a closed page/context so any
residual crash
   surfaces at its true origin instead of being swallowed/retried.

9. **schema ×2 — `selectStream` can't find just-created
`test1`/`test3`.** Local reproduction
proved the root cause: the **fixed** stream names hit `400 "stream is
being deleted"`
(a prior run's cleanup still finishing) → the stream got no data → never
listed. Fixed
with **unique per-invocation stream names**; also hardened the ingestion
helper
(status-check + transient retry) and added a streams-API readiness gate
before
   `selectStream`. (`schema.spec.js`)

10. **enrichment `@upload` ×2 — `_search` `waitForResponse` timeout.**
The 30s search wait
was armed **before** the up-to-120s `selectStream`, so it expired
mid-selection. Re-armed
it (200-gated) immediately before `applyQuery`, plus a streams-API
readiness gate for
`e2e_automate`. `schemaload` gated on the `streams?type=logs` response
before reload.

**Metrics**

11. Replaced `waitForTimeout`s in `metricsPage.js` with real signals
(`data-selected="true"`,
`data-state="on"`) and fixed a reka `OToggleGroupItem` state-detection
bug (active state
    is `data-state="on"`, not a `selected` class).

12. **`metrics-promql-query-persistence` load-sensitive flake.**
`selectFirstStream` returned
before the async auto-populate finished, and persistence tests read the
query editor
before Monaco re-rendered after tab switches. Added editor-readiness
gates on real
    signals (auto-populated query present; Monaco mounted + laid out) in
    `metricsQueryEditorPage.js`; assertions unchanged.

## Validation

- **CI — SDR / GeneralTests / Metrics green (alpha cloud):**
  https://github.com/openobserve/o2-enterprise/actions/runs/29633444186
- **Original failing run:**
https://github.com/openobserve/o2-enterprise/actions/runs/29481437880
- **Local (alpha cloud, CI conditions, single-worker):** each
previously-failing test re-run
  to green — `schema.spec.js` 3/3, `multipleSDRPatterns.spec.js` 2/2.

## Notes

- 21 test files change (8 page objects + 13 specs). No shared
cleanup/setup, config, or
  workflow files touched.
- RegressionSet was unaffected by this branch — a transient hang in the
workflow's
"pre-test cleanup" step (before any test runs), unrelated to these
changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 05:45:02 +00:00

59 lines
2.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Language Translation Coverage Tests
*
* Tests translation coverage for all supported languages. Runs in parallel.
*/
const { test, expect, navigateToBase } = require('../utils/enhanced-baseFixtures.js');
const testLogger = require('../utils/test-logger.js');
const PageManager = require('../../pages/page-manager.js');
// Keep the 10 language cases running in parallel (fast, fits the shard timeout).
// The OOM cascade seen in run 29481437880 (a worker browser process killed →
// "Target page, context or browser has been closed" across 8 cases) is addressed
// WITHOUT serialising: the crawl (languagePage.js) now navigates with
// `waitUntil:'domcontentloaded'` + a bounded settle instead of waiting up to 10–30s
// for `networkidle` on chart/websocket-heavy pages. That cuts each heavy page's
// live-at-peak-memory dwell from ~10s to ~3s (so 5 concurrent crawls are far less
// likely to spike memory simultaneously) and makes each crawl ~3–4× faster. The
// fail-fast on a closed page/context (languagePage.js / landingPage.spec.js) stays
// as defence-in-depth so any residual crash surfaces at its true origin.
test.describe.configure({ mode: 'parallel' });
const languages = [
{ code: 'de', name: 'German (Deutsch)', tag: '@de' },
{ code: 'es', name: 'Spanish (Español)', tag: '@es' },
{ code: 'fr', name: 'French (Français)', tag: '@fr' },
{ code: 'it', name: 'Italian (Italiano)', tag: '@it' },
{ code: 'nl', name: 'Dutch (Nederlands)', tag: '@nl' },
{ code: 'pt', name: 'Portuguese (Português)', tag: '@pt' },
{ code: 'tr-turk', name: 'Turkish (Türkçe)', tag: '@tr' },
{ code: 'ja', name: 'Japanese (日本語)', tag: '@ja' },
{ code: 'ko', name: 'Korean (한국어)', tag: '@ko' },
{ code: 'zh-cn', name: 'Chinese Simplified (简体中文)', tag: '@zh' },
];
for (const { code, name, tag } of languages) {
test(`${name} translation coverage`, {
tag: ['@languageTranslation', '@P1', tag]
}, async ({ page }) => {
test.setTimeout(360000);
await navigateToBase(page);
const pm = new PageManager(page);
await pm.languagePage.navigateToHome();
const result = await pm.languagePage.testLanguageTranslation(pm, code, true);
await pm.languagePage.resetToEnglish(pm);
// Log result with status
const statusMsg = result.status === 'ideal' ? 'PASS (ideal)'
: result.status === 'acceptable' ? 'ACCEPTABLE (needs work)'
: 'FAIL';
testLogger.info(`\n${name.toUpperCase()} RESULT: ${result.overallPercentage}% - ${statusMsg}`);
// Test passes if coverage >= acceptable minimum (ideal - delta)
expect(result.overallPercentage,
`${name} translation coverage should be >= ${pm.languagePage.getAcceptableMinCoverage()}%`)
.toBeGreaterThanOrEqual(pm.languagePage.getAcceptableMinCoverage());
});
}