mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 08:09:27 +00:00
## Summary - Adds a single GeneralTests spec (`edition-features.spec.js`) that validates the header edition button, the `EnterpriseUpgradeDialog`, every enterprise feature card, and the `o2.ws/*` documentation links each card opens. - Two tests live in the spec; exactly one runs per environment. The active edition is detected from the rendered header button label (most direct signal of what the user sees, tolerates frontend/backend build-flag mismatches like an OSS frontend served by an ENT backend). - Pairs with the same-named branch on `openobserve/o2-enterprise` so ENT CI tree-merges this spec in and runs the ENT variant. ## What the spec validates - Header button label per edition (`Get OpenObserve Enterprise (Free)` vs `Edition: Enterprise`) - Hero panel (title, badge, primary button, features title, Learn More button) - 20 enterprise feature cards (presence + external-link icon + BETA/HA badges) - Cloud-only `Bring Your Own Bucket` card stays hidden outside Cloud - Every feature card click opens a popup that lands on the expected `openobserve.ai` doc page - Hero external link buttons (`Download Now`/`Learn More` on OSS, `Learn More` on ENT) — `Get Free License` intentionally not clicked because it switches the active org to the meta org ## Files - `tests/ui-testing/playwright-tests/GeneralTests/edition-features.spec.js` (new) - `tests/ui-testing/pages/generalPages/editionFeaturesPage.js` (new — page object + truth table of slugs / expected doc paths) - `tests/ui-testing/pages/page-manager.js` (register `pm.editionFeaturesPage`) ## Test plan - [x] OSS local run: 1 passed, 1 skipped (~2.0m) - [x] ENT local run: 1 passed, 1 skipped (~2.0m) - [x] Sentinel audit passed (POM compliance, no raw selectors in spec, no hardcoded secrets, no console.log) - [ ] OSS CI green on this PR - [ ] ENT CI green on companion PR 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
564 lines
22 KiB
JavaScript
564 lines
22 KiB
JavaScript
/**
|
|
* Logs Query Builder — Chart Tests
|
|
*
|
|
* Covers: P0 critical, tab navigation, chart type on tab switch,
|
|
* entry conditions, and chart auto-selection.
|
|
*
|
|
* @tags @queryBuilder @logs @all
|
|
*/
|
|
|
|
const { test, expect, navigateToBase } = require('../utils/enhanced-baseFixtures.js');
|
|
const testLogger = require('../utils/test-logger.js');
|
|
const PageManager = require('../../pages/page-manager.js');
|
|
const {
|
|
ingestForQueryBuilderTest,
|
|
setupQueryAndSwitchToBuild,
|
|
initQueryBuilderTest,
|
|
} = require('../utils/queryBuilder-helpers.js');
|
|
|
|
// ============================================================================
|
|
// Test Suite: P0 - Critical Tests (Smoke)
|
|
// ============================================================================
|
|
|
|
test.describe("Logs Query Builder - P0 Critical Tests", () => {
|
|
test.describe.configure({ mode: 'parallel' });
|
|
let pm;
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
await ingestForQueryBuilderTest(request);
|
|
});
|
|
|
|
test.beforeEach(async ({ page }, testInfo) => {
|
|
testLogger.testStart(testInfo.title, testInfo.file);
|
|
await navigateToBase(page);
|
|
pm = new PageManager(page);
|
|
await initQueryBuilderTest(page, pm);
|
|
testLogger.info('Query Builder test setup completed');
|
|
});
|
|
|
|
test("Build tab opens successfully", {
|
|
tag: ['@queryBuilder', '@smoke', '@P0', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Build tab opens successfully');
|
|
|
|
await pm.logsPage.expectBuildToggleVisible();
|
|
await pm.logsPage.clickBuildToggle();
|
|
|
|
const loaded = await pm.logsPage.waitForBuildTabLoaded();
|
|
expect(loaded).toBeTruthy();
|
|
|
|
testLogger.info('Build tab opens successfully - PASSED');
|
|
});
|
|
|
|
test("Histogram query selects bar chart on Build tab", {
|
|
tag: ['@queryBuilder', '@smoke', '@P0', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing histogram query → bar chart');
|
|
|
|
const histogramQuery = 'SELECT histogram(_timestamp) as time, count(*) as count FROM "e2e_automate" GROUP BY time';
|
|
await setupQueryAndSwitchToBuild(pm, page, histogramQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
|
|
testLogger.info('Histogram query → bar chart - PASSED');
|
|
});
|
|
|
|
test("CTE query selects table chart on Build tab", {
|
|
tag: ['@queryBuilder', '@smoke', '@P0', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing CTE query → table chart');
|
|
|
|
const cteQuery = 'WITH recent AS (SELECT * FROM "e2e_automate" LIMIT 10) SELECT * FROM recent';
|
|
await setupQueryAndSwitchToBuild(pm, page, cteQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('table');
|
|
|
|
testLogger.info('CTE query → table chart - PASSED');
|
|
});
|
|
|
|
test("SELECT star query opens with default histogram/count and bar chart", {
|
|
tag: ['@queryBuilder', '@smoke', '@P0', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing SELECT * → default histogram/count → bar chart');
|
|
|
|
const selectAllQuery = 'SELECT * FROM "e2e_automate"';
|
|
await setupQueryAndSwitchToBuild(pm, page, selectAllQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
|
|
await pm.logsPage.expectBuilderModeActive();
|
|
await pm.logsPage.expectXAxisLayoutVisible();
|
|
await pm.logsPage.expectYAxisLayoutVisible();
|
|
|
|
testLogger.info('SELECT * → default histogram/count → bar chart - PASSED');
|
|
});
|
|
|
|
test("SQL mode preserved when toggling to Build tab (not forced ON)", {
|
|
tag: ['@queryBuilder', '@smoke', '@P0', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing SQL mode preserved on Build tab switch');
|
|
|
|
await pm.logsPage.disableSqlModeIfNeeded();
|
|
const sqlModeOff = await pm.logsPage.isSqlModeOn();
|
|
expect(sqlModeOff).toBe(false);
|
|
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
|
|
const preserved = await pm.logsPage.verifySqlModePreservedOnBuild(false);
|
|
expect(preserved).toBeTruthy();
|
|
|
|
testLogger.info('SQL mode preserved on Build tab - PASSED');
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// Test Suite: P1 - Tab Navigation Tests
|
|
// ============================================================================
|
|
|
|
test.describe("Logs Query Builder - Tab Navigation", () => {
|
|
test.describe.configure({ mode: 'parallel' });
|
|
let pm;
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
await ingestForQueryBuilderTest(request);
|
|
});
|
|
|
|
test.beforeEach(async ({ page }, testInfo) => {
|
|
testLogger.testStart(testInfo.title, testInfo.file);
|
|
await navigateToBase(page);
|
|
pm = new PageManager(page);
|
|
await initQueryBuilderTest(page, pm);
|
|
testLogger.info('Tab Navigation test setup completed');
|
|
});
|
|
|
|
test("Switch from Logs to Build tab", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing switch from Logs to Build tab');
|
|
|
|
await pm.logsPage.expectBuildToggleVisible();
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
await pm.logsPage.expectBuildTabActive();
|
|
|
|
testLogger.info('Switch from Logs to Build tab - PASSED');
|
|
});
|
|
|
|
test("Build tab preserves query state on tab switch", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Build tab preserves query state');
|
|
|
|
await pm.logsPage.enableSqlModeIfNeeded();
|
|
await page.waitForLoadState('domcontentloaded');
|
|
const testQuery = 'SELECT count(*) as total FROM "e2e_automate"';
|
|
await pm.logsPage.setQueryEditorContent(testQuery);
|
|
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
|
|
await pm.logsPage.clickLogsToggle();
|
|
await page.waitForLoadState('domcontentloaded');
|
|
|
|
// Monaco editor is reinitialised after the Build→Logs tab switch; poll the
|
|
// model for the preserved query before reading. Without this, the 500ms
|
|
// wait inside clickLogsToggle races against Monaco mounting and
|
|
// getQueryEditorText returns "" (CI flake on logsQueryBuilder-chart:165).
|
|
await pm.logsPage.waitForQueryEditorValue('e2e_automate');
|
|
|
|
const queryText = await pm.logsPage.getQueryEditorText();
|
|
expect(queryText.toLowerCase()).toContain('e2e_automate');
|
|
expect(queryText.trim().length).toBeGreaterThan(0);
|
|
|
|
testLogger.info('Build tab preserves query state - PASSED');
|
|
});
|
|
|
|
test("SQL Mode auto-enables on Build tab", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing SQL mode behavior on Build tab switch');
|
|
|
|
await pm.logsPage.disableSqlModeIfNeeded();
|
|
const sqlModeOff = await pm.logsPage.isSqlModeOn();
|
|
expect(sqlModeOff).toBe(false);
|
|
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
|
|
const sqlModeAfter = await pm.logsPage.isSqlModeOn();
|
|
expect(sqlModeAfter).toBe(false);
|
|
|
|
testLogger.info('SQL mode preserved (not auto-enabled) on Build tab - PASSED');
|
|
});
|
|
|
|
test("Logs → Build → Logs roundtrip is stable", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Logs → Build → Logs → Build roundtrip');
|
|
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
await pm.logsPage.expectBuildTabActive();
|
|
|
|
await pm.logsPage.clickLogsToggle();
|
|
await page.waitForLoadState('domcontentloaded');
|
|
await pm.logsPage.expectLogsTableVisible();
|
|
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
await pm.logsPage.expectBuildTabActive();
|
|
|
|
testLogger.info('Roundtrip stable - PASSED');
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// Test Suite: P1 - Chart Type Verification on Tab Switch
|
|
// ============================================================================
|
|
|
|
test.describe("Logs Query Builder - Chart Type on Tab Switch", () => {
|
|
test.describe.configure({ mode: 'parallel' });
|
|
let pm;
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
await ingestForQueryBuilderTest(request);
|
|
});
|
|
|
|
test.beforeEach(async ({ page }, testInfo) => {
|
|
testLogger.testStart(testInfo.title, testInfo.file);
|
|
await navigateToBase(page);
|
|
pm = new PageManager(page);
|
|
await initQueryBuilderTest(page, pm);
|
|
testLogger.info('Chart Type on Tab Switch test setup completed');
|
|
});
|
|
|
|
test("Histogram query selects bar chart type", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing histogram → bar chart');
|
|
|
|
const histogramQuery = 'SELECT histogram(_timestamp) as time, count(*) as count FROM "e2e_automate" GROUP BY time';
|
|
await setupQueryAndSwitchToBuild(pm, page, histogramQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
|
|
testLogger.info('Histogram → bar chart - PASSED');
|
|
});
|
|
|
|
test("Count-only query selects metric chart type", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing count-only → metric chart');
|
|
|
|
const countQuery = 'SELECT count(*) as total FROM "e2e_automate"';
|
|
await setupQueryAndSwitchToBuild(pm, page, countQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('metric');
|
|
|
|
testLogger.info('Count-only → metric chart - PASSED');
|
|
});
|
|
|
|
test("CTE query selects table chart type", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing CTE → table chart');
|
|
|
|
const cteQuery = 'WITH recent AS (SELECT * FROM "e2e_automate" LIMIT 10) SELECT * FROM recent';
|
|
await setupQueryAndSwitchToBuild(pm, page, cteQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('table');
|
|
|
|
testLogger.info('CTE → table chart - PASSED');
|
|
});
|
|
|
|
test("Subquery selects table chart type", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing subquery → table chart');
|
|
|
|
const subquery = 'SELECT code, cnt FROM (SELECT code, count(*) as cnt FROM "e2e_automate" GROUP BY code) subq LIMIT 10';
|
|
await setupQueryAndSwitchToBuild(pm, page, subquery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('table');
|
|
|
|
testLogger.info('Subquery → table chart - PASSED');
|
|
});
|
|
|
|
test("SELECT star query selects bar chart type (default histogram/count)", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing SELECT * → bar chart (default histogram/count)');
|
|
|
|
const selectAllQuery = 'SELECT * FROM "e2e_automate"';
|
|
await setupQueryAndSwitchToBuild(pm, page, selectAllQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
|
|
await pm.logsPage.expectBuilderModeActive();
|
|
await pm.logsPage.expectXAxisLayoutVisible();
|
|
await pm.logsPage.expectYAxisLayoutVisible();
|
|
|
|
testLogger.info('SELECT * → bar chart (default histogram/count) - PASSED');
|
|
});
|
|
|
|
test("Histogram with filter populates X-axis, Y-axis, and filter", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing histogram + filter query populates builder fields');
|
|
|
|
const filterQuery = 'SELECT histogram(_timestamp) as "x_axis_1", count(*) as "y_axis_1" FROM "e2e_automate" WHERE code = \'200\' GROUP BY x_axis_1';
|
|
await setupQueryAndSwitchToBuild(pm, page, filterQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
|
|
await pm.logsPage.expectXAxisLayoutVisible();
|
|
await pm.logsPage.expectYAxisLayoutVisible();
|
|
|
|
testLogger.info('Histogram + filter → builder fields populated - PASSED');
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// Test Suite: Entry Conditions (Design Doc Cases 1-9)
|
|
// ============================================================================
|
|
|
|
test.describe("Logs Query Builder - Entry Conditions (Cases 1-9)", () => {
|
|
test.describe.configure({ mode: 'parallel' });
|
|
let pm;
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
await ingestForQueryBuilderTest(request);
|
|
});
|
|
|
|
test.beforeEach(async ({ page }, testInfo) => {
|
|
testLogger.testStart(testInfo.title, testInfo.file);
|
|
await navigateToBase(page);
|
|
pm = new PageManager(page);
|
|
await initQueryBuilderTest(page, pm);
|
|
testLogger.info('Entry Conditions test setup completed');
|
|
});
|
|
|
|
test("Case 1: SQL OFF + Empty → auto mode, histogram/count, bar chart, auto-runs", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Case 1: SQL OFF + Empty');
|
|
|
|
await pm.logsPage.disableSqlModeIfNeeded();
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
|
|
await pm.logsPage.expectXAxisLayoutVisible();
|
|
await pm.logsPage.expectYAxisLayoutVisible();
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
|
|
const sqlModeOn = await pm.logsPage.isSqlModeOn();
|
|
expect(sqlModeOn).toBe(false);
|
|
|
|
testLogger.info('Case 1 - PASSED');
|
|
});
|
|
|
|
test("Case 2: SQL OFF + WHERE clause → auto mode, filter parsed from WHERE", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Case 2: SQL OFF + WHERE clause');
|
|
|
|
await pm.logsPage.disableSqlModeIfNeeded();
|
|
await page.waitForLoadState('domcontentloaded');
|
|
await pm.logsPage.setQueryEditorContent("code = '200'");
|
|
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
|
|
await pm.logsPage.expectXAxisLayoutVisible();
|
|
await pm.logsPage.expectYAxisLayoutVisible();
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
|
|
await pm.logsPage.expectFilterLayoutVisible();
|
|
|
|
const sqlModeOn = await pm.logsPage.isSqlModeOn();
|
|
expect(sqlModeOn).toBe(false);
|
|
|
|
testLogger.info('Case 2 - PASSED');
|
|
});
|
|
|
|
test("Case 3: SQL ON + Empty → auto mode, default histogram/count, auto-runs", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Case 3: SQL ON + Empty');
|
|
|
|
await pm.logsPage.enableSqlModeIfNeeded();
|
|
await pm.logsPage.setQueryEditorContent('');
|
|
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
|
|
await pm.logsPage.expectXAxisLayoutVisible();
|
|
await pm.logsPage.expectYAxisLayoutVisible();
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
|
|
await pm.logsPage.expectChartOrNoDataAttached();
|
|
|
|
testLogger.info('Case 3 - PASSED');
|
|
});
|
|
|
|
test("Case 4: SQL ON + simple parseable SQL → auto mode, fields from parsed SQL", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Case 4: SQL ON + simple parseable SQL');
|
|
|
|
const simpleSQL = 'SELECT histogram(_timestamp) as "x_axis_1", count(_timestamp) as "y_axis_1" FROM "e2e_automate" WHERE code = \'200\' GROUP BY x_axis_1';
|
|
await setupQueryAndSwitchToBuild(pm, page, simpleSQL);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
await pm.logsPage.expectXAxisLayoutVisible();
|
|
await pm.logsPage.expectYAxisLayoutVisible();
|
|
|
|
testLogger.info('Case 4 - PASSED');
|
|
});
|
|
|
|
test("Case 5: SQL ON + complex SQL (CTE) → custom mode, table chart", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Case 5: SQL ON + complex SQL');
|
|
|
|
const complexSQL = 'WITH recent AS (SELECT * FROM "e2e_automate" LIMIT 10) SELECT * FROM recent';
|
|
await setupQueryAndSwitchToBuild(pm, page, complexSQL);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('table');
|
|
|
|
testLogger.info('Case 5 - PASSED');
|
|
});
|
|
|
|
test("Case 6: SQL ON + aggregation only → auto mode, Y-only, metric chart", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Case 6: SQL ON + aggregation only');
|
|
|
|
const aggOnlySQL = 'SELECT count(*) as total FROM "e2e_automate"';
|
|
await setupQueryAndSwitchToBuild(pm, page, aggOnlySQL);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('metric');
|
|
|
|
testLogger.info('Case 6 - PASSED');
|
|
});
|
|
|
|
test("Case 7: SQL ON + >2 GROUP BY → auto mode, table chart", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Case 7: SQL ON + >2 GROUP BY');
|
|
|
|
const multiGroupSQL = 'SELECT code, method, level, count(*) as "y_axis_1" FROM "e2e_automate" GROUP BY code, method, level';
|
|
await setupQueryAndSwitchToBuild(pm, page, multiGroupSQL);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('table');
|
|
|
|
testLogger.info('Case 7 - PASSED');
|
|
});
|
|
|
|
test("Case 8: SQL OFF + multi-stream → only first stream used in builder", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing Case 8: SQL OFF + multi-stream');
|
|
|
|
await pm.logsPage.disableSqlModeIfNeeded();
|
|
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
|
|
await pm.logsPage.expectXAxisLayoutVisible();
|
|
await pm.logsPage.expectYAxisLayoutVisible();
|
|
|
|
testLogger.info('Case 8 - PASSED');
|
|
});
|
|
|
|
});
|
|
|
|
// ============================================================================
|
|
// Test Suite: Chart Type Auto-Selection Comprehensive
|
|
// ============================================================================
|
|
|
|
test.describe("Logs Query Builder - Chart Auto-Selection", () => {
|
|
test.describe.configure({ mode: 'parallel' });
|
|
let pm;
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
await ingestForQueryBuilderTest(request);
|
|
});
|
|
|
|
test.beforeEach(async ({ page }, testInfo) => {
|
|
testLogger.testStart(testInfo.title, testInfo.file);
|
|
await navigateToBase(page);
|
|
pm = new PageManager(page);
|
|
await initQueryBuilderTest(page, pm);
|
|
testLogger.info('Chart Auto-Selection test setup completed');
|
|
});
|
|
|
|
test("Custom mode always selects table chart", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing: custom mode → table chart');
|
|
|
|
const subquery = 'SELECT code, cnt FROM (SELECT code, count(*) as cnt FROM "e2e_automate" GROUP BY code) subq';
|
|
await setupQueryAndSwitchToBuild(pm, page, subquery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('table');
|
|
|
|
testLogger.info('Custom mode → table chart - PASSED');
|
|
});
|
|
|
|
test("Auto mode with Y-axis only selects metric chart", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing: Y-axis only → metric chart');
|
|
|
|
const yOnlyQuery = 'SELECT avg(code) as "y_axis_1" FROM "e2e_automate"';
|
|
await setupQueryAndSwitchToBuild(pm, page, yOnlyQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('metric');
|
|
|
|
testLogger.info('Y-axis only → metric chart - PASSED');
|
|
});
|
|
|
|
test("Auto mode with X + Y selects bar chart (default)", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing: X + Y → bar chart (default)');
|
|
|
|
const xyQuery = 'SELECT histogram(_timestamp) as "x_axis_1", count(_timestamp) as "y_axis_1" FROM "e2e_automate" GROUP BY x_axis_1';
|
|
await setupQueryAndSwitchToBuild(pm, page, xyQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
await pm.logsPage.expectXAxisLayoutVisible();
|
|
await pm.logsPage.expectYAxisLayoutVisible();
|
|
|
|
testLogger.info('X + Y → bar chart - PASSED');
|
|
});
|
|
|
|
test("Auto mode with >2 GROUP BY selects table chart (useTableChart)", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing: >2 GROUP BY → table chart (useTableChart)');
|
|
|
|
const tableChartQuery = 'SELECT code, method, level, count(*) as "y_axis_1" FROM "e2e_automate" GROUP BY code, method, level';
|
|
await setupQueryAndSwitchToBuild(pm, page, tableChartQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('table');
|
|
|
|
testLogger.info('>2 GROUP BY → table chart - PASSED');
|
|
});
|
|
|
|
test("Multiple Y-axis with X-axis selects bar chart", {
|
|
tag: ['@queryBuilder', '@functional', '@P1', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Testing: multiple Y + X → bar chart');
|
|
|
|
const multiYQuery = 'SELECT histogram(_timestamp) as "x_axis_1", count(_timestamp) as "y_axis_1", avg(code) as "y_axis_2" FROM "e2e_automate" GROUP BY x_axis_1';
|
|
await setupQueryAndSwitchToBuild(pm, page, multiYQuery);
|
|
|
|
await pm.logsPage.verifyChartTypeSelected('bar');
|
|
|
|
testLogger.info('Multiple Y + X → bar chart - PASSED');
|
|
});
|
|
});
|