Files
openobserve/tests/ui-testing/playwright-tests/Logs/logsQuickPick.spec.js
T
Shrinath RaoandClaude Opus 4.8 c6b2829a5e test(autoe2e): generated E2E tests for #13025 (logs-stream-quick-pick) (#13030)
🤖 Auto-generated E2E tests for #13025 — **healed to passing** against a
live OpenObserve before this PR was opened.

- Branch `autoe2e/pr-13025` (stacked on `issue-ent-2038`), so the tests
run against the feature code and pass before it merges.
- Spec: `tests/ui-testing/playwright-tests/Logs/logsQuickPick.spec.js`

The repo Playwright CI re-validates here. Review is for **quality +
coverage** — the tests already pass.

_Generated by the E2E Council pipeline._


**Test cases added / changed:**

| Test case | Type | What it verifies |
|---|---|---|
| `should quick pick a stream from the sidebar` | new | clicking a
sidebar quick pick button selects the stream and loads the field list |
| `should show hero state on fresh arrival with no stream selected` |
new | the main content area shows both hero action cards when no stream
is selected |
| `should open stream dropdown when clicking select stream card` | new |
clicking the "Select a stream" hero card opens the stream dropdown
popover |
| `should reappear quick pick after deselecting and re-select works` |
new | after deselecting a stream the quick pick reappears and
re-selection works correctly |
| `should show more footer when org has more than 8 streams` | new | the
quick pick more footer is visible with the correct remaining count when
org has > 8 streams (skips otherwise) |
| `should select stream via hero recent chip` | new | clicking a
recent-stream chip in the hero state selects the stream and triggers
field list loading |
| `should open query guide documentation in new tab` | new | clicking
the "Read the query guide" card opens the OpenObserve docs in a new
browser tab |

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 16:40:14 +00:00

248 lines
11 KiB
JavaScript

