## Summary
- Fixes the `Invalid PromQL syntax error handling` test failing in
enterprise CI
- Enterprise CI renders the no-data/error state slower than the 3s fixed
timeout used previously
- Replaced `isVisible({ timeout: 3000})` with `expect.poll` (10s window,
500ms–2s intervals) so the assertion is real but tolerates CI rendering
lag
## Root cause
When `sum(rate(` is entered and applied, the UI renders a no-data
indicator asynchronously. Locally (enterprise) this appears in ~2s. In
enterprise CI (slower hardware, more features enabled) it takes longer
than 3s, causing all three indicator checks to return `false` before
they appear.
## Test plan
- [x] Passes locally: `hasNoData=true` confirmed
- [ ] Enterprise CI Metrics shard goes green
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary
Two independent improvements to the Playwright E2E test suite.
---
### Part 1 — Sentinel audit fixes (original PR scope)
Fixes from the Sentinel audit review of PR #12358 (selector drift
stabilization).
- **Dead code removal**: delete `clickJobID()` from `logsPageEP.js`
(unreachable code containing `console.log`); remove unused `chromium`
import
- **Critical fix**: replace `console.log`/`console.error` in
`decryptLogSQL()` with `testLogger` equivalents
- **POM compliance**: replace raw `page.locator()` call in
`alerts-ui-operations.spec.js` `beforeEach` with
`pm.alertsPage.isIncidentsFeatureEnabled()`; add that method to
`alertsPage.js`
- **POM compliance**: move per-test `const pm = new PageManager(page)`
into `beforeEach` in `service-graph.spec.js`; replace raw
`page.waitForLoadState()` with
`pm.serviceGraphPage.waitForGraphReload()`; add `waitForGraphReload()`
to `serviceGraphPage.js`
- **Inline selector cleanup**: move metrics tab inline string literals
in `serviceGraphPage.js` into constructor properties
- **Tagging**: add
`@cipherKeys/@enterprise/@P1/@P2/@negative/@validation` to all 6 tests
in `cipherKeys.spec.js` (were untagged); add `@P1/@P2` to all 5 tests in
`regexPatternManagement.spec.js`
- **ESM fix**: correct `export const path = require('path')` → `import
path from 'path'` in `logoManagementPage.js`
- **Deduplication**: consolidate
`createFirstFunction`/`createSecondFunction` into shared
`createFunction(name, vrlCode)` in `pipelinesEP.js`
---
### Part 2 — Parallelize Metrics E2E shard
**Problem**: The `e2e / Metrics` CI shard was consistently the slowest
job at ~22 minutes per PR run, while all other shards complete in ~5-7
minutes.
**Root cause**: 9 of 11 Metrics spec files used
`test.describe.configure({ mode: 'serial' })` because they shared a
describe-scope `let pm` variable reassigned in `beforeEach`. This forced
every test in those files onto a single Playwright worker, eliminating
all parallelism despite `fullyParallel: true` and 5 workers being
configured.
**Fix applied to all 9 affected files** (`metrics.spec.js`,
`metrics-config.spec.js`, `metrics-config-tabs.spec.js`,
`metrics-visualizations.spec.js`,
`metrics-promql-query-persistence.spec.js`,
`metrics-table-column-order.spec.js`, `metrics-queries.spec.js`,
`metrics-aggregations.spec.js`, `metrics-advanced.spec.js`):
- Remove `test.describe.configure({ mode: 'serial' })`
- Replace shared `let pm` + `beforeEach` pattern with a `setupTest(page,
testInfo)` helper that creates and returns a fresh `PageManager` per
test — the same pattern already used in `metrics-promql-builder.spec.js`
(the one file that was already parallel)
- `metrics-table-column-order.spec.js`: pass `pm` explicitly into
`setupTableChart(pm, page, mode)` since it can no longer close over a
describe-scope variable
- Split consolidated mega-tests (for-loops over multiple independent
scenarios) in `metrics-queries`, `metrics-aggregations`, and
`metrics-advanced` into individual `test()` blocks so Playwright can
distribute them across workers
**No test assertions, selectors, query logic, or validation changed.**
| File | Tests before | Tests after |
|---|---|---|
| `metrics.spec.js` | 10 (serial) | 10 (parallel) |
| `metrics-config.spec.js` | 2 (serial) | 2 (parallel) |
| `metrics-config-tabs.spec.js` | 3 (serial) | 3 (parallel) |
| `metrics-visualizations.spec.js` | 4 (serial) | 4 (parallel) |
| `metrics-promql-query-persistence.spec.js` | 6 (serial) | 6 (parallel)
|
| `metrics-table-column-order.spec.js` | 20 (serial) | 20 (parallel) |
| `metrics-queries.spec.js` | 4 mega-tests (serial) | 12 individual
(parallel) |
| `metrics-aggregations.spec.js` | 3 mega-tests (serial) | 10 individual
(parallel) |
| `metrics-advanced.spec.js` | 4 mega-tests (serial) | 12 individual
(parallel) |
**Expected impact**: ~1300s (~22 min) → ~300-400s (~5-7 min) wall-clock
time.
---
## Test plan
- [ ] All 40 tests in the 4 Sentinel-audit spec files enumerate cleanly
via `npx playwright test --list`
- [ ] Tag filters `@cipherKeys`, `@P2`, `@sdr` match expected tests
- [ ] All Metrics spec files enumerate cleanly with no serial mode
warnings
- [ ] Metrics shard CI time drops to ~5-7 min on next PR run
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace Quasar-based selectors with O2 component equivalents across
alerts, dashboard, logs, and streams page objects. Key changes:
- OSwitch: target -btn suffix on inner button
- OSelect: use -trigger/-popover/-option suffixes, fallback to
[role="option"][data-test-value] when parent has no data-test
- OCombobox: use placeholder-based locators where no data-test exists
- OInput: descendant input selectors, pagination text format handling
- OTable: custom bottom slot pagination format ("N Stream(s)")
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: ktx-akshay <akshay.patil@kiara.tech>
## Summary
Design at:
https://github.com/openobserve/designs/blob/main/infrastructure/bloomfilter/DESIGN.md
A bloom-filter pruning layer that sits **between `file_list` and
tantivy** in the search path. It drops candidate files before any `.ttv`
is opened, for **positive equality / IN** lookups on high-cardinality
fields (`trace_id`, `request_id`, …).
It is built **on top of** tantivy: the `.bf` is constructed by iterating
the tantivy term dictionary, so a field must be a tantivy secondary
index (`index_fields`) **and** opted into `bloom_filter_fields`. Only
the intersection is built — a bloom-only field produces nothing. To make
that intersection non-empty by construction, enabling a field for bloom
now folds it into `index_fields` automatically (see Config). Values are
not inspected; the operator chooses which fields are worth it (see
guidance below).
Design notes live in the module-level docs under `src/infra/src/bloom/`
(`mod.rs`, `writer.rs`, `reader.rs`, `sbbf.rs`).
## Design
- **Transposed (block-major) `.bf` layout.** All files in a `.bf` share
`num_blocks = B`, so `block_index = fastmap(hash(value), B)` is
identical across files and the blocks a query needs form **one
contiguous row**. The search side reads **one `M × 32`-byte row per
`.bf`** to answer membership for all `M` files — prune cost is
`O(groups)`, not `O(files)`. (`infra::bloom`, own ~120-LOC SBBF over
gxhash64.)
- **Sub-grouping.** A hour's new files are sorted by record count and
split into chunks of ≤ `ZO_BLOOM_FILTER_MAX_FILES_PER_BF` (default 256),
one `.bf` each. Bounds compactor build memory (`M × B × 32`) and `.bf`
object size; query reads become `ceil(files / 256)` rows.
- **Footer-only reader + batched fetch.** Footer (≈ `M × 12` B) comes
from `BLOOM_FOOTER_CACHE` or one 16 KB suffix GET (with a precise
re-read when a large footer overflows the probe); rows are pulled with
one `cache_storage::get_ranges` call. `cache_storage` was reworked to do
real batched cache reads (memory: 1 lookup + N slices; disk: 1
`File::open` + N `pread`).
- **B sizing.** `num_blocks_for(max_records_in_chunk,
ZO_BLOOM_FILTER_FPP)` (default fpp `0.01`) — record count is a safe NDV
upper bound, so the SBBF never saturates for high-cardinality fields.
- **Versioned, with orphan cleanup.** A file's `bloom_ver` is write-once
— a row is never re-stamped, so dumped rows keep pointing at the `.bf`
they were built into. But `bloom_ver` is **not** append-only at the
bucket level: a merge produces new output files with a fresh `bloom_ver`
and deletes the small inputs, so the old inputs' `.bf` can become
orphaned. After each merge round the compactor retires any `.bf` whose
`bloom_ver` is no longer referenced by a live `file_list` row in the
bucket (enqueued through the existing `file_list_deleted` path).
`bloom_ver` is preserved through every file_list INSERT/SELECT path
(incl. the SQLite read-cache) and the dump parquet.
- **Observability.** Prometheus metrics for prune
(`bloom_prune_keep_ratio`, `bloom_prune_duration_seconds`);
`bloom-inspect` CLI dumps a `.bf` footer (fields, B, row bytes, file
names); footer-cache hit/miss via the shared `BytesCache` tagged
metrics; `Local::get_ranges` now reports `STORAGE_READ_*` (previously
bypassed).
## When it helps (measured, S3, no disk cache)
Same stream `benchtest`, 170 files / 14.64 GB index, single matching
row. The only variable is whether the field's values are
time-correlated:
| Field | Type | tantivy only | bloom + tantivy | Outcome |
|---|---|---|---|---|
| `trace_id` (16-byte random) | random | **2584 ms** (opens all 170
`.ttv`) | 24 ms prune + 65 ms = **89 ms** | **~29× faster** |
| `request_id` (`…-7e74-…`, UUIDv7) | time-ordered | **154 ms** (sparse
index range-prunes) | 42 ms + 154 ms = **196 ms** | ~1.3× **slower** |
The whole 170-file group was answered by **one row read of 5440 bytes**
(`170 × 32`) + a cached footer.
**Guidance — enable only when all three hold (advisory; not enforced):**
1. **High cardinality** field.
2. **Random values** (not time-ordered) — so tantivy can't range-prune
and must scan every file. Time-ordered ids (UUIDv7, snowflake) are
already pruned by tantivy's sparse index in memory → bloom is pure
overhead there.
3. **Many files per hour** — hourly volume ≳ 10 ×
`ZO_COMPACT_MAX_FILE_SIZE` (≳10 `.ttv` files), so there's something to
prune. Bloom turns N file opens into one row read; at 1–2 files/hour
it's net overhead.
The 29× result above had 170 files/hour all answered by one `.bf`. ❌
Low-cardinality / non-indexed / range / `LIKE` / regex / `!=` / OR: no
effect.
## Config
- `ZO_BLOOM_FILTER_ENABLED` (default true) — global gate.
- Per stream: a field must be in **both** `index_fields` and
`bloom_filter_fields`. Adding a field to `bloom_filter_fields` auto-adds
it to `index_fields` (bloom is built on the secondary index), and the
default index fields include the default bloom fields.
- `ZO_BLOOM_FILTER_FPP` (default 0.01) — target false-positive
probability; sizes the SBBF block count (smaller fpp = fewer false
survivors, larger `.bf`). Out-of-range falls back to 0.01.
- `ZO_BLOOM_FILTER_MAX_FILES_PER_BF` (default 256) — files per `.bf`;
trades query reads vs build memory.
- `ZO_BLOOM_FILTER_DEFAULT_FIELDS` (default empty) — fields bloomed for
every stream.
- `ZO_BLOOM_FOOTER_CACHE_MAX_SIZE` (default 1% mem, clamped 32–256 MB).
Removed in this PR: `ZO_BLOOM_FILTER_DISABLED_ON_SEARCH`,
`ZO_BLOOM_FILTER_NDV_RATIO` (B is now sized from record count + fpp, not
an ndv ratio).
## Test plan
- [x] `cargo build`, `cargo clippy -p infra -p openobserve --lib -- -D
warnings`, `cargo fmt --check` clean
- [x] Unit tests: `cargo test -p infra --lib bloom`, `cargo test -p
openobserve --lib bloom`
- [x] E2E on S3 (results above): random field prunes 170→1 and is ~29×
faster; transposed read = 1 request / 5440 B per group
- [x] Reviewer: confirm gating expectations (operator opts fields in; no
auto value detection)
- [x] Test: orphan bloom: 2 * 256MB -> merge to 512MB -> merge to
1024MB, the first .bf should be deleted
- [x] Test: orphan bloom: 6 * 256MB -> merge to 1GB + 512MB -> 512 MB
merge to 1024MB, the first .bf include 2 files(1GB + 512MB), after merge
again, the first still have 2 files but one of them already deleted. we
should keep the first .bf, because still have files in use.
## Notes
- `.bf` format is `VERSION 0x01` (transposed). Not compatible with any
pre-merge experimental `.bf`; rebuild by wiping the `bloom/` dir and
resetting `bloom_ver=0`.
- Hash is gxhash64 (project-wide `config::utils::hash`), not the Parquet
spec's xxhash64 — `.bf` is internal, never read by external tools.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
- SDR Save Settings trigger point discrepency
- Edit the existing alert - Ai icon is overlapping
- On stream field Scroller is not working
- With other languages, the Side Navigation UI is broken
- Search box dont having any border (List search view )
- text area color not looks proper
- Pipeline history - pagination is not working properly
- iam page default pagination value change
## Summary
- **`--no-sandbox` / `--disable-setuid-sandbox`** added to
`chromium.launch()` in `globalSetup.js` and `launchOptions` in
`playwright.config.js` (CI-only) — prevents silent Chromium hangs on
restricted runner environments
- **`globalTimeout: 110 min`** added to `playwright.config.js` — caps
the entire suite at 110 min (10 min under the job timeout) so hung runs
fail with a clear Playwright error instead of a silent CI kill
- **`restore-keys` fallback** added to the browser cache step — a
`package-lock.json` change no longer forces a full 163 MB re-download on
every shard simultaneously
- **Runner right-sizing**: `ui_integration_tests` →
`repo-openobserve-standard-16`; `merge_and_upload_reports` +
`playwright_summary` → `repo-openobserve-standard-4`
## Test plan
- [ ] Confirm `ui_integration_tests` shards start without Chromium
launch hangs
- [ ] Confirm cache hit on second run (restore-keys fallback working)
- [ ] Confirm `merge_and_upload_reports` and `playwright_summary`
succeed on 4 GB runners
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## Summary
- Moves 3 enterprise-only tests out of OSS regression spec files into
dedicated `*-ent` spec files
- These spec files live in the OSS repo but are **not referenced in the
OSS CI workflow** — they are picked up only by the enterprise CI
- Fixes recurring failures in the OSS regression run caused by features
that don't exist in OSS builds
## Why the tests were failing in OSS
| Shard | Test | Root cause |
|---|---|---|
| Traces-Regression | Service graph side panel (Bug #11687) |
`[data-test="traces-service-graph-toggle"]` is wrapped in
`v-if="config.isEnterprise == 'true'"` in `SearchBar.vue` — element
never renders in OSS → 45s timeout |
| Logs-Regression | Scheduled Search navigation (Bug #7354) | `POST
/api/{org}/search_jobs` returns **404** in OSS — endpoint is
enterprise-only |
## Changes
**New files:**
-
`tests/ui-testing/playwright-tests/RegressionSet/logs-regression-ent.spec.js`
— Scheduled Search / `search_jobs` describe block (2 tests)
-
`tests/ui-testing/playwright-tests/RegressionSet/traces-regression-ent.spec.js`
— service graph side panel test (Bug #11687)
**Modified files:**
- `logs-regression-9044-7354.spec.js` — removed the `#7354` Scheduled
Search describe block; `#9044` scroll retention tests remain
- `traces-regression.spec.js` — removed Bug #11687 service graph test
block
The companion PR in `o2-enterprise` adds these two files to the
Logs-Regression and Traces-Regression shards of the enterprise workflow.
## Test plan
- [ ] OSS regression CI (`playwright_regression.yml`) should pass — no
more enterprise-only test failures
- [ ] Enterprise regression CI picks up `*-ent.spec.js` files via the
companion workflow PR
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary
Follow-up to #12249. The cross-type collision check in the file upload
handler passes the formatted `stream_name` to `get_url_jobs_for_table`,
but URL jobs are stored with the raw `table_name` from the HTTP path.
When names contain uppercase or special characters,
`format_stream_name("My_Table")` produces `"my_table"`, which won't
match the stored URL job name `"My_Table"` — causing the cross-type
protection to be silently bypassed.
## Fix
Changed `get_url_jobs_for_table(&org_id, &stream_name)` to
`get_url_jobs_for_table(&org_id, table_name.trim())` — matching how the
URL handler itself queries URL jobs at line 299.
## Before/After
```rust
// Before: formatted name passed to URL jobs lookup (WRONG)
get_url_jobs_for_table(&org_id, &stream_name)
// After: raw table_name passed (CORRECT, matches how URL handler queries)
get_url_jobs_for_table(&org_id, table_name.trim())
```
## Notes
- `ENRICHMENT_TABLES` cache key continues to use `stream_name`
(formatted) — that's correct
- `get_url_jobs_for_table` now uses `table_name.trim()` — matching the
URL handler at line 299
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Fixes https://github.com/openobserve/o2-enterprise/issues/1796 (item 1:
"Reload Existing URLs" returns error).
## Summary
Commit
[`85d261b5d0`](https://github.com/openobserve/openobserve/commit/85d261b5d0e4b68dbc79ca18b844fc53e2368ee9)
(vulnerability scan fixes, Apr 14 2026) removed the `!retry` guard from
enrichment table URL validation. This broke the **reload** update mode
because the frontend sends an empty URL when retrying/reprocessing
existing URLs — the backend already has them stored and just needs to
re-trigger processing.
## Root Cause
Before the breaking commit, URL validation was guarded by `!retry`:
```rust
if !retry && let Err(err_msg) = validate_enrichment_url(&request_body.url) {
return MetaHttpResponse::bad_request(err_msg);
}
```
The security fix removed the guard under the assumption that skipping
validation on retry was an SSRF bypass vector. However, the retry flow
sends `url=""` intentionally — the existing URLs are in the database.
## Fix
Re-adds the `!retry` guard around URL validation. In retry mode, URL
validation is skipped entirely (the URLs come from DB). All other modes
(create, append, replace, replace_failed) still require a non-empty,
valid URL with full SSRF protection.
## Test Plan
- [ ] Create enrichment table from URL
- [ ] Edit table → Reload existing URLs → Should succeed (no "URL cannot
be empty")
- [ ] Edit table → Add new URL → Should still validate URL format
- [ ] Edit table → Replace all URLs → Should still validate URL format
- [ ] Edit table → Replace failed URL → Should still validate URL format
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Subhradeep Chakraborty <chakrabortysubhradeep556@gmail.com>
## Summary
Adds Playwright E2E regression tests for 15 verified bug fixes. Tests
are added to the existing CI matrix files:
- 6 logs tests in `logs-regression-bugs-2.spec.js`
- 9 traces tests in `traces-regression-bugs.spec.js`
Also fixes framework compliance: all raw `page.locator()` calls moved to
page object getter methods, missing assertions added, and flaky test
logic fixed in #10595.
## Logs bugs covered
| Bug | Description |
|-----|-------------|
| #11606 | include/exclude search term gets added at incorrect position
|
| #9339 | collapse or expand the indexlist wont redraw the histogram
chart |
| #7310 | search term appended instead of replaced in streams dropdown |
| #5277 | column positions change back after re-running query |
| #4426 | text wrap toggle causes column misalignment on saved view
switch |
| #4091 | cancel query button on visualize page |
## Traces bugs covered
| Bug | Description |
|-----|-------------|
| #11816 | trace API called multiple times with auto search enabled |
| #11815 | traces not sorted correctly when sorted by spans column |
| #11531 | spans tab method column references non-existent field |
| #11446 | incorrect duration value in logs detail traces tab |
| #11384 | switching organization does not clear trace explorer results
|
| #11244 | timestamp values inconsistent between traces and logs |
| #8978 | no cancel option while running a query in traces |
| #4151 | trace values not visible on hover in dark mode |
| #2887 | traces should be orderable by duration column |
## Files changed
| File | Change |
|------|--------|
| `tests/ui-testing/pages/logsPages/logsPage.js` | 9 new getter methods
for selectors |
| `tests/ui-testing/pages/tracesPages/tracesPage.js` | 14 new getter
methods for selectors |
|
`tests/ui-testing/playwright-tests/RegressionSet/logs-regression-bugs-2.spec.js`
| 6 new tests, 0 raw locators, fixed#10595 |
|
`tests/ui-testing/playwright-tests/RegressionSet/traces-regression-bugs.spec.js`
| 9 new tests, 0 raw locators |
## Test plan
All 21 tests (15 new + 6 existing) pass against the dev environment. No
new CI config needed — both spec files are already listed in
`playwright_regression.yml`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Adds 2 new E2E regression test specs to `RegressionSet/` for recently
fixed bugs
- Adds 13 new page object methods to `logsPage.js` for scroll,
pagination, scheduled search, and sidebar navigation
https://github.com/openobserve/openobserve/issues/7354https://github.com/openobserve/openobserve/issues/9044
## Tests Added
### scroll-retention-9044.spec.js (3 tests)
- Scroll resets to top when navigating page 1 → page 2 via page number
button
- Scroll resets to top when navigating page 2 → page 1
- Scroll resets to top via Next Page (>) button
### undefined-length-7354.spec.js (2 tests)
- No "Undefined Length" error after navigating Logs → Scheduled Search →
Streams → Logs
- No console errors containing "undefined" or "length" after the
reproduction path
## CI
- Updated `playwright_regression.yml` to include both new spec files in
the `Logs-Regression` matrix
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- **Add `reportFoldersPage.js`** page object with 30+ methods for folder
CRUD, report move, search, and cross-folder toggle
- **Add `reportFolders.spec.js`** with 12 tests covering:
- **P0 Smoke**: Sidebar renders with default folder, create new folder
- **P1 Functional**: Create report via API (creates temp dashboard from
scratch), move report between folders, cross-folder search, folder
sidebar search filter
- **P2 Edge Cases**: Move button disabled when source=destination, save
disabled for empty name, cancel closes dialog, default folder has no
edit/delete options, special characters allowed in folder names
- **Cleanup**: Deletes all test reports, folders, and leaves no
resources behind
- **Add `createDashboardViaApi`** to apiCleanup.js — creates a minimal
v8 dashboard from scratch, removing dependency on pre-existing
dashboards
- **Add `createReportViaApi`**, `fetchReportFolders`,
`deleteReportFolder`, `cleanupReportFolders` methods to apiCleanup.js
- Register ReportFoldersPage in PageManager
## Approach
- Everything created from scratch — unique report via API, unique
folders via UI, all cleaned up afterward
- No dependency on pre-existing dashboards or reports
- Zero `waitForTimeout` calls — all waits use `waitForLoadState`,
`waitFor({ state: 'visible/hidden' })`, or role-based waits
- Serial execution (tests build on each other: create folder → create
report → move report → cleanup)
## Test Results
```
12 passed (2.1m)
```
## CI Integration
- Added to `.github/workflows/playwright.yml` under `Reports` testfolder
alongside existing report tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Restores `applyQueryButton` call in `initQueryBuilderTestLite` — the
initial match_all search serves as a UI priming step that ensures the
auto-search from stream selection has completed before the test runs its
own query
- Adds `runQueryAndWaitForResults` before `clickBuildToggle` in SQL OFF
mode tests — matching the flow in `setupQueryAndSwitchToBuild` so the
builder has query results to parse into filters
## Root Cause
PR #11797 moved ingestion from `beforeEach` to `beforeAll` and
introduced `initQueryBuilderTestLite` which skipped the initial
match_all search. Two issues emerged:
1. **No UI priming**: After `selectStream`, an auto-search fires
automatically. Without waiting for it to complete, the test's own query
could run while the UI was in an intermediate state, causing the builder
to parse zero filter conditions.
2. **SQL OFF tests skipped query execution**: These tests set search bar
content and clicked build toggle without running the query first. The
builder had no executed query results to parse into filters.
## Changes
| File | Change |
|------|--------|
| `queryBuilder-helpers.js` | Add `applyQueryButton(pm)` to
`initQueryBuilderTestLite` (same as full init) |
| `logsQueryBuilder-filters-advanced.spec.js` | Add
`runQueryAndWaitForResults()` before `clickBuildToggle()` in 2 SQL OFF
tests |
## Test Results
- Local (5 workers, 77 tests): **74 passed**, 3 pre-existing
intermittent failures (CTE chart type, auto-mode chart type, NOT LIKE
filter parsing)
- The 8 CI flaky tests from #11797 are all in the passing set
## Test plan
- [ ] CI: Logs-Builder-Basic and Logs-Builder-Advanced shards pass with
0 flaky tests
- [ ] All 77 QB tests pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Moves `ingestTestData` from `beforeEach` to `beforeAll` across all QB
describe blocks (one ingestion per describe instead of per test)
- For describe blocks where ALL tests call `setupQueryAndSwitchToBuild`
(run their own query), uses a lite `beforeEach` that skips the initial
`match_all` `/_search` call
- Adds `ingestForQueryBuilderTest` helper that works with Playwright's
`request` fixture (no page needed in `beforeAll`)
- Adds `initQueryBuilderTestLite` helper for describe blocks that don't
need the initial query
**Impact:** ~74 fewer redundant ingestions and ~41 fewer redundant
`/_search` calls per shard run. Estimated reduction: Logs-Builder from
~19 min to ~10-12 min.
## Files changed
| File | Change |
|------|--------|
| `queryBuilder-helpers.js` | Add `ingestForQueryBuilderTest` +
`initQueryBuilderTestLite`, remove ingestion from `initQueryBuilderTest`
|
| `logsQueryBuilder-filters.spec.js` | Split SQL OFF tests into separate
describe, add `beforeAll`, use lite init for main block |
| `logsQueryBuilder-chart.spec.js` | Add `beforeAll` to 5 describe
blocks, use lite init for Chart Type + Chart Auto-Selection blocks |
| `logsQueryBuilder-editor.spec.js` | Add `beforeAll` to 7 describe
blocks, use lite init for Bare Field Select + FieldList visibility
blocks |
## Test plan
- [ ] CI: Logs-Builder shard completes in < 13 minutes (currently ~19
min)
- [ ] All 77 QB tests pass (no regressions)
- [ ] No changes to test assertions or coverage
## Fallback
If this doesn't bring Logs-Builder below ~13 min, Plan B (4-shard split)
is documented in `tests/ui-testing/MD_Files/Logs Shard
Split/4-shard-strategy.md`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
- #11689: Service Catalog clear search filter blanks page regression
- #11687: Service graph side panel $ pattern fix verification
- Added clickServiceCatalogTab() and clickFilterClearButton() to
servicesCatalogPage
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
- #11565
Design At:
https://github.com/openobserve/designs/tree/main/dashboards/builder-tab-impr
- Implemented parseWhereClauseToFilter to convert raw WHERE clause text
into a structured filter format.
- Added extractWhereClause to retrieve the WHERE clause from a full SQL
query.
- Enhanced unit tests for both functions to cover various scenarios
including empty inputs, valid conditions, and error handling.
---------
Co-authored-by: ktx-akshay <akshay.patil@kiara.tech>
## Summary
- Added `playwright_regression.yml` with one-shard-per-spec parallelism
(11 regression specs)
- Removed `RegressionSet` shard from main `playwright.yml` (tests now
run via dedicated regression workflow)
- Added `Cache test failures to TestDino` step to regression workflow
(matching main playwright.yml)
- Uses `ubicloud-standard-8` runners for all regression jobs
## Schedule
- Auto-triggers every 4 hours starting from 9 AM IST (3:30, 7:30, 11:30,
15:30, 19:30, 23:30 UTC)
- Manual trigger via `workflow_dispatch`
## Test Plan
- [ ] Confirm `playwright_regression.yml` appears in Actions tab
- [ ] Trigger a manual run to verify all 11 regression specs run in
parallel
- [ ] Verify `playwright.yml` no longer includes RegressionSet shard
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Fixes Playwright selectors broken by the UX revamp of buttons and tabs
(PRs #11595, #11652)
- The migration from Quasar to Reka UI changed active state from CSS
`selected` class to `data-state="on"`/`data-state="active"` attributes
## Changes
- **themePage.js**: Replace broken `button[data-o2-btn]` with
`[data-test="navbar-theme-toggle-btn"]` for theme switcher
- **logsPage.js**: Replace `toHaveClass(/selected/)` with
`toHaveAttribute('data-state', 'on')` for patterns toggle
- **serviceGraphPage.js**: Same selected→data-state fix for graph/tree
view toggle buttons
- **jobScheduler.js**: Replace `getByRole('cell', ...)` with
`:visible`-filtered `[data-test="tab-more_details"]` to handle
multi-element matches from v-show
- **org.spec.js**: Increase validation message timeout from 3s to 5s
- **jobSearch.spec.js**: Add 10s wait before `viewJobDetails()` for job
processing
## Test plan
- [x] `searchPatterns.spec.js` — 15/15 passed
- [x] `theme-management.spec.js` — 5/5 passed
- [x] `jobSearch.spec.js` — 8/8 passed (parallel)
- [x] `org.spec.js` — 11/11 passed
- [x] `join.spec.js` — 12/12 passed
- [x] `logspage.spec.js` — 22/28 passed (3 pre-existing flaky, all pass
in isolation)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
Stabilises alpha1 cloud E2E tests across the Logs-Core shard. Fixes a
UI/API org mismatch root cause, adds env-aware query execution helpers,
and brings all 10 changed spec files into POM compliance.
## Root cause (original)
After Dex login, the Pinia store binds all API calls to the user's
*default* org. The URL `?org_identifier=...` alone does not update the
store. Ingestion went to the `.env` org while UI searches went to the
user's default org → empty results → cascading test failures.
## Changes
### Alpha1 environment / authentication
- **`global-setup-alpha1.js`** — switches active org via the navbar
dropdown after Dex login so the Pinia store adopts the correct org;
`context.storageState` captures the result for all test contexts
- **`playwright-alpha1.config.js`** — `ORGNAME` sourced purely from
`.env`; cloud-config override removed
- **`loginPage.login()` / `unflattened.spec.js`** — include
`?org_identifier=${ORGNAME}` in SPA navigation to prevent defaulting to
`_meta`
- **`unflattened.js openStreamDetail()`** — replaced broken
stream-name-text click with `Stream Detail` action button + Schema-tab
visibility wait
### Auto-run query handling (`auto_query_enabled` flag)
- **`logsPage.js`** — added `runQueryAfterModeChange()`: on alpha1
(`auto_query_enabled=true`) waits for the in-flight auto-query to
complete; on local triggers a fresh query. Fixes
`@interestingFieldsCRUD` and `@quickModeResults` tests that were passing
on alpha1 but failing locally because the old fix clicked Refresh
mid-auto-run (hitting Cancel)
- **`logsQueryPage.js`** — null-guard `textContent()` return in
`_toggleAutoRun()` (`|| ''`) to satisfy Playwright's `string | null`
type contract
### Merge conflict resolution
- **`logsPage.js enableQuickModeIfDisabled()`** — kept HEAD's version
that defines `quickModeIndicator` at the top of the function (used in
the retry loop); discarded main's version that opened the utilities menu
before the variable was defined
### POM compliance (Sentinel audit)
Added three new POM methods to **`logsPage.js`**:
- `watchForNotification(timeout)` — returns a promise for pre-action
race-condition-safe notification watching
- `expectNotificationContainsText(text)` — notification text assertion
- `waitForNotificationWithText(text, timeout)` — notification waiter
with text filter
Removed raw locators from spec files:
- **`logspage.spec.js`** — notification race pattern →
`watchForNotification()` + `expectNotificationContainsText()`; 5-line
raw histogram toggle block → `ensureHistogramState(true)` (POM method
already existed)
- **`logsqueries.spec.js`** —
`pm.logsPage.page.waitForSelector('.q-notification__message:has-text(...)')`
→ `waitForNotificationWithText()`
- **`jobSearch.spec.js`** — added `testLogger` import; replaced 14×
`console.log` with `testLogger.info`; raw Monaco editor locators (lines
158–168) → `logsPage.waitForQueryEditorVisible()` +
`logsPage.getQueryEditorText()` (both already in POM)
### Tags
- **`jobSearch.spec.js`** — all 8 tests now tagged: `@jobSearch,
@P0/@P1` with functional sub-tags (`@smoke`, `@crud`, `@validation`)
- **`logshistogram.spec.js`** — all 5 tests now include `@P1`
## Results
- All `logsquickmode.spec.js` tests pass on both local and alpha1
- Zero Sentinel critical issues remaining across all 10 changed spec
files
- Remaining warnings (old-style auth in `jobSearch.spec.js` /
`pagination.spec.js`, `pm.logsPage.page.reload()` in
`logsquickmode.spec.js`) are pre-existing tech debt deferred to a
separate PR
## Test plan
- [ ] Run `logsquickmode.spec.js` locally and on alpha1 — both should
pass
- [ ] Run full Logs-Core shard on alpha1: `npx playwright test --config
playwright-alpha1.config.js
playwright-tests/Logs/{join,logspage,logsquickmode,pagination,unflattened,logshistogram,jobSearch,logsqueries,logsAnalyzeDimensions}.spec.js`
- [ ] Verify global setup logs: `Switching active org to: <ORGNAME>` →
`Org switch complete`
- [ ] Confirm no `console.log` output in `jobSearch.spec.js` test run
(all replaced by `testLogger`)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Adds 18 new POM methods to `alertsPage.js` for stream-type/query-mode
coherence verification, chart state assertions, query editor
interaction, and aggregation field filtering
- Adds 5 helper methods to `alertCreationWizard.js` for full editor
open/close, stream switching, and query execution
- Adds new regression spec `alerts-stream-switching-regression.spec.js`
covering 5 closed bugs:
| Bug | Description |
|-----|-------------|
| #11580 | Metrics+PromQL -> Logs, PromQL editor persists |
| #11572 | Logs -> Metrics -> Logs, chart error "No field named value" |
| #11571 | Builder -> SQL, chart blank table instead of line |
| #11573 | Full editor open/close blanks the graph |
| #11578 | Agg functions don't filter to integer fields |
## Test plan
- [ ] Run `alerts-stream-switching-regression.spec.js` against dev
environment
- [ ] All 5 tests pass with no raw selectors in spec (POM-compliant)
- [ ] Chart assertions verify canvas child exists (not just bounding
box)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## Summary
- Enhanced existing scheduled pipeline query builder tests with exact
default query format assertions (`max(_timestamp)`, `count(_timestamp)`,
`histogram(_timestamp)`)
- Added new P2 test verifying Run Query button transitions from disabled
to enabled after stream selection and default query population
- Verifies behavior described in Issue #11575
## Test plan
- [x] All 4 tests pass (verified on test environment)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## What changed
Fixed `addFieldTerm` in `SearchBar.vue` so that include/exclude search
terms are inserted at the correct position in SQL aggregation queries.
Previously the code checked for `ORDER BY` before `GROUP BY`, causing
the injected `WHERE` clause to land after `GROUP BY` (invalid SQL). The
fix scans all terminating clauses (`GROUP BY`, `HAVING`, `ORDER BY`,
`LIMIT`) and inserts `WHERE` before whichever appears earliest. The
remaining diff is Prettier-driven reformatting with no logic changes.
## Why
The old sequential `if/else if` checked `ORDER BY` first. On a query
containing both `GROUP BY` and `ORDER BY`, it would split at `ORDER BY`
and produce `… WHERE <filter> ORDER BY … GROUP BY …` — structurally
invalid SQL. The fix enforces correct SQL clause ordering (`FROM → WHERE
→ GROUP BY → HAVING → ORDER BY → LIMIT`).
## Approach
The new algorithm iterates over all four terminating clauses, records
the index of each that is present, picks the one with the smallest index
(`firstClause`), then uses the existing `queryIndexSplit` utility to
splice the `WHERE <filter>` token in before it. If no terminating clause
exists the filter is appended. The spec file was extended with 14 new
unit tests covering the core bug scenario (GROUP BY + ORDER BY
together), each individual clause in isolation, all-clauses-present,
AND-append paths, and edge cases (case-insensitive matching, column
names containing clause keywords, special characters in filter values).
## Risk
The logic change is isolated to the `else` branch of `addFieldTerm` that
handles queries with no existing `WHERE` clause. Queries that already
have a `WHERE` clause follow a separate code path and are unaffected.
Reviewers should confirm the `queryIndexSplit` utility is
case-insensitive-safe (the fix lowercases only for the index scan, then
splits the original string) and verify the preserved trailing
`afterClause` string includes the space/newline that was previously part
of the `" order by"` / `" group by"` literals.
## Summary
- Add API tests verifying that stream settings fields (index_fields,
bloom_filter_fields, full_text_search_keys) are deduplicated when the
same field is added multiple times
- Tests cover: single field dedup, multiple fields, repeated adds (4x),
remove+re-add, empty payloads, and partial updates
- All tests use existing schema fields from the seed data stream
(`stream_pytest_data`)
## Test plan
- [x] All 10 tests pass against testing environment
- Tests run via `cd tests/api-testing && rye run pytest
tests/test_stream_settings_dedup.py -v`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Three fixes in alertCreationWizard.js:
- Align threshold operator dropdown with working SQL method pattern
(q-field__control click + role-based option + q-menu fallback)
- Narrow portal cleanup from all q-portal to q-portal--dialog only to
avoid hiding new dropdown menus
- Fix _switchToTab to target v3 inner tab divs instead of wrapper
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
- API-first methods in alertTemplatesPage.js (_findTemplateViaApi,
createTemplateViaApi, deleteTemplateViaApi) to bypass fragile UI
pagination
- API-first destination lookup in alertDestinationsPage.js
(findDestinationViaApi) resolves cascade failure
- v3-compatible locators for alert type dropdown, condition operators,
deduplication flow in alertCreationWizard.js
- Self-contained test pattern with per-test random suffixes and no
shared state
- URL-based navigation with menu fallback for templates and destinations
pages
- q-portal cleanup before click interactions to prevent interception
- Conditional enterprise feature guards at runtime
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <noreply@anthropic.com>