mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-03 16:10:21 +00:00
179 lines
7.5 KiB
JavaScript
179 lines
7.5 KiB
JavaScript
const { test, expect, navigateToBase } = require('../utils/enhanced-baseFixtures.js');
|
|
const testLogger = require('../utils/test-logger.js');
|
|
const PageManager = require('../../pages/page-manager.js');
|
|
|
|
/**
|
|
* E2E coverage for the Date-Time picker Forward Shift Cap (PR #14683).
|
|
*
|
|
* The shared picker (web/src/components/DateTime.vue) renders Previous / Next
|
|
* shift buttons on either side of its trigger. The fix caps the forward shift
|
|
* so it can never land past "now": Next is disabled in Relative mode and
|
|
* whenever the absolute window's end is within one second of the present, and
|
|
* shiftTimeRange('next') clamps its delta with Math.min(duration, now - end).
|
|
*
|
|
* Assertion strategy — copy-back round-trip (same as the copy/paste spec):
|
|
* after a shift the picker closes, so the test reopens it, clicks Copy, and
|
|
* compares the {"start_date","end_date"} epoch-microsecond payload. This is
|
|
* exact for second-aligned input and independent of the runner's timezone.
|
|
*/
|
|
|
|
// Fixed past anchor: 2026-07-23T10:00:00Z .. 2026-07-23T11:00:00Z.
|
|
// Second-aligned and far from now, so no calendar max-date / cap can interfere.
|
|
const ANCHOR_START_MICROS = 1784800800000000;
|
|
const ANCHOR_END_MICROS = 1784804400000000;
|
|
const ONE_HOUR_MICROS = 3_600_000_000;
|
|
const MICROS_PER_SECOND = 1_000_000;
|
|
|
|
test.describe("Date-Time Picker Forward Shift Cap 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);
|
|
|
|
// The Logs search bar hosts the picker with auto-apply on and does NOT pass
|
|
// hide-range-shift, so both shift buttons render and a shift commits the
|
|
// moment it is applied (no Apply button to manage).
|
|
await page.goto(`${process.env["ZO_BASE_URL"]}/web/logs?org_identifier=${process.env["ORGNAME"]}`);
|
|
await page.waitForLoadState('domcontentloaded');
|
|
await pm.dateTimePickerPage.openPicker();
|
|
|
|
testLogger.info('Logs date-time picker opened');
|
|
});
|
|
|
|
// TC-01
|
|
test("next shift button is disabled while the picker is in relative mode", {
|
|
tag: ['@date-time-next-shift-cap', '@all', '@P0']
|
|
}, async () => {
|
|
testLogger.info('Verifying Next is disabled in the default Relative mode');
|
|
|
|
// A relative window has no concrete boundary to shift forward from, so the
|
|
// forward shift is gated off; backward shift stays permitted.
|
|
await pm.dateTimePickerPage.expectNextDisabled();
|
|
await pm.dateTimePickerPage.expectPrevEnabled();
|
|
|
|
testLogger.info('Next disabled and Prev enabled in Relative mode');
|
|
});
|
|
|
|
// TC-02
|
|
test("forward shift moves both boundaries forward by the window duration and stays absolute", {
|
|
tag: ['@date-time-next-shift-cap', '@all', '@P0']
|
|
}, async () => {
|
|
testLogger.info('Shifting a fixed past 1-hour window forward');
|
|
|
|
await pm.dateTimePickerPage.seedClipboard(`${ANCHOR_START_MICROS} - ${ANCHOR_END_MICROS}`);
|
|
await pm.dateTimePickerPage.clickPaste();
|
|
await pm.dateTimePickerPage.expectPasteSuccessToast();
|
|
await pm.dateTimePickerPage.expectAbsolutePanelActive();
|
|
await pm.dateTimePickerPage.expectNextEnabled();
|
|
|
|
await pm.dateTimePickerPage.clickNext();
|
|
|
|
// The shift closes the picker; reopen it and copy the shifted window back.
|
|
await pm.dateTimePickerPage.openPicker();
|
|
await pm.dateTimePickerPage.expectAbsolutePanelActive();
|
|
await pm.dateTimePickerPage.clickCopy();
|
|
const range = await pm.dateTimePickerPage.readCopiedRange();
|
|
|
|
expect(range.start_date).toBe(ANCHOR_START_MICROS + ONE_HOUR_MICROS);
|
|
expect(range.end_date).toBe(ANCHOR_END_MICROS + ONE_HOUR_MICROS);
|
|
|
|
testLogger.info('Window advanced forward by exactly one hour and stayed absolute');
|
|
});
|
|
|
|
// TC-03
|
|
test("forward shift clamps the window so its end never passes the present", {
|
|
tag: ['@date-time-next-shift-cap', '@all', '@P0']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Shifting a window ending just before now and checking the cap');
|
|
|
|
// Compute the anchor from the page's own clock so the test shares the
|
|
// component's notion of "now" (Date.now() * 1000 is epoch microseconds).
|
|
const { startMicros, endMicros } = await page.evaluate(() => {
|
|
const now = Date.now() * 1_000;
|
|
return { startMicros: now - 90_000_000, endMicros: now - 30_000_000 };
|
|
});
|
|
|
|
const before = await pm.dateTimePickerPage.pasteAndReadBackRange(`${startMicros} - ${endMicros}`);
|
|
await pm.dateTimePickerPage.expectNextEnabled();
|
|
|
|
await pm.dateTimePickerPage.clickNext();
|
|
|
|
await pm.dateTimePickerPage.openPicker();
|
|
await pm.dateTimePickerPage.clickCopy();
|
|
const after = await pm.dateTimePickerPage.readCopiedRange();
|
|
|
|
const nowMicros = await page.evaluate(() => Date.now() * 1_000);
|
|
|
|
// Headline assertion: the clamped end never lands in the future. The shift
|
|
// clamps its delta to now - end, so after.end_date is at most "now" at the
|
|
// moment of the click; the +2s slack absorbs normal execution drift.
|
|
expect(after.end_date).toBeLessThanOrEqual(nowMicros + 2 * MICROS_PER_SECOND);
|
|
// The window stays valid and has still moved forward.
|
|
expect(after.end_date).toBeGreaterThan(after.start_date);
|
|
expect(after.start_date).toBeGreaterThan(before.start_date);
|
|
|
|
testLogger.info('Forward shift clamped at now', { before, after });
|
|
});
|
|
|
|
// TC-04
|
|
test("previous shift moves both boundaries backward by the window duration", {
|
|
tag: ['@date-time-next-shift-cap', '@all', '@P1']
|
|
}, async () => {
|
|
testLogger.info('Shifting a fixed past 1-hour window backward');
|
|
|
|
await pm.dateTimePickerPage.seedClipboard(`${ANCHOR_START_MICROS} - ${ANCHOR_END_MICROS}`);
|
|
await pm.dateTimePickerPage.clickPaste();
|
|
await pm.dateTimePickerPage.expectPasteSuccessToast();
|
|
await pm.dateTimePickerPage.expectAbsolutePanelActive();
|
|
|
|
await pm.dateTimePickerPage.clickPrev();
|
|
|
|
await pm.dateTimePickerPage.openPicker();
|
|
await pm.dateTimePickerPage.clickCopy();
|
|
const range = await pm.dateTimePickerPage.readCopiedRange();
|
|
|
|
expect(range.start_date).toBe(ANCHOR_START_MICROS - ONE_HOUR_MICROS);
|
|
expect(range.end_date).toBe(ANCHOR_END_MICROS - ONE_HOUR_MICROS);
|
|
|
|
testLogger.info('Window shifted backward by exactly one hour');
|
|
});
|
|
|
|
// TC-05
|
|
test("forward shift is disabled when the window end is past the present", {
|
|
tag: ['@date-time-next-shift-cap', '@all', '@P1']
|
|
}, async ({ page }) => {
|
|
testLogger.info('Verifying Next is disabled for a window ending past the present');
|
|
|
|
// An end exactly at now re-enables Next ~1s later (endUTC + 1s > now), so end in the future.
|
|
const { startMicros, endMicros } = await page.evaluate(() => {
|
|
const now = Date.now() * 1_000;
|
|
return { startMicros: now - 30_000_000, endMicros: now + 300_000_000 };
|
|
});
|
|
|
|
await pm.dateTimePickerPage.seedClipboard(`${startMicros} - ${endMicros}`);
|
|
await pm.dateTimePickerPage.clickPaste();
|
|
await pm.dateTimePickerPage.expectPasteSuccessToast();
|
|
await pm.dateTimePickerPage.expectAbsolutePanelActive();
|
|
|
|
await pm.dateTimePickerPage.expectNextDisabled();
|
|
|
|
testLogger.info('Next disabled for a window ending past the present');
|
|
});
|
|
|
|
// TC-06
|
|
test("both previous and next shift buttons render with accessible labels", {
|
|
tag: ['@date-time-next-shift-cap', '@all', '@P2']
|
|
}, async () => {
|
|
testLogger.info('Verifying shift buttons render with accessible labels');
|
|
|
|
await pm.dateTimePickerPage.expectShiftButtonsVisible();
|
|
await pm.dateTimePickerPage.expectShiftAriaLabels();
|
|
|
|
testLogger.info('Shift buttons visible with correct aria-labels');
|
|
});
|
|
});
|