import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
import TimeRangeSelector from 'sentry/components/organizations/timeRangeSelector';
import ConfigStore from 'sentry/stores/configStore';
describe('TimeRangeSelector', function () {
const onChange = jest.fn();
const routerContext = TestStubs.routerContext();
const organization = TestStubs.Organization();
function getComponent(props = {}) {
return (
);
}
function renderComponent(props = {}) {
return render(getComponent(props), {context: routerContext});
}
beforeEach(function () {
ConfigStore.loadInitialData({
user: {options: {timezone: 'America/New_York'}},
});
onChange.mockReset();
});
it('renders when given relative period not in dropdown', function () {
render(
,
{context: routerContext}
);
expect(screen.getByText('Last 9 days')).toBeInTheDocument();
});
it('renders when given an invalid relative period', function () {
render(
,
{context: routerContext}
);
expect(screen.getByText('Invalid period')).toBeInTheDocument();
});
it('hides relative and absolute selectors', function () {
render(
,
{context: routerContext}
);
userEvent.click(screen.getByRole('button'));
// Ensure none of the relative options are shown
expect(screen.queryByTestId('1h')).not.toBeInTheDocument();
expect(screen.queryByTestId('24h')).not.toBeInTheDocument();
expect(screen.queryByTestId('7d')).not.toBeInTheDocument();
expect(screen.queryByTestId('14d')).not.toBeInTheDocument();
expect(screen.queryByTestId('30d')).not.toBeInTheDocument();
expect(screen.queryByTestId('90d')).not.toBeInTheDocument();
// Ensure absolute option not shown
expect(screen.queryByTestId('absolute')).not.toBeInTheDocument();
});
it('does not open selector menu when disabled', function () {
renderComponent({disabled: true});
userEvent.click(screen.getByRole('button'));
// Dropdown not open
expect(screen.queryByText(/last hour/i)).not.toBeInTheDocument();
});
it('selects absolute item', async function () {
renderComponent();
userEvent.click(screen.getByRole('button'));
expect(screen.queryByTestId('date-range')).not.toBeInTheDocument();
userEvent.click(await screen.findByTestId('absolute'));
const newProps = {
relative: null,
start: new Date('2017-10-03T02:41:20.000Z'),
end: new Date('2017-10-17T02:41:20.000Z'),
};
expect(onChange).toHaveBeenLastCalledWith(newProps);
expect(await screen.findByTestId('date-range')).toBeInTheDocument();
});
it('selects absolute item with utc enabled', async function () {
renderComponent({utc: true});
userEvent.click(screen.getByRole('button'));
expect(screen.queryByTestId('date-range')).not.toBeInTheDocument();
userEvent.click(await screen.findByTestId('absolute'));
const newProps = {
relative: null,
start: new Date('2017-10-02T22:41:20.000Z'),
end: new Date('2017-10-16T22:41:20.000Z'),
utc: true,
};
expect(onChange).toHaveBeenLastCalledWith(newProps);
expect(await screen.findByTestId('date-range')).toBeInTheDocument();
});
it('switches from relative to absolute while maintaining equivalent date range', async function () {
const {rerender} = renderComponent({
relative: '7d',
utc: false,
});
userEvent.click(screen.getByRole('button'));
userEvent.click(await screen.findByTestId('absolute'));
expect(onChange).toHaveBeenCalledWith({
relative: null,
start: new Date('2017-10-10T02:41:20.000Z'),
end: new Date('2017-10-17T02:41:20.000Z'),
utc: false,
});
userEvent.click(screen.getByTestId('14d'));
expect(onChange).toHaveBeenLastCalledWith({
relative: '14d',
start: undefined,
end: undefined,
});
rerender(
getComponent({
relative: '14d',
utc: false,
})
);
userEvent.click(screen.getByRole('button'));
userEvent.click(await screen.findByTestId('absolute'));
expect(onChange).toHaveBeenLastCalledWith({
relative: null,
start: new Date('2017-10-03T02:41:20.000Z'),
end: new Date('2017-10-17T02:41:20.000Z'),
utc: false,
});
});
it('switches from relative to absolute while maintaining equivalent date range (in utc)', async function () {
const {rerender} = renderComponent({
relative: '7d',
utc: true,
});
userEvent.click(screen.getByRole('button'));
userEvent.click(await screen.findByTestId('absolute'));
expect(onChange).toHaveBeenCalledWith({
relative: null,
start: new Date('2017-10-09T22:41:20.000Z'),
end: new Date('2017-10-16T22:41:20.000Z'),
utc: true,
});
userEvent.click(screen.getByTestId('14d'));
expect(onChange).toHaveBeenLastCalledWith({
relative: '14d',
start: undefined,
end: undefined,
});
rerender(
getComponent({
relative: '14d',
utc: true,
})
);
userEvent.click(screen.getByRole('button'));
userEvent.click(await screen.findByTestId('absolute'));
expect(onChange).toHaveBeenLastCalledWith({
relative: null,
start: new Date('2017-10-02T22:41:20.000Z'),
end: new Date('2017-10-16T22:41:20.000Z'),
utc: true,
});
});
it('switches from relative to absolute and then toggling UTC (starting with UTC)', async function () {
renderComponent({
relative: '7d',
utc: true,
});
userEvent.click(screen.getByRole('button'));
// Local time is 22:41:20-0500 -- this is what date picker should show
userEvent.click(await screen.findByTestId('absolute'));
expect(onChange).toHaveBeenCalledWith({
relative: null,
start: new Date('2017-10-09T22:41:20.000Z'),
end: new Date('2017-10-16T22:41:20.000Z'),
utc: true,
});
userEvent.click(screen.getByRole('checkbox'));
expect(onChange).toHaveBeenLastCalledWith({
relative: null,
start: new Date('2017-10-09T22:41:20.000Z'),
end: new Date('2017-10-16T22:41:20.000Z'),
utc: false,
});
userEvent.click(screen.getByRole('checkbox'));
expect(onChange).toHaveBeenLastCalledWith({
relative: null,
start: new Date('2017-10-10T02:41:20.000Z'),
end: new Date('2017-10-17T02:41:20.000Z'),
utc: true,
});
});
it('switches from relative to absolute and then toggling UTC (starting with non-UTC)', async function () {
renderComponent({
relative: '7d',
utc: false,
});
userEvent.click(screen.getByRole('button'));
userEvent.click(await screen.findByTestId('absolute'));
expect(onChange).toHaveBeenCalledWith({
relative: null,
start: new Date('2017-10-09T22:41:20.000-0400'),
end: new Date('2017-10-16T22:41:20.000-0400'),
utc: false,
});
userEvent.click(screen.getByRole('checkbox'));
expect(onChange).toHaveBeenLastCalledWith({
relative: null,
start: new Date('2017-10-10T02:41:20.000Z'),
end: new Date('2017-10-17T02:41:20.000Z'),
utc: true,
});
userEvent.click(screen.getByRole('checkbox'));
expect(onChange).toHaveBeenLastCalledWith({
relative: null,
start: new Date('2017-10-09T22:41:20.000Z'),
end: new Date('2017-10-16T22:41:20.000Z'),
utc: false,
});
});
it('maintains time when switching UTC to local time', function () {
// Times should never change when changing UTC option
// Instead, the utc flagged is used when querying to create proper date
let state;
const {rerender} = renderComponent({
relative: null,
start: new Date('2017-10-10T00:00:00.000Z'),
end: new Date('2017-10-17T23:59:59.000Z'),
utc: true,
});
userEvent.click(screen.getByRole('button'));
// Local
userEvent.click(screen.getByRole('checkbox'));
state = {
relative: null,
start: new Date('2017-10-10T00:00:00.000Z'),
end: new Date('2017-10-17T23:59:59.000Z'),
utc: false,
};
expect(onChange).toHaveBeenLastCalledWith(state);
rerender(getComponent(state));
// UTC
userEvent.click(screen.getByRole('checkbox'));
state = {
relative: null,
start: new Date('2017-10-10T00:00:00.000Z'),
end: new Date('2017-10-17T23:59:59.000Z'),
utc: true,
};
expect(onChange).toHaveBeenLastCalledWith(state);
rerender(getComponent(state));
// Local
userEvent.click(screen.getByRole('checkbox'));
expect(onChange).toHaveBeenLastCalledWith({
relative: null,
start: new Date('2017-10-10T00:00:00.000Z'),
end: new Date('2017-10-17T23:59:59.000Z'),
utc: false,
});
});
it('deselects default filter when absolute date selected', async function () {
renderComponent({
relative: '14d',
utc: false,
});
userEvent.click(screen.getByRole('button'));
userEvent.click(await screen.findByTestId('absolute'));
});
it('uses the default absolute date', async function () {
renderComponent({
defaultAbsolute: {
start: new Date('2017-10-10T00:00:00.000Z'),
end: new Date('2017-10-17T23:59:59.000Z'),
},
});
userEvent.click(screen.getByRole('button'));
userEvent.click(await screen.findByTestId('absolute'));
expect(onChange).toHaveBeenCalledWith({
relative: null,
start: new Date('2017-10-10T00:00:00.000Z'),
end: new Date('2017-10-17T23:59:59.000Z'),
});
});
it('uses the current absolute date if provided', async function () {
renderComponent({
start: new Date('2022-06-12T00:00:00.000Z'),
end: new Date('2022-06-14T00:00:00.000Z'),
});
userEvent.click(screen.getByRole('button'));
userEvent.click(await screen.findByTestId('absolute'));
// On change should not be called because start/end did not change
expect(onChange).not.toHaveBeenCalled();
});
it('can select arbitrary relative time ranges', () => {
renderComponent();
userEvent.click(screen.getByRole('button'));
const input = screen.getByRole('textbox');
userEvent.type(input, '5');
// With just the number "5", all unit options should be present
expect(screen.getByText('Last 5 seconds')).toBeInTheDocument();
expect(screen.getByText('Last 5 minutes')).toBeInTheDocument();
expect(screen.getByText('Last 5 hours')).toBeInTheDocument();
expect(screen.getByText('Last 5 days')).toBeInTheDocument();
expect(screen.getByText('Last 5 weeks')).toBeInTheDocument();
userEvent.type(input, 'd');
// With "5d", only "Last 5 days" should be shown
expect(screen.getByText('Last 5 days')).toBeInTheDocument();
expect(screen.queryByText('Last 5 seconds')).not.toBeInTheDocument();
expect(screen.queryByText('Last 5 minutes')).not.toBeInTheDocument();
expect(screen.queryByText('Last 5 hours')).not.toBeInTheDocument();
expect(screen.queryByText('Last 5 weeks')).not.toBeInTheDocument();
userEvent.type(input, 'ays');
// "5days" Should still show "Last 5 days" option
expect(screen.getByText('Last 5 days')).toBeInTheDocument();
userEvent.type(input, '{Enter}');
expect(onChange).toHaveBeenLastCalledWith({
relative: '5d',
start: undefined,
end: undefined,
});
});
it('cannot select arbitrary relative time ranges with disallowArbitraryRelativeRanges', () => {
renderComponent({disallowArbitraryRelativeRanges: true});
userEvent.click(screen.getByRole('button'));
const input = screen.getByRole('textbox');
userEvent.type(input, '5');
expect(screen.getByText('No items found')).toBeInTheDocument();
userEvent.type(input, '{Enter}');
expect(onChange).not.toHaveBeenCalled();
});
});