Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(mantine, tabledaterangepicker): close datepicker when clicking back on calendar button #3286

Merged
merged 7 commits into from
May 24, 2023
12 changes: 7 additions & 5 deletions packages/mantine/src/__tests__/VitestSetup.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import matchers, {TestingLibraryMatchers} from '@testing-library/jest-dom/matchers';
import type {TestingLibraryMatchers} from '@testing-library/jest-dom/matchers';
import matchers from '@testing-library/jest-dom/matchers';
import {cleanup} from '@testing-library/react';
import {expect} from 'vitest';

declare global {
namespace Vi {
interface JestAssertion<T = any> extends jest.Matchers<void, T>, TestingLibraryMatchers<T, void> {}
}
declare module 'vitest' {
interface Assertion<T = any> extends jest.Matchers<void, T>, TestingLibraryMatchers<T, void> {}
}

expect.extend(matchers);

Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation((query) => ({
Expand Down
17 changes: 9 additions & 8 deletions packages/mantine/src/components/table/TableDateRangePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {CalendarSize24Px} from '@coveord/plasma-react-icons';
import {Grid, Group, Popover, Text} from '@mantine/core';
import dayjs from 'dayjs';
import {FunctionComponent, useState} from 'react';
import {FunctionComponent} from 'react';

import {useToggle} from '@mantine/hooks';
import {Button} from '../button';
import {
DateRangePickerInlineCalendar,
Expand Down Expand Up @@ -33,27 +34,27 @@ export const TableDateRangePicker: FunctionComponent<TableDateRangePickerProps>
presets = {},
rangeCalendarProps,
}) => {
const [opened, setOpened] = useState(false);
const [opened, toggleOpened] = useToggle();
const {form} = useTable();

const onApply = (dates: DateRangePickerValue) => {
form.setFieldValue('dateRange', dates);
setOpened(false);
toggleOpened(false);
};
const onCancel = () => {
setOpened(false);
toggleOpened(false);
};

const formatDate = (date: Date) => dayjs(date).format('MMM DD, YYYY');
const formatedRange = `${formatDate(form.values.dateRange[0])} - ${formatDate(form.values.dateRange[1])}`;
const formattedRange = `${formatDate(form.values.dateRange[0])} - ${formatDate(form.values.dateRange[1])}`;

return (
<Grid.Col span="content" order={TableComponentsOrder.DateRangePicker} py="sm">
<Group spacing="xs">
<Text span>{formatedRange}</Text>
<Popover opened={opened} onChange={setOpened} withinPortal>
<Text span>{formattedRange}</Text>
<Popover opened={opened} onChange={toggleOpened} withinPortal>
<Popover.Target>
<Button variant="outline" color="gray" onClick={() => setOpened(true)} px="xs">
<Button variant="outline" color="gray" onClick={() => toggleOpened()} px="xs">
<CalendarSize24Px width={24} height={24} />
</Button>
</Popover.Target>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import {ColumnDef, createColumnHelper} from '@tanstack/table-core';
import {render, screen, userEvent, waitFor} from '@test-utils';
import {act} from 'react-dom/test-utils';

import {Table} from '../Table';

type RowData = {name: string};

const columnHelper = createColumnHelper<RowData>();
const columns: Array<ColumnDef<RowData>> = [columnHelper.accessor('name', {enableSorting: false})];
const basicTableWithDateRangePicker = (
<Table
data={[{name: 'fruit'}, {name: 'vegetable'}]}
columns={columns}
initialState={{dateRange: [new Date(2022, 0, 1), new Date(2022, 0, 7)]}}
>
<Table.Header>
<Table.DateRangePicker />
</Table.Header>
</Table>
);

// Since we're mocking the date and the animations are timer based we're mocking useReduceMotion to disable all the animations
// I tried wrapping the components in <MantineProvider theme={{components: {Transition: {defaultProps: {duration: 0}}}}}>
Expand All @@ -20,8 +32,6 @@ vi.mock('@mantine/hooks', async () => {
});

describe('Table.DateRangePicker', () => {
// vi.setTimeout(15000);

beforeEach(() => {
vi.useFakeTimers().setSystemTime(new Date(2022, 0, 15));
});
Expand All @@ -30,24 +40,41 @@ describe('Table.DateRangePicker', () => {
vi.useRealTimers();
});

it('displays the intial dates', async () => {
render(
<Table
data={[{name: 'fruit'}, {name: 'vegetable'}]}
columns={columns}
initialState={{dateRange: [new Date(2022, 0, 1), new Date(2022, 0, 7)]}}
>
<Table.Header>
<Table.DateRangePicker />
</Table.Header>
</Table>
);
it('displays the initial dates', async () => {
render(basicTableWithDateRangePicker);

await waitFor(() => {
expect(screen.getByText('Jan 01, 2022 - Jan 07, 2022')).toBeVisible();
});
});

it('opens the dialog when clicking on the calendar button', async () => {
// Otherwise, css transition is not triggered in Mantine component
vi.useRealTimers();
const user = userEvent.setup({delay: null});
render(basicTableWithDateRangePicker);

await screen.findByRole('button', {name: 'calendar'});
await act(async () => {
await user.click(screen.getByRole('button', {name: 'calendar'}));
});
expect(screen.queryByRole('dialog')).toBeVisible();
});

it('closes the dialog when clicking back on the calendar button', async () => {
// Otherwise, css transition is not triggered in Mantine component
vi.useRealTimers();
const user = userEvent.setup({delay: null});
render(basicTableWithDateRangePicker);

await screen.findByRole('button', {name: 'calendar'});
await act(async () => {
await user.click(screen.getByRole('button', {name: 'calendar'}));
await user.click(screen.getByRole('button', {name: 'calendar'}));
});
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});

it('displays the selected date range in the table', async () => {
const user = userEvent.setup({delay: null});
const onChange = vi.fn();
Expand Down