mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 08:09:27 +00:00
Revamp the metrics explorer to enable faster visualization and exploration of metrics. Design at: metrics_cards_prd.md file --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: ktx-abhay <abhay.padamani@kiara.tech> Co-authored-by: Abhay Padamani <141122205+ktx-abhay@users.noreply.github.com>
221 lines
8.2 KiB
JavaScript
221 lines
8.2 KiB
JavaScript
// Copyright 2026 OpenObserve Inc.
|
|
|
|
import { gotoMetricsEditor } from '../commonActions.js';
|
|
|
|
export class SharedComponentsFormValidationPage {
|
|
/**
|
|
* @param {import('@playwright/test').Page} page
|
|
*/
|
|
constructor(page) {
|
|
this.page = page;
|
|
|
|
// ── AddToDashboard dialog ─────────────────────────────────────────────
|
|
// ODialog wrapper — data-test="add-to-dashboard-dialog"
|
|
this.addToDashboardDialog = '[data-test="add-to-dashboard-dialog"]';
|
|
|
|
// OFormInput data-test="metrics-new-dashboard-panel-title"
|
|
// OFormInput generates -field (native <input>) and -error (error message)
|
|
this.panelTitleInput = '[data-test="metrics-new-dashboard-panel-title-field"]';
|
|
this.panelTitleError = '[data-test="metrics-new-dashboard-panel-title-error"]';
|
|
|
|
// ODialog built-in buttons scoped to dialog
|
|
this.addToDashboardSubmitBtn =
|
|
'[data-test="add-to-dashboard-dialog"] [data-test="o-dialog-primary-btn"]';
|
|
this.addToDashboardCancelBtn =
|
|
'[data-test="add-to-dashboard-dialog"] [data-test="o-dialog-secondary-btn"]';
|
|
|
|
// ── TimeRangeEditor dialog ────────────────────────────────────────────
|
|
// ODialog wrapper — data-test="time-range-editor-dialog"
|
|
this.timeRangeEditorDialog = '[data-test="time-range-editor-dialog"]';
|
|
|
|
// Preset radio buttons
|
|
this.window1min = '[data-test="window-1min"]';
|
|
this.window5min = '[data-test="window-5min"]';
|
|
this.window15min = '[data-test="window-15min"]';
|
|
this.window30min = '[data-test="window-30min"]';
|
|
this.window1hour = '[data-test="window-1hour"]';
|
|
this.windowCustom = '[data-test="window-custom"]';
|
|
|
|
// Custom time inputs — OInput generates -field (native <input>) and -error
|
|
this.customStartInput = '[data-test="custom-start-input-field"]';
|
|
this.customStartError = '[data-test="custom-start-input-error"]';
|
|
this.customEndInput = '[data-test="custom-end-input-field"]';
|
|
this.customEndError = '[data-test="custom-end-input-error"]';
|
|
|
|
// ODialog built-in buttons scoped to dialog
|
|
this.timeRangeApplyBtn =
|
|
'[data-test="time-range-editor-dialog"] [data-test="o-dialog-primary-btn"]';
|
|
this.timeRangeCancelBtn =
|
|
'[data-test="time-range-editor-dialog"] [data-test="o-dialog-secondary-btn"]';
|
|
this.timeRangeResetBtn =
|
|
'[data-test="time-range-editor-dialog"] [data-test="o-dialog-neutral-btn"]';
|
|
|
|
// ── Metrics page navigation ───────────────────────────────────────────
|
|
this.metricsMenuLink = '[data-test="menu-link-\\/metrics-item"]';
|
|
}
|
|
|
|
// ── AddToDashboard helpers ────────────────────────────────────────────────
|
|
|
|
/**
|
|
* The AddToDashboard dialog under test is reached from the metrics panel
|
|
* EDITOR (run a query, then "Add to Dashboard"), so go there directly —
|
|
* the sidebar's Metrics item now opens the Metrics Explorer browse grid,
|
|
* which has no query bar at all.
|
|
*/
|
|
async navigateToMetrics() {
|
|
await gotoMetricsEditor(this.page);
|
|
}
|
|
|
|
async waitForAddToDashboardDialog() {
|
|
await this.page
|
|
.locator(this.addToDashboardDialog)
|
|
.waitFor({ state: 'visible', timeout: 10000 });
|
|
}
|
|
|
|
async fillPanelTitle(title) {
|
|
const input = this.page.locator(this.panelTitleInput);
|
|
await input.waitFor({ state: 'visible' });
|
|
await input.fill(title);
|
|
}
|
|
|
|
async clearPanelTitle() {
|
|
const input = this.page.locator(this.panelTitleInput);
|
|
await input.waitFor({ state: 'visible' });
|
|
await input.fill('');
|
|
}
|
|
|
|
async clickAddToDashboardSubmit() {
|
|
await this.page.locator(this.addToDashboardSubmitBtn).click();
|
|
}
|
|
|
|
async clickAddToDashboardCancel() {
|
|
await this.page.locator(this.addToDashboardCancelBtn).click();
|
|
}
|
|
|
|
getAddToDashboardDialogLocator() {
|
|
return this.page.locator(this.addToDashboardDialog);
|
|
}
|
|
|
|
getPanelTitleErrorLocator() {
|
|
return this.page.locator(this.panelTitleError);
|
|
}
|
|
|
|
getAddToDashboardSubmitBtnLocator() {
|
|
return this.page.locator(this.addToDashboardSubmitBtn);
|
|
}
|
|
|
|
// ── TimeRangeEditor helpers ───────────────────────────────────────────────
|
|
|
|
async waitForTimeRangeEditorDialog() {
|
|
await this.page
|
|
.locator(this.timeRangeEditorDialog)
|
|
.waitFor({ state: 'visible', timeout: 10000 });
|
|
}
|
|
|
|
async selectCustomWindow() {
|
|
await this.page.locator(this.windowCustom).click();
|
|
}
|
|
|
|
async selectPresetWindow(preset) {
|
|
// preset: '1min' | '5min' | '15min' | '30min' | '1hour'
|
|
await this.page.locator(`[data-test="window-${preset}"]`).click();
|
|
}
|
|
|
|
async fillCustomStartTime(datetimeLocal) {
|
|
const input = this.page.locator(this.customStartInput);
|
|
await input.waitFor({ state: 'visible' });
|
|
await input.fill(datetimeLocal);
|
|
// Trigger change event so validation runs
|
|
await input.dispatchEvent('change');
|
|
}
|
|
|
|
async fillCustomEndTime(datetimeLocal) {
|
|
const input = this.page.locator(this.customEndInput);
|
|
await input.waitFor({ state: 'visible' });
|
|
await input.fill(datetimeLocal);
|
|
await input.dispatchEvent('change');
|
|
}
|
|
|
|
async clickTimeRangeApply() {
|
|
await this.page.locator(this.timeRangeApplyBtn).click();
|
|
}
|
|
|
|
async clickTimeRangeCancel() {
|
|
await this.page.locator(this.timeRangeCancelBtn).click();
|
|
}
|
|
|
|
async clickTimeRangeReset() {
|
|
await this.page.locator(this.timeRangeResetBtn).click();
|
|
}
|
|
|
|
getTimeRangeEditorDialogLocator() {
|
|
return this.page.locator(this.timeRangeEditorDialog);
|
|
}
|
|
|
|
getCustomStartErrorLocator() {
|
|
return this.page.locator(this.customStartError);
|
|
}
|
|
|
|
getCustomEndErrorLocator() {
|
|
return this.page.locator(this.customEndError);
|
|
}
|
|
|
|
getTimeRangeApplyBtnLocator() {
|
|
return this.page.locator(this.timeRangeApplyBtn);
|
|
}
|
|
|
|
getWindow1minLocator() {
|
|
return this.page.locator(this.window1min);
|
|
}
|
|
|
|
getWindow5minLocator() {
|
|
return this.page.locator(this.window5min);
|
|
}
|
|
|
|
getWindow15minLocator() {
|
|
return this.page.locator(this.window15min);
|
|
}
|
|
|
|
getWindow30minLocator() {
|
|
return this.page.locator(this.window30min);
|
|
}
|
|
|
|
getWindow1hourLocator() {
|
|
return this.page.locator(this.window1hour);
|
|
}
|
|
|
|
getWindowCustomLocator() {
|
|
return this.page.locator(this.windowCustom);
|
|
}
|
|
|
|
getCustomStartInputLocator() {
|
|
return this.page.locator(this.customStartInput);
|
|
}
|
|
|
|
getCustomEndInputLocator() {
|
|
return this.page.locator(this.customEndInput);
|
|
}
|
|
|
|
// ── Navigation to Logs > Correlation tab ─────────────────────────────────
|
|
|
|
get logsMenuLink() {
|
|
return '[data-test="menu-link-\\/logs-item"]';
|
|
}
|
|
|
|
async navigateToLogsCorrelation() {
|
|
await this.page.locator(this.logsMenuLink).click();
|
|
// Wait for logs page then click the Correlation tab
|
|
await this.page.locator('[data-test="logs-search-bar"]').waitFor({ state: 'visible', timeout: 15000 });
|
|
const correlationTab = this.page.locator('[data-test="logs-correlation-tab"]');
|
|
await correlationTab.waitFor({ state: 'visible', timeout: 10000 });
|
|
await correlationTab.click();
|
|
}
|
|
|
|
async openTimeRangeEditorFromCorrelation() {
|
|
// Click the time range editor trigger button in the Correlation tab
|
|
const trigger = this.page.locator('[data-test="correlation-time-range-edit-btn"], [data-test="time-range-editor-trigger"]');
|
|
await trigger.waitFor({ state: 'visible', timeout: 10000 });
|
|
await trigger.click();
|
|
}
|
|
}
|