## What
Adds E2E regression coverage for the dashboard **Scheduled Reports
drawer**, verifying the two
bugs fixed in #13569.
No production code is touched — this is test-only.
## Why
#13569 (`fix: dashboard reports drawer duplicates entries and hides
reports in custom folders`)
shipped with unit-test updates only. The drawer had no E2E coverage at
all, so both regressions
could return unnoticed.
| Bug | Root cause | Fix under test |
|-----|-----------|----------------|
| **1. Rows duplicate on reopen** | `scheduledReports` was seeded with
the `reports` prop and `formatReports()` pushed onto it, mutating the
prop. The drawer stays mounted between opens, so each reopen multiplied
the rows. | `ScheduledDashboards.vue` now rebuilds the array with
`.map()` |
| **2. Custom-folder reports hidden** | `reports.list(org, folderId,
dashboardId)` passed the **dashboard's** folder, but `folder_id` filters
by the **report's own** folder | `ViewDashboard.vue` passes `""` so
`folder_id` is omitted |
## Tests added — 9, all passing
`tests/ui-testing/playwright-tests/Reports/scheduledReportsDrawer.spec.js`
| # | Test | Covers |
|---|------|--------|
| 1 | P0: Drawer opens and lists the dashboard's cached report |
baseline |
| 2 | P0: Bug 13569-1 — reopening the drawer does not duplicate rows |
**bug 1** — exact row count across 3 close/reopen cycles |
| 3 | P0: Bug 13569-2 — report saved in a custom report folder is listed
| **bug 2** — report in custom folder, dashboard in default folder |
| 4 | P1: Reports list request omits `folder_id` | **bug 2** — pins the
network contract the fix changed |
| 5 | P1: Switching tabs re-filters the list without duplicating rows |
`filterReports()`, the second path bug 1 corrupted |
| 6 | P1: Search filter does not survive a reopen or leave stale rows |
filter + rebuild interaction |
| 7 | P2: Dashboard with no reports shows the empty state on every open
| empty state across reopen |
| 8 | P2: A report bound to another dashboard is not listed | guards
against over-correcting bug 2 (`dashboard_id` scoping must survive) |
| 9 | Cleanup: Remove all test resources via API | teardown |
## What
Adds an end-to-end **traces SDR (Sensitive Data Redaction)** test suite,
extending SDR coverage from logs to traces. This validates the fix in
this PR branch (`feat/fix-traces-sdr-bug`) — SDR regex patterns were
previously applied to logs only; these tests assert the same policies
now apply to **trace span attributes** at both ingestion and query time.
Targets `feat/fix-traces-sdr-bug` so the tests land together with the
fix they cover.
## Tests added
**6 new spec files → 12 tests** (each spec = 1 `setup: cleanup patterns`
+ 1 combined functional test), covering **24 field-level policy
assertions** (4 sensitive fields × 6 specs). All tagged `@enterprise
@sdr @traces`.
| # | Spec | Policy | Timing | What it asserts |
|---|------|--------|--------|-----------------|
| 1 | `tracesIngestionTimeRedaction.spec.js` | Redact | Ingestion |
Span-attribute values matching the pattern are stored as `[REDACTED]` |
| 2 | `tracesQueryTimeRedaction.spec.js` | Redact | Query | Stored
values are untouched; the search response returns `[REDACTED]` |
| 3 | `tracesIngestionTimeDrop.spec.js` | Drop | Ingestion | Matching
fields are removed from the record at write time |
| 4 | `tracesQueryTimeDrop.spec.js` | Drop | Query | Fields present in
storage are dropped from the search response |
| 5 | `tracesIngestionTimeHash.spec.js` | Hash | Ingestion | Matching
values are stored as `[REDACTED:<hash>]` |
| 6 | `tracesQueryTimeHash.spec.js` | Hash | Query | Search response
returns `[REDACTED:<hash>]`; storage untouched |
Each combined test drives the full flow for **4 fields / patterns**:
- **email** (`user_email` = `john.doe@example.com`) —
`^[\w\.-]+@[\w\.-]+\.\w{2,}$`
- **US phone** (`phone` = `5551234567`) — `^\d{10}$`
- **credit card** (`cc_number` = `1234 5678 9012 3456`) —
`^\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}$`
- **SSN** (`ssn` = `123-45-6789`) — `^\d{3}-\d{2}-\d{4}$`
(drop/hash specs use `website_url`, `user_password`, `server_ip`,
`theme_color` with URL / password / IPv4 / hex-color patterns.)
Each functional test follows: ingest → assert field visible (no pattern)
→ create 4 patterns → associate to the traces stream's fields →
ingest/re-query → assert the field is redacted / dropped / hashed.
## How it works
Traces reuse the **shared** pattern create/associate/verify flow with
logs — only the ingest and read seams differ:
- **`sdrTracesIngestionPage.js`** (new): ingests via OTLP
`/api/{org}/v1/traces` (`stream-name` header). Each test field is a span
attribute that flattens to an identical top-level field; every span also
carries an `sdr_test_id` marker for batch isolation.
- **`sdrVerificationPage` / `streamAssociationPage`**: parameterized by
`streamType` — `?type=traces` search, Traces stream-type tab selection,
and schema-field filtering so a field row in the (virtualized,
~20-field) traces schema is reliably found.
- **`apiCleanup`**: `fetchStreams` / `deleteStream` / `cleanupStreams` /
`isStreamStillDeleting` / `waitForStreamDeletion` take an optional
`streamType` (default `'logs'` — no change for existing callers).
## Artifact cleanup
- `cleanup.spec.js` sweeps `sdr_traces_*` streams via `streamType:
'traces'` (the logs sweep is `type=logs`-only and never listed them).
- `cleanupRegexPatterns` adds the `traces_` prefix.
- **Verified live**: the sweep deleted 8 leftover traces streams + 32
traces patterns; 0 remained.
## Verification
- All **6 specs / 12 tests pass** against a local enterprise build
carrying the fix.
- The existing **logs** SDR suite still passes unchanged (no regression
from the shared page-object changes).
## Companion
CI wiring is a paired o2-enterprise PR (branch `test/traces-sdr-e2e`)
that splits the SDR matrix into `SDR-Logs` and `SDR-Traces` shards so
the new specs run as their own shard.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Chaitanya Sistla <sistlachaitanya2@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
## What
Stabilizes the **Streams** shard of the alpha1 cloud E2E suite
(`playwright_alpha1.yml`) to green after the UX revamp — plus a shared
node-fetch protocol fix that unblocks ingestion for several non-Streams
shards too. Rebased on `main` (no longer stacked on #13155). Un-skips
the multistream **interesting-fields** test, and rewrites the
**extended-retention** flow for the revamped UI (page-object retained,
but the test itself is currently re-skipped — see fix 8).
## Root cause & fixes
1. **https ingestion rejected in shared fetch helpers.** `apiUtils.js`,
`apiCleanup.js`, `pipelinesPage.js`, `streamsPage.js`,
`model-pricing.spec.js` still forced an `http.Agent` on node-fetch →
`Protocol "https:" not supported` against alpha's https ingestion URL,
killing every multiselect / streamname / streaming ingestion. Replaced
the single `http.Agent` with a protocol-selecting agent (an `http.Agent`
for `http://` and an `https.Agent` for `https://`), passed as a function
so node-fetch picks per-URL. Same fix as #13155's `ingestionPage.js`.
2. **Add Stream dialog selectors** (`streamsPage.js`). The revamped form
is an `ODialog`: the panel is `add-stream-dialog`; save/cancel/close are
the ODialog-owned `o-dialog-primary/secondary/close-btn` ids (scoped
under the panel). The old `add-stream-title` / `save-stream-btn` /
`add-stream-cancel/close-btn` no longer exist on the dialog.
3. **Streams-page navigation** (`streamsFormValidationPage.js`). The
`/streams` left-nav tile is now a hover-flyout group — navigate by URL
(`/web/streams?org_identifier=…`) and wait for the Add Stream button
(rendered only after zoConfig loads, `v-if="isSchemaUDSEnabled"`) before
clicking.
4. **Casing-preservation test skipped on cloud** (`streamname.spec.js`).
Alpha runs the server default `ZO_FORMAT_STREAM_NAME_TO_LOWERCASE=true`
(local CI sets it `false`), so stream names are always lowercased there
— the feature under test is off. `test.skip(isCloudEnvironment(), …)`.
5. **TC002 cloud async-delete race** (`streamsPage.js`). A just-deleted
stream lingers "being deleted" server-side after it leaves the streams
list, so the recreate POST 400s; the create eventually goes through, so
a follow-up "already exists" is treated as created. Also re-clicks Save
when no POST fires (submit occasionally doesn't reach the form under
parallel load), asserts name/retention values stick before saving, and
adds `_waitForStreamGoneCloud` so `deleteStreamViaAPI` polls the streams
list until the stream is actually gone. Success is now signalled by the
dialog closing (the toast auto-dismisses), and both create and retention
saves capture the API response so a server-side failure shows in the
test log.
6. **streaming field-list waits** (`streamsPage.js`).
`kubernetesContainerName` filters the field list and waits for the
expand toggle before clicking — the cloud field list populates slowly.
7. **`managementPage.goToManagement` retry.** Under parallel-worker load
the first settings-nav click can land before the nav is interactive;
retry (`expect().toPass`) until the settings page renders.
8. **Un-skipped / rewritten for the revamped UI:**
- **interesting-fields** (`multiselect-stream.spec.js`): **un-skipped.**
Enable quick mode and hover the field row so the (ⓘ) toggle renders.
Locators live in the page object
(`logsPage.hoverAndClickInterestingFieldLast()` + reused
`clickLogTableColumnSource()`), not in the spec.
- **extended-retention** (`stream-settings.spec.js`): the page-object
flow was rewritten for the new date-range calendar
(`daterangecalendar-cell-*`), OTable row checkbox, and shared
`ConfirmDialog` — **but the test is currently `test.skip`ed.** Clicking
the Extended Retention tab collapses the entire Stream Detail drawer on
alpha's deployed build (DOM elements drop 274 → 2), so the picker never
renders. Verified by live DOM diff; sibling Settings-tab tests still
pass, so it's a deployed-frontend regression, not test flakiness.
Skipped with a documented reason; re-enable once the tab renders its
panel again.
9. **CI-flake stabilization pass** (`logsPage.js`, `streamsPage.js`) —
from alpha1 Streams CI run 29504364410:
- **`clickInterestingFields`** (`logsPage.js`): an instant `isVisible()`
check raced the field list re-rendering after the query completed, then
toggled quick mode (already on) which churned the utilities menu. Now
asserts quick mode on once (idempotent) and waits deterministically (20s
+ fallback) for the interesting buttons to render.
- **`navigateToExtendedRetention`** (`streamsPage.js`): replaced fixed
`waitForUI(2000)/(1000)` sleeps with real waits — schema dialog tab bar
visible, then the date-picker button visible — so "date-time-btn not
visible" can't recur.
- **`navigateToStreamExplorer` / `searchStream` /
`clickAddStreamButton`** (`streamsPage.js`): wait for the streams search
input / add-stream button to actually render before interacting instead
of a fixed 1s wait, removing the 45s click timeouts on slow CI.
## Validation
- **Local (alpha, CI conditions — 3 workers):** Streams shard green (30
passed / 2 skipped / 0 failed; TC002 stable 3/3) prior to the
extended-retention re-skip. With extended-retention now skipped (fix 8),
that test moves to the skipped column.
- **CI:**
https://github.com/openobserve/o2-enterprise/actions/runs/29328193145 ·
flake triage from run 29504364410.
## Notes
- `pipelinesPage.js` / `model-pricing.spec.js` receive the same shared
protocol fix as collateral, so a couple of non-Streams shards benefit
too.
- The extended-retention page-object rewrite (calendar / OTable /
ConfirmDialog) is kept and correct; only the test invocation is skipped
pending the alpha drawer fix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Shrinath Rao <shnath@openobserve.ai>
## Summary
Applies the same node-fetch v2 fix from PR #12799 (pipelines) to all
remaining CI jobs that show \"Premature close\" / ECONNRESET failures:
- **apiUtils.js** (`sendRequest`): adds `compress:false` +
`noKeepAliveAgent` — fixes **Streams** job
(`multiselect-stream.spec.js`, `streamname.spec.js`)
- **apiCleanup.js** (`_fetch`): same fix on the node-fetch fallback path
— fixes **Reports** job (dashboard/report API calls)
- **model-pricing.spec.js**: wraps `node-fetch` with a local safe-fetch
shim — fixes **GeneralTests** job (`/llm/models` premature close)
- **streamsPage.js**: replaces four dynamic `node-fetch` imports with a
shared `_nodeFetchSafe` helper
- **ingestionPage.js**: adds `fetchWithRetry` around native fetch to
handle transient `ECONNRESET`/premature close in `beforeEach` ingestion
**SDR fix:** `regexPatternManagement.spec.js` — `AddRegexPattern.vue`
migrated to `OForm` with submit-time Zod validation
(`AddRegexPattern.schema.ts`). The `ODrawer` primary button is no longer
disabled for empty fields; validation triggers on click and keeps the
drawer open on error. Replaces stale `expect(isDisabled).toBeTruthy()`
checks with click-then-expect-drawer-still-visible assertions.
## Root cause (same as #12799)
`node-fetch` v2 defaults to `keepAlive: true` (connection pooling) and
`compress: true` (Gunzip stream). When the server closes a pooled
connection early, the Gunzip stream throws \"Premature close\". Because
the dead socket stays in the pool, retries hit the same socket.
`keepAlive: false` + `compress: false` eliminates both failure modes.
## Test plan
- [ ] GeneralTests / `model-pricing.spec.js` — no more premature close
on `/llm/models`
- [ ] Streams / `multiselect-stream.spec.js` + `streamname.spec.js` — no
more premature close on ingestion
- [ ] Reports / `reportsScheduleNow.spec.js` — no more premature close
during beforeEach ingestion
- [ ] SDR / `regexPatternManagement.spec.js` — validation test passes
with updated assertion
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary
- **13 Playwright E2E journey tests** for the Model Pricing feature
(\`/settings/model_pricing\`), consolidating all P0–P2 scenarios into
journey-based flows
- New page object \`ModelPricingPage\` under \`pages/generalPages/\`
- API cleanup integrated into the centralized \`APICleanup\` class and
called from \`cleanup.spec.js\`
- CI matrix updated: \`ZO_MODEL_PRICING_ENABLED=true\` env var added;
\`model-pricing.spec.js\` added to the \`GeneralTests\` job
- **Bug fix**: \`waitForBuildTabLoaded\` now polls the Monaco editor for
non-empty content (Phase 3), fixing a timing race where Build tab SQL
tests read an empty query string on slower CI machines
## Test coverage
| Journey | Scenarios covered |
|---------|------------------|
| List, tabs & search | Controls, tab switching, search, built-in tab |
| Create & validation | All form validation cases + successful save |
| Edit, cancel & delete | Full lifecycle |
| Duplicate & clone | Org model duplicate + built-in clone |
| Bulk actions | Select, export JSON, bulk delete |
| Toggle | Disable/re-enable with correct visual state |
| Test match dialog | Empty state, no-result, clear, match result |
| Import | Valid JSON, correction flow, cancel |
| Editor features | Multi-tier, pricing template, pattern examples |
| Pricing drawer | Overflow link → drawer with all price keys |
| Empty state | CTA when org has no custom models |
| Cost applied | LLM span matched → cost stored correctly |
| No matching model | Unknown model name → zero cost stored |
## Bug fix: Build tab query editor timing
\`waitForBuildTabLoaded\`'s Phase 2 (chart-type-selected signal) fires
as soon as \`initializeFromQuery\` sets the chart type — before
\`makeAutoSQLQuery\` has run. On slower CI machines this left
\`queries[0].query\` empty when tests read the editor, causing the "SQL
ON + Auto mode" and "Auto → Custom" tests to receive \`""\` instead of
generated SQL.
Phase 3 polls the Monaco editor
(\`[data-test="logs-search-bar-query-editor"]\`) for non-empty content,
confirming \`onBuildQueryGenerated\` has been called and the query is
ready.
## Test plan
- [x] All 13 model pricing tests pass locally
- [x] \`logsQueryBuilder-editor.spec.js\` (23 tests) — all pass with
Phase 3 fix applied
- [x] Sentinel code audit passed (no blocking issues)
- [x] API cleanup added to \`cleanup.spec.js\` via
\`apiCleanup.cleanupModelPricingModels()\` — 404-safe for instances
where the feature is disabled
🤖 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
- **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
- Make all 8 Alerts spec files cloud-compatible for alpha1 environment
- Replace `process.env.ORGNAME` with `getOrgIdentifier()` from
cloud-auth.js
- Replace `getAuthToken()` (email:password) with `getAuthHeaders()` for
cloud passcode-based auth in 3 files with API calls
(alerts-scheduled-features, alerts-incident-correlation,
alerts-vrl-encoding)
## Test plan
- [ ] All existing self-hosted E2E tests still pass
- [ ] Alpha1 cloud E2E Alerts shard passes
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Shrinath Rao <undefined@users.noreply.github.com>
## Summary
- Add enrichment table cleanup patterns for orphaned RBAC test data:
- `viewer_created_et_*`, `partial_access_et_*`, `health_check_*`
- `enrich_basic_*`, `enrich_duplicate_*`, `enrich_invalid_*`,
`enrich_protocols_*`
- `enrich_table_*`, `enrich_update_append_*`, `enrich_update_replace_*`
- `editor_create_test_*`
- Add alert cleanup prefixes for RBAC test alerts:
- `user_delete_test_*`, `user_update_test_*`
- `viewer_delete_test_*`, `viewer_update_test_*`
- `editor_create_test_*`, `editor_delete_test_*`
- Add stream cleanup patterns: `backfill_source_*`, `backfill_dest_*`
- Add log response body on URL enrichment table fetch failure for
debugging
- Fix precise regex for cleanup-only detection in global-setup.js
- Fix null check before Object.keys() in cleanupUrlEnrichmentTables
## Why
These patterns clean up orphaned test data from o2-enterprise RBAC tests
when individual test teardown fails due to:
- Test crashes/failures mid-execution
- CI/CD timeouts killing jobs before teardown
- API deletion failures during teardown
The Playwright cleanup.spec.js serves as a safety net for all orphaned
data.
## Test plan
- [x] Patterns validated against actual orphaned data on
dev2.internal.zinclabs.dev
- [x] Source tests identified in o2-enterprise RBAC test files
## Summary
- Adds E2E tests for Correlation Settings page (#9790)
- Fixes CI failure when TestDino rerun optimization skips tests
## CI Fix Details
### Problem
When TestDino's rerun optimization skips tests (because they already
passed in a previous run), the `merge_and_upload_reports` job was
failing:
1. Tests skip → no blob reports uploaded
2. Merge step found no artifacts, checked job status, saw all succeeded
3. Old code just did `exit 0` without creating `report.json`
4. Upload step failed: "JSON report not found"
This happened on:
- https://github.com/openobserve/openobserve/actions/runs/21205291873
- https://github.com/openobserve/openobserve/actions/runs/21207884853
### Root Cause
The TestDino rerun optimization works across different `run_id`s (based
on cache), not just attempts. So even a "fresh" run (attempt 1) can have
all tests skip if a previous run for the same PR/branch cached that all
tests passed.
### Fix
1. **Merge Reports step**: Create empty `report.json` and HTML when all
tests skip (aligns with ENT repo which already has this fix)
2. **Cache step**: Changed error message to notice for graceful handling
3. **Upload step**: Added safety check to skip if `report.json` doesn't
exist
## Test plan
- [x] Correlation Settings E2E tests pass locally
- [ ] CI workflow handles rerun scenarios gracefully
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Add regex pattern `/^destination\d{1,3}$/` to alert destinations
cleanup in `cleanup.spec.js`
- Update pipeline destinations pattern from `\d{2,3}` to `\d{1,3}` to
cover 1-3 digits
- Update `apiCleanup.js` `completeCascadeCleanup()` to support both
string prefixes and RegExp patterns
This cleans up leftover test destinations like `destination4`,
`destination44`, `destination444`, etc.
## Changes
### cleanup.spec.js
- Added `/^destination\d{1,3}$/` pattern to alert destinations array
(line 35)
- Updated pipeline destinations pattern to `/^destination\d{1,3}$/`
(line 128)
### apiCleanup.js
- Updated `completeCascadeCleanup()` to handle both string prefixes and
RegExp patterns in `destinationPrefixes` parameter
- Updated JSDoc to reflect new parameter type: `Array<string|RegExp>`
- Filter logic now checks `instanceof RegExp` to use `.test()` for regex
or `.startsWith()` for strings
## Test plan
- [x] Verified patterns match intended destination names
(destination1-999)
- [ ] Run cleanup spec to verify alert destinations are deleted
- [ ] Run cleanup spec to verify pipeline destinations are deleted
- Add delete_all=true parameter for complete stream deletion
- Change error return format to use 'message' field (consistent with logs cleanup)
- Ensures metrics cleanup matches logs cleanup pattern
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add validation to ensure patterns array is not empty before attempting
to clean up metrics streams. This prevents accidental deletion of all
metrics streams if the method is called without proper patterns.
Safety improvement for cleanupMetricsStreams() method.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add metrics-specific cleanup methods to handle test metrics data:
- Add fetchMetricsStreams() to fetch metrics streams via API
- Add deleteMetricsStream() to delete individual metrics streams
- Add cleanupMetricsStreams() to clean up test metrics streams
Update cleanup.spec.js to include metrics cleanup:
- Clean up test metrics streams matching patterns
- Protect 'default' metrics stream (primary test stream)
- Support patterns: test_*_metrics, e2e_metrics_*, otlp_test_*, etc.
This ensures metrics test data is cleaned up between test runs,
similar to existing logs stream cleanup.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
## Summary
- Add unique testRunId to pattern and stream names for test isolation
during parallel execution
- Add retry logic to `checkPatternExists` for backend indexing delays (3
attempts with 2s wait)
- Add search box filtering in `selectStream` for reliable stream
selection in long lists
- Add retry logic for Stream Detail button in stream association page
- Fix ingestion retry with exponential backoff for "stream being
deleted" errors
- Update regexPatternManagement test with unique pattern names to avoid
conflicts
## Test plan
- [x] All 23 SDR tests pass reliably in parallel execution
- [x] Verified tests pass when run individually and as a suite
- [x] No regressions in other test suites