mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-03 16:10:21 +00:00
Co-authored-by: Shrinath-O2 <214651540+Shrinath-O2@users.noreply.github.com> Co-authored-by: Neha P <neha@openobserve.ai>
95 lines
4.9 KiB
JavaScript
95 lines
4.9 KiB
JavaScript
/**
|
|
* Logs Patterns Multi-Stream Guard (OSS).
|
|
*
|
|
* The Patterns extraction runs on a dedicated single-stream API. This spec verifies the
|
|
* client-side guard in Index.vue's extractPatternsForCurrentQuery(): when more than one
|
|
* stream is selected in non-SQL mode it cancels the in-flight extraction, clears stale
|
|
* patterns and surfaces an error toast BEFORE any API call. The Patterns toggle button is
|
|
* enterprise-gated, so in OSS we enter patterns mode via the URL query param
|
|
* (logs_visualize_toggle=patterns). No ingestion/FTS/patterns-config setup is required —
|
|
* the guard fires on selectedStream.length alone.
|
|
*/
|
|
|
|
const { test, expect, navigateToBase } = require('../utils/enhanced-baseFixtures.js');
|
|
const testLogger = require('../utils/test-logger.js');
|
|
const PageManager = require('../../pages/page-manager.js');
|
|
const { waitForStreamListed } = require('../utils/data-ingestion.js');
|
|
const { getOrgIdentifier } = require('../utils/cloud-auth.js');
|
|
|
|
// POST /api/{org}/streams/{stream}/patterns/extract — the single-stream extraction API
|
|
// the guard exists to keep multi-stream selections away from (web/src/services/patterns.ts).
|
|
const PATTERNS_EXTRACT_URL = /\/streams\/[^/]+\/patterns\/extract/;
|
|
|
|
// Unique per-test stream names so parallel tests never collide. cleanup.spec.js reclaims
|
|
// these via the /^e2e_multi_patterns/ prefix.
|
|
function makeStreamName(letter) {
|
|
return `e2e_multi_patterns_${letter}_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 5)}`;
|
|
}
|
|
|
|
test.describe("Logs Patterns Multi-Stream Guard 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);
|
|
testLogger.info('Test setup completed');
|
|
});
|
|
|
|
test.afterEach(async ({}, testInfo) => {
|
|
testLogger.testEnd(testInfo.title, testInfo.status);
|
|
});
|
|
|
|
test("should show an error toast and refuse patterns when multiple streams are selected @P0 @smoke", {
|
|
tag: ['@logs-patterns-multi-stream-guard', '@all', '@smoke', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Test: multi-stream patterns guard fires an error toast');
|
|
|
|
// The guard fires before any network call, so the streams only need to exist.
|
|
const streamA = makeStreamName('a');
|
|
const streamB = makeStreamName('b');
|
|
await pm.streamsPage.createStream(streamA, 'logs');
|
|
await pm.streamsPage.createStream(streamB, 'logs');
|
|
await waitForStreamListed(page, streamA, 'logs');
|
|
await waitForStreamListed(page, streamB, 'logs');
|
|
|
|
// The guard's whole point is that it returns before the request is built, so record
|
|
// every extraction call and assert none was made — a toast alone would still pass if
|
|
// the guard ran after the API had already been hit.
|
|
const extractCalls = [];
|
|
page.on('request', (req) => {
|
|
if (PATTERNS_EXTRACT_URL.test(req.url())) extractCalls.push(req.url());
|
|
});
|
|
|
|
// Enter patterns mode via URL (the toggle is enterprise-gated in OSS). restoreUrlQueryParams
|
|
// splits `stream` on ',' into [a, b], so the guard condition is true on mount and the toast fires.
|
|
const logsUrl = `${process.env.ZO_BASE_URL}/web/logs?org_identifier=${getOrgIdentifier()}`;
|
|
await pm.logsPage.startToastRecorder();
|
|
await page.goto(`${logsUrl}&stream_type=logs&stream=${streamA},${streamB}&logs_visualize_toggle=patterns`, { waitUntil: 'domcontentloaded' });
|
|
|
|
await pm.logsPage.expectMultiStreamPatternsToast();
|
|
expect(extractCalls, `patterns/extract must not be called for a multi-stream selection, got: ${extractCalls.join(', ')}`).toHaveLength(0);
|
|
testLogger.info('PASSED: multi-stream guard error toast shown, no extraction request issued');
|
|
});
|
|
|
|
test("should not show the multi-stream patterns toast for a single stream @P1", {
|
|
tag: ['@logs-patterns-multi-stream-guard', '@all', '@logs']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Test: single-stream patterns skips the multi-stream guard');
|
|
|
|
const streamA = makeStreamName('a');
|
|
await pm.streamsPage.createStream(streamA, 'logs');
|
|
await waitForStreamListed(page, streamA, 'logs');
|
|
|
|
const logsUrl = `${process.env.ZO_BASE_URL}/web/logs?org_identifier=${getOrgIdentifier()}`;
|
|
await pm.logsPage.startToastRecorder();
|
|
await page.goto(`${logsUrl}&stream_type=logs&stream=${streamA}&logs_visualize_toggle=patterns`, { waitUntil: 'domcontentloaded' });
|
|
|
|
// selectedStream.length is 1, so the guard is skipped and extraction proceeds. The exact
|
|
// multi-stream error message must never appear (a generic errorExtractingPatterns toast may).
|
|
await pm.logsPage.expectNoMultiStreamPatternsToast();
|
|
testLogger.info('PASSED: no multi-stream toast for a single stream');
|
|
});
|
|
});
|