/**
* Logs No-Stream Quick Pick — E2E suite
*
* Verifies that when a user navigates to the Logs page without a pre-selected stream,
* the UI surfaces two complementary quick-pick surfaces:
* 1. Sidebar quick pick — up to 8 one-click stream buttons (IndexList)
* 2. Hero-state quick pick — action cards + recent-stream chips (LogsNoStreamState)
*
* Test coverage:
* - TC-QP-001: Quick pick a stream from the sidebar
* - TC-QP-002: Hero state appears on fresh arrival
* - TC-QP-003: Hero "Select a stream" card opens the stream dropdown
* - TC-QP-004: Deselect a stream, quick pick reappears, re-select works
* - TC-QP-005: Quick pick "X more" footer (conditional, org must have > 8 streams)
* - TC-QP-006: Hero "Recent:" chip selects stream (gated on localStorage seeding)
* - TC-QP-007: "Read the query guide" card opens documentation in new tab
*/
const { test, expect, navigateToBase } = require('../utils/enhanced-baseFixtures.js');
const testLogger = require('../utils/test-logger.js');
const PageManager = require('../../pages/page-manager.js');
const logData = require("../../fixtures/log.json");
const { getOrgIdentifier } = require('../utils/cloud-auth.js');
test.describe("Logs No-Stream Quick Pick testcases", () => {
test.describe.configure({ mode: 'parallel' });
let pm;
test.beforeEach(async ({ page }, testInfo) => {
testLogger.testStart(testInfo.title, testInfo.file);
await navigateToBase(page);
pm = new PageManager(page);
// Navigate to logs page WITHOUT a stream query param — triggers the
// no-stream-selected state which renders both the sidebar quick pick
// and the main-content hero cards.
await page.goto(`${logData.logsUrl}?org_identifier=${getOrgIdentifier()}`);
await page.waitForLoadState('networkidle', { timeout: 30000 }).catch(() => {});
testLogger.info('Test setup completed');
});
// ── P0: Quick Pick a stream from the sidebar ────────────────────────
test("should quick pick a stream from the sidebar", {
tag: ['@logs-stream-quick-pick', '@all', '@logs']
}, async ({ page }) => {
testLogger.info('Testing quick pick stream selection from the sidebar');
// Wait for the sidebar quick pick container to become visible
await pm.logsPage.expectQuickPickContainerVisible();
// Click the quick pick button for e2e_automate
await pm.logsPage.clickQuickPickButton('e2e_automate');
// After selection the quick pick container should disappear
await pm.logsPage.expectQuickPickContainerNotVisible();
// Verify the stream dropdown now shows the selected stream name
await pm.logsPage.expectStreamDropdownShowsStream('e2e_automate');
// Wait for field list to load (or "no field found" to appear)
await pm.logsPage.waitForFieldListAfterStreamSelection();
testLogger.info('Quick pick stream selection completed');
});
// ── P0: Hero state appears on fresh arrival ────────────────────────
test("should show hero state on fresh arrival with no stream selected", {
tag: ['@logs-stream-quick-pick', '@all', '@logs']
}, async ({ page }) => {
testLogger.info('Testing hero state visibility on fresh arrival');
// Wait for the hero container to be visible in the main content area
await pm.logsPage.expectNoStreamHeroVisible();
// Assert both action cards are present
await pm.logsPage.expectSelectStreamCardVisible();
await pm.logsPage.expectQueryGuideCardVisible();
testLogger.info('Hero state verified');
});
// ── P1: Hero "Select a stream" card opens the stream dropdown ──────
test("should open stream dropdown when clicking select stream card", {
tag: ['@logs-stream-quick-pick', '@all', '@logs']
}, async ({ page }) => {
testLogger.info('Testing select stream card opens the stream dropdown');
// Hero card must be visible first
await pm.logsPage.expectNoStreamHeroVisible();
await pm.logsPage.expectSelectStreamCardVisible();
// Click the card — should trigger onSelectStream() which opens the dropdown
await pm.logsPage.clickSelectStreamCard();
// Verify the stream dropdown popover opened
await pm.logsPage.expectStreamDropdownPopoverVisible();
testLogger.info('Dropdown opened via select stream card');
});
// ── P1: Deselect, quick pick reappears, re-select works ────────────
test("should reappear quick pick after deselecting and re-select works", {
tag: ['@logs-stream-quick-pick', '@all', '@logs']
}, async ({ page }) => {
testLogger.info('Testing deselect and re-pick workflow');
// Step 1: Select a stream via quick pick
await pm.logsPage.expectQuickPickContainerVisible();
await pm.logsPage.clickQuickPickButton('e2e_automate');
await pm.logsPage.expectQuickPickContainerNotVisible();
await pm.logsPage.expectStreamDropdownShowsStream('e2e_automate');
// Step 2: Deselect the stream. The logs stream OSelect is multi-mode with
// rowClickSingleSelect, so clearing the single selection requires clicking the
// option's checkbox zone (see deselectStreamViaCheckbox), not the option row.
await pm.logsPage.deselectStreamViaCheckbox('e2e_automate');
// Step 3: Quick pick should reappear in the sidebar
await pm.logsPage.expectQuickPickContainerVisible();
// Step 4: Re-select the same stream via quick pick
await pm.logsPage.clickQuickPickButton('e2e_automate');
await pm.logsPage.expectQuickPickContainerNotVisible();
await pm.logsPage.expectStreamDropdownShowsStream('e2e_automate');
// Verify field list loads after re-selection
await pm.logsPage.waitForFieldListAfterStreamSelection();
testLogger.info('Deselect and re-pick workflow completed');
});
// ── P2: Quick pick "X more" footer (seeds > 8 streams, then verifies) ─
// QUICK_PICK_LIMIT is 8 (IndexList.vue). The quick pick caps at 8 buttons and
// shows a "Search above for N more" footer whenever the org has more than 8
// logs streams. This test CREATES 9 streams so the condition always holds, then
// asserts the cap + footer.
//
// Stream names carry a per-run unique token (e2e_qp_more_stream_<token>_N) so
// repeat/parallel runs never collide with a still-deleting same-named stream
// (stream deletion in OpenObserve is async). Freshly-ingested streams have no
// stats yet, so they sort to the bottom of the quick pick and never displace
// already-active streams (e.g. e2e_automate) that sibling tests rely on. The
// seeds are swept by cleanup.spec.js via the `e2e_qp_more_stream_` prefix.
test("should create more than 8 streams and show the quick pick more footer", {
tag: ['@logs-stream-quick-pick', '@all', '@logs']
}, async ({ page }) => {
testLogger.info('Testing quick pick more footer with seeded streams');
const QUICK_PICK_LIMIT = 8;
const runToken = `${Date.now()}${Math.floor(Math.random() * 1000)}`;
const seedPrefix = `e2e_qp_more_stream_${runToken}_`;
// Create one more than the limit so streamList always exceeds it.
const seededStreams = await pm.logsPage.seedLogStreams(seedPrefix, QUICK_PICK_LIMIT + 1);
await pm.logsPage.waitForStreamsListed(seededStreams);
// Reload the no-stream logs page so the stream list picks up the new streams.
await page.goto(`${logData.logsUrl}?org_identifier=${getOrgIdentifier()}`);
await page.waitForLoadState('networkidle', { timeout: 30000 }).catch(() => {});
await pm.logsPage.expectQuickPickContainerVisible();
// The quick pick must cap visible stream buttons at the limit.
const count = await pm.logsPage.getQuickPickButtonCount();
expect(count, 'Quick pick should cap visible buttons at the limit (8)').toBe(QUICK_PICK_LIMIT);
// The "more" footer must be visible and report a positive remaining count.
await pm.logsPage.expectQuickPickMoreFooterVisible();
const footerText = await page.locator(pm.logsPage.quickPickMoreFooter).innerText();
expect(footerText, 'More footer should report a remaining count').toMatch(/\d+/);
testLogger.info(`Quick pick more footer verified (${footerText.trim()})`);
});
// ── P2: Hero "Recent:" chip selects stream and triggers search ─────
test("should select stream via hero recent chip", {
tag: ['@logs-stream-quick-pick', '@all', '@logs']
}, async ({ page }) => {
testLogger.info('Testing hero recent chip stream selection');
const orgId = getOrgIdentifier();
// Seed localStorage with a recent stream entry BEFORE navigation so that
// restoreLogsStream() picks it up when the page mounts. The key is
// `oo_selected_stream_logs_<orgId>` and the value is a string[] (see streamPersist.ts:3-4,10-13).
await page.evaluate((oid) => {
localStorage.setItem(
`oo_selected_stream_logs_${oid}`,
JSON.stringify(["e2e_automate"])
);
}, orgId);
// Re-navigate to pick up the localStorage-seeded recent streams.
// The beforeEach already navigated, but the localStorage was not set yet
// at that point, so we must go again.
await page.goto(`${logData.logsUrl}?org_identifier=${orgId}`);
await page.waitForLoadState('networkidle', { timeout: 30000 }).catch(() => {});
// Hero state must be visible with the recent chip
await pm.logsPage.expectNoStreamHeroVisible();
await pm.logsPage.expectRecentChipVisible('e2e_automate');
// Click the recent chip — should select the stream and trigger a search
await pm.logsPage.clickRecentChip('e2e_automate');
// Verify the stream was selected: the quick pick disappears and the
// dropdown shows the stream name
await pm.logsPage.expectQuickPickContainerNotVisible();
await pm.logsPage.expectStreamDropdownShowsStream('e2e_automate');
// Wait for the field list to load (confirms the stream selection completed)
await pm.logsPage.waitForFieldListAfterStreamSelection();
testLogger.info('Hero recent chip selection completed');
});
// ── P2: "Read the query guide" card opens documentation ────────────
test("should open query guide documentation in new tab", {
tag: ['@logs-stream-quick-pick', '@all', '@logs']
}, async ({ page }) => {
testLogger.info('Testing query guide card opens documentation');
await pm.logsPage.expectNoStreamHeroVisible();
await pm.logsPage.expectQueryGuideCardVisible();
// Set up a popup listener BEFORE clicking, so we capture the new tab
// that window.open() creates (LogsNoStreamState.vue:55)
const pagePromise = page.context().waitForEvent('page');
await pm.logsPage.clickQueryGuideCard();
// Wait for the new page to be created and load
const newPage = await pagePromise;
await newPage.waitForLoadState('domcontentloaded', { timeout: 15000 }).catch(() => {});
// The card opens https://openobserve.ai/docs/example-queries/ which
// redirects to /docs/user-guide/data-exploration/example-queries/.
// Accept any URL under openobserve.ai that contains "example-queries".
expect(
newPage.url(),
'New tab URL should point to openobserve query guide docs'
).toMatch(/openobserve\.ai\/.*example-queries/);
// Clean up the new tab
await newPage.close().catch(() => {});
testLogger.info('Query guide card verified — docs opened in new tab');
});
});