From e4ad55d2d0fc862abb3b8c6a935164a871237408 Mon Sep 17 00:00:00 2001 From: Seyed Mahmoud SHAHROKNI Date: Tue, 10 Mar 2026 11:00:49 +0100 Subject: [PATCH] [IGNORE] add unit tests for the dashboard timezone Signed-off-by: Seyed Mahmoud SHAHROKNI Signed-off-by: Seyed Mahmoud SHAHROKNI Signed-off-by: Seyed Mahmoud SHAHROKNI Signed-off-by: Seyed Mahmoud SHAHROKNI Signed-off-by: Seyed Mahmoud SHAHROKNI --- .../DateTimeRangePicker.test.tsx | 120 ++++++++++++++++++ .../TimeRangeSelector/DateTimeRangePicker.tsx | 5 +- 2 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 components/src/TimeRangeSelector/DateTimeRangePicker.test.tsx diff --git a/components/src/TimeRangeSelector/DateTimeRangePicker.test.tsx b/components/src/TimeRangeSelector/DateTimeRangePicker.test.tsx new file mode 100644 index 0000000..077f201 --- /dev/null +++ b/components/src/TimeRangeSelector/DateTimeRangePicker.test.tsx @@ -0,0 +1,120 @@ +// Copyright The Perses Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { AbsoluteTimeRange } from '@perses-dev/core'; +import { render, screen, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { AbsoluteTimeFormProps, DateTimeRangePicker } from './DateTimeRangePicker'; + +type ExpectedType = { + start_time_input: string; + end_time_input: string; +}; + +type MockDataType = Omit & { + title: string; + expected: ExpectedType; +}; + +describe('DateTimeRangePicker', () => { + const spy = jest.spyOn(Intl.DateTimeFormat.prototype, 'resolvedOptions'); + const INITIAL_TIME_RANGE: AbsoluteTimeRange = { + start: new Date('2026-03-09T10:00:00+01:00'), + end: new Date('2026-03-09T11:00:00+01:00'), + }; + + const onCancel = jest.fn(); + const MOCK_DATA_COLLECTIONS: MockDataType[] = [ + { + title: 'should consider local time zone', + timeZone: 'local', + initialTimeRange: INITIAL_TIME_RANGE, + onCancel, + expected: { + start_time_input: '2026-03-09 10:00:00', + end_time_input: '2026-03-09 11:00:00', + }, + }, + { + title: 'should consider local time zone', + timeZone: 'browser', + initialTimeRange: INITIAL_TIME_RANGE, + onCancel, + + expected: { + start_time_input: '2026-03-09 10:00:00', + end_time_input: '2026-03-09 11:00:00', + }, + }, + { + title: 'should consider london GMT+0 time zone', + timeZone: 'Europe/London', + initialTimeRange: INITIAL_TIME_RANGE, + onCancel, + + expected: { + start_time_input: '2026-03-09 09:00:00', + end_time_input: '2026-03-09 10:00:00', + }, + }, + ]; + + MOCK_DATA_COLLECTIONS.forEach((mock) => { + const { title, initialTimeRange, onCancel, timeZone, expected } = mock; + + spy.mockReturnValue({ + timeZone: 'Europe/Berlin', + locale: 'en-US', + calendar: 'gregory', + numberingSystem: 'latn', + }); + + test(title, () => { + render( + + ); + + Object.keys(expected).forEach((k) => { + const element = screen.getByTestId(k); + expect(element).toBeInTheDocument(); + const text = within(element).getByDisplayValue(expected[k as keyof ExpectedType]); + expect(text).toBeInTheDocument(); + }); + }); + + test('onChange should receive the local time regardless of the timezone', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const onChange = jest.fn<[AbsoluteTimeRange], any[]>(); + render( + + ); + const applyButton = screen.getByRole('button', { name: /apply/i }); + expect(applyButton).toBeInTheDocument(); + userEvent.click(applyButton); + expect(onChange).toHaveBeenLastCalledWith({ + start: new Date(INITIAL_TIME_RANGE.start), + end: new Date(INITIAL_TIME_RANGE.end), + }); + }); + }); +}); diff --git a/components/src/TimeRangeSelector/DateTimeRangePicker.tsx b/components/src/TimeRangeSelector/DateTimeRangePicker.tsx index 5000aa3..848ea80 100644 --- a/components/src/TimeRangeSelector/DateTimeRangePicker.tsx +++ b/components/src/TimeRangeSelector/DateTimeRangePicker.tsx @@ -21,7 +21,7 @@ import { ErrorBoundary } from '../ErrorBoundary'; import { ErrorAlert } from '../ErrorAlert'; import { DATE_TIME_FORMAT, validateDateRange } from './utils'; -interface AbsoluteTimeFormProps { +export interface AbsoluteTimeFormProps { initialTimeRange: AbsoluteTimeRange; onChange: (timeRange: AbsoluteTimeRange) => void; onCancel: () => void; @@ -47,7 +47,6 @@ export const DateTimeRangePicker = ({ ? Intl.DateTimeFormat().resolvedOptions().timeZone : timeZone; const [timeRange, setTimeRange] = useState(initialTimeRange); - const [showStartCalendar, setShowStartCalendar] = useState(true); const changeTimeRange = (newTime: Date, segment: keyof AbsoluteTimeRange): void => { @@ -154,6 +153,7 @@ export const DateTimeRangePicker = ({