Skip to content

Commit

Permalink
feat(CalendarFrame): adding previous calendar quarter (apache#31889)
Browse files Browse the repository at this point in the history
Co-authored-by: Diego Pucci <[email protected]>
  • Loading branch information
alexandrusoare and geido authored Jan 22, 2025
1 parent b74da79 commit e4e07ee
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 2 deletions.
9 changes: 7 additions & 2 deletions superset-frontend/src/GlobalStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,16 @@ export const GlobalStyles = () => (
.echarts-tooltip[style*='visibility: hidden'] {
display: none !important;
}
// Ant Design is applying inline z-index styles causing troubles
// TODO: Remove z-indexes when Ant Design is fully upgraded to v5
// Prefer vanilla Ant Design z-indexes that should work out of the box
.ant-popover,
.antd5-dropdown,
.ant-dropdown,
.ant-select-dropdown {
z-index: ${theme.zIndex.max};
.ant-select-dropdown,
.antd5-modal-wrap,
.antd5-modal-mask {
z-index: ${theme.zIndex.max} !important;
}
// TODO: Remove when buttons have been upgraded to Ant Design 5.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 { render, screen, fireEvent } from 'spec/helpers/testing-library';
import { CalendarFrame } from '../components/CalendarFrame';
import { PreviousCalendarWeek, PreviousCalendarQuarter } from '../types';
import { CALENDAR_RANGE_OPTIONS } from '../utils/constants';

describe('CalendarFrame', () => {
it('calls onChange with PreviousCalendarWeek if value is not in CALENDAR_RANGE_SET', () => {
const mockOnChange = jest.fn();
render(<CalendarFrame onChange={mockOnChange} value="invalid-value" />);

expect(mockOnChange).toHaveBeenCalledWith(PreviousCalendarWeek);
});

it('renders null if value is not in CALENDAR_RANGE_SET', () => {
render(<CalendarFrame onChange={jest.fn()} value="invalid-value" />);
expect(
screen.queryByText('Configure Time Range: Previous...'),
).not.toBeInTheDocument();
});

it('renders the correct number of radio options', () => {
render(<CalendarFrame onChange={jest.fn()} value={PreviousCalendarWeek} />);
const radios = screen.getAllByRole('radio');
expect(radios).toHaveLength(CALENDAR_RANGE_OPTIONS.length);
CALENDAR_RANGE_OPTIONS.forEach(option => {
expect(screen.getByText(option.label)).toBeInTheDocument();
});
});

it('calls onChange with the correct value when a radio button is selected', () => {
const mockOnChange = jest.fn();
render(
<CalendarFrame
onChange={mockOnChange}
value={CALENDAR_RANGE_OPTIONS[0].value}
/>,
);

const secondOption = CALENDAR_RANGE_OPTIONS[1];
const radio = screen.getByLabelText(secondOption.label);
fireEvent.click(radio);

expect(mockOnChange).toHaveBeenCalledWith(secondOption.value);
});

it('renders the section title correctly', () => {
render(
<CalendarFrame
onChange={jest.fn()}
value={CALENDAR_RANGE_OPTIONS[0].value}
/>,
);
expect(
screen.getByText('Configure Time Range: Previous...'),
).toBeInTheDocument();
});

it('ensures the third option is PreviousCalendarQuarter', () => {
render(
<CalendarFrame
onChange={jest.fn()}
value={CALENDAR_RANGE_OPTIONS[0].value}
/>,
);

const thirdOption = CALENDAR_RANGE_OPTIONS[2];
expect(thirdOption.value).toBe(PreviousCalendarQuarter);

expect(screen.getByLabelText(thirdOption.label)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,12 @@ export type CommonRangeType =

export const PreviousCalendarWeek = 'previous calendar week';
export const PreviousCalendarMonth = 'previous calendar month';
export const PreviousCalendarQuarter = 'previous calendar quarter';
export const PreviousCalendarYear = 'previous calendar year';
export type CalendarRangeType =
| typeof PreviousCalendarWeek
| typeof PreviousCalendarMonth
| typeof PreviousCalendarQuarter
| typeof PreviousCalendarYear;

export const CurrentDay = 'Current day';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
SelectOptionType,
PreviousCalendarWeek,
PreviousCalendarMonth,
PreviousCalendarQuarter,
PreviousCalendarYear,
CommonRangeType,
CalendarRangeType,
Expand Down Expand Up @@ -56,6 +57,7 @@ export const COMMON_RANGE_VALUES_SET = new Set(
export const CALENDAR_RANGE_OPTIONS: SelectOptionType[] = [
{ value: PreviousCalendarWeek, label: t('previous calendar week') },
{ value: PreviousCalendarMonth, label: t('previous calendar month') },
{ value: PreviousCalendarQuarter, label: t('previous calendar quarter') },
{ value: PreviousCalendarYear, label: t('previous calendar year') },
];
export const CALENDAR_RANGE_VALUES_SET = new Set(
Expand Down Expand Up @@ -119,6 +121,7 @@ export const COMMON_RANGE_SET: Set<CommonRangeType> = new Set([
export const CALENDAR_RANGE_SET: Set<CalendarRangeType> = new Set([
PreviousCalendarWeek,
PreviousCalendarMonth,
PreviousCalendarQuarter,
PreviousCalendarYear,
]);

Expand Down
9 changes: 9 additions & 0 deletions superset/utils/date_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,15 @@ def get_since_until( # pylint: disable=too-many-arguments,too-many-locals,too-m
and separator not in time_range
):
time_range = "DATETRUNC(DATEADD(DATETIME('today'), -1, MONTH), MONTH) : DATETRUNC(DATETIME('today'), MONTH)" # pylint: disable=line-too-long,useless-suppression # noqa: E501
if (
time_range
and time_range.startswith("previous calendar quarter")
and separator not in time_range
):
time_range = (
"DATETRUNC(DATEADD(DATETIME('today'), -1, QUARTER), QUARTER) : "
"DATETRUNC(DATETIME('today'), QUARTER)" # pylint: disable=line-too-long,useless-suppression # noqa: E501
)
if (
time_range
and time_range.startswith("previous calendar year")
Expand Down
28 changes: 28 additions & 0 deletions tests/unit_tests/utils/date_parser_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from typing import Optional
from unittest.mock import Mock, patch

import freezegun
import pytest
from dateutil.relativedelta import relativedelta

Expand Down Expand Up @@ -316,6 +317,33 @@ def test_get_since_until_instant_time_comparison_enabled() -> None:
assert result == expected


def test_previous_calendar_quarter():
with freezegun.freeze_time("2023-01-15"):
result = get_since_until("previous calendar quarter")
expected = (datetime(2022, 10, 1), datetime(2023, 1, 1))
assert result == expected

with freezegun.freeze_time("2023, 4, 15"):
result = get_since_until("previous calendar quarter")
expected = (datetime(2023, 1, 1), datetime(2023, 4, 1))
assert result == expected

with freezegun.freeze_time("2023, 8, 15"):
result = get_since_until("previous calendar quarter")
expected = (datetime(2023, 4, 1), datetime(2023, 7, 1))
assert result == expected

with freezegun.freeze_time("2023, 10, 15"):
result = get_since_until("previous calendar quarter")
expected = (datetime(2023, 7, 1), datetime(2023, 10, 1))
assert result == expected

with freezegun.freeze_time("2024, 1, 1"):
result = get_since_until("previous calendar quarter")
expected = (datetime(2023, 10, 1), datetime(2024, 1, 1))
assert result == expected


@patch("superset.utils.date_parser.parse_human_datetime", mock_parse_human_datetime)
def test_datetime_eval() -> None:
result = datetime_eval("datetime('now')")
Expand Down

0 comments on commit e4e07ee

Please sign in to comment.