Files
cunningham/packages/react/src/components/Forms/DatePicker/DateRangePicker.spec.tsx
Nathan Vasse 16dd24148b (react) update DateRangerPicker test
Due to the recent update of @react-aria/calendar the role of the calendar
has changed from group to application, the test were using this role.
2023-07-12 15:47:35 +02:00

1035 lines
30 KiB
TypeScript

import { render, screen, within } from "@testing-library/react";
import React, { FormEvent, useState } from "react";
import { expect, vi } from "vitest";
import userEvent from "@testing-library/user-event";
import { CunninghamProvider } from ":/components/Provider";
import { DateRangePicker } from ":/components/Forms/DatePicker/DateRangePicker";
import { Button } from ":/components/Button";
describe("<DateRangePicker/>", () => {
const expectDatesToBeEqual = (
firstDate: Date | string | undefined | null,
secondDate: Date | string | undefined | null
) => {
expect(firstDate).toBeDefined();
expect(secondDate).toBeDefined();
expect(new Date(firstDate!).toLocaleDateString()).eq(
new Date(secondDate!).toLocaleDateString()
);
};
const expectCalendarToBeClosed = () => {
expect(screen.queryByRole("application")).toBeNull();
};
const expectDateFieldsToBeDisplayed = () => {
expect(screen.queryAllByRole("presentation")).toBeTruthy();
};
const expectDateFieldsToBeHidden = async () => {
const dateFields = await screen.queryAllByRole("presentation");
expect(dateFields.length).eq(2);
dateFields.forEach((dateField) => {
expect(Array.from(dateField.parentElement!.classList)).contains(
"c__date-picker__inner--collapsed"
);
});
};
const expectDateRangePickerStateToBe = async (state: string) => {
const input = (await screen.findAllByRole("button"))![0];
const classNames =
input.parentElement && Array.from(input.parentElement.classList);
expect(classNames).contains(`c__date-picker--${state}`);
};
const expectCalendarToBeOpen = () => {
const calendar = screen.queryByRole("application");
expect(calendar).toBeDefined();
expect(calendar).not.toBeNull();
expect(Array.from(calendar!.classList)).contains(
"c__calendar__wrapper--opened"
);
};
const expectedSelectedCells = (selectionSize: number) => {
const selectedCells = screen.queryAllByRole("gridcell", {
selected: true,
});
expect(selectedCells.length).eq(selectionSize);
};
it("toggles calendar", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Pick a date"
endLabel="Pick a date"
name="datepicker"
/>
</CunninghamProvider>
);
const [input, button] = await screen.findAllByRole("button");
// It returns the clickable div.
expect(input.tagName).toEqual("DIV");
// It returns the toggle button.
expect(button.tagName).toEqual("BUTTON");
// Calendar is initially closed.
expectCalendarToBeClosed();
await expectDateFieldsToBeHidden();
// Toggle button opens the calendar.
await user.click(button);
expectCalendarToBeOpen();
expectDateFieldsToBeDisplayed();
// Clicking again closes the calendar.
await user.click(button);
expectCalendarToBeClosed();
await expectDateFieldsToBeHidden();
// Click on the input opens the calendar.
await user.click(input);
expectCalendarToBeOpen();
expectDateFieldsToBeDisplayed();
// Clicking again on the input should not close the calendar.
// Click could happen while selecting the date field input.
await user.click(input);
expectCalendarToBeOpen();
expectDateFieldsToBeDisplayed();
// While the calendar open, clicking on
// the toggle button closes the calendar.
await user.click(button);
expectCalendarToBeClosed();
});
it("focuses in the right order with no picked date range", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
/>
</CunninghamProvider>
);
// Get elements that should receive focus when no date is picked.
const [input, toggleButton] = await screen.findAllByRole("button")!;
await user.keyboard("{Tab}");
expect(input).toHaveFocus();
expectCalendarToBeClosed();
await user.keyboard("{Tab}");
expect(toggleButton).toHaveFocus();
expectCalendarToBeClosed();
await user.keyboard("{Enter}");
expectCalendarToBeOpen();
expectedSelectedCells(0);
});
it.each([
["2022-05-25", "2022-05-26"],
["25 Mar 2025", "2029-05-26"],
["2023-06-01T13:50", "2024-05-26"],
])("has a default value", async (start: string, end: string) => {
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={[start, end]}
/>
</CunninghamProvider>
);
// Get picked date.
const [startInput, endInput] = await screen.queryAllByRole("presentation");
expectDatesToBeEqual(start, startInput.textContent);
expectDatesToBeEqual(end, endInput.textContent);
expectDateFieldsToBeDisplayed();
});
it("focuses in the right order with a default value", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={["2023-04-25", "2023-05-25"]}
/>
</CunninghamProvider>
);
// Get elements that should receive focus when a date is already picked.
const [input, toggleButton] = await screen.findAllByRole("button")!;
const clearButton = screen.getByRole("button", {
name: "Clear date",
});
const [
monthStartSegment,
dayStartSegment,
yearStartSegment,
monthEndSegment,
dayEndSegment,
yearEndSegment,
] = await screen.findAllByRole("spinbutton")!;
// Navigate through elements using Tab.
await user.keyboard("{Tab}");
expect(input).toHaveFocus();
await user.keyboard("{Tab}");
expect(toggleButton).toHaveFocus();
await user.keyboard("{Tab}");
expect(monthStartSegment).toHaveFocus();
await user.keyboard("{Tab}");
expect(dayStartSegment).toHaveFocus();
await user.keyboard("{Tab}");
expect(yearStartSegment).toHaveFocus();
await user.keyboard("{Tab}");
expect(monthEndSegment).toHaveFocus();
await user.keyboard("{Tab}");
expect(dayEndSegment).toHaveFocus();
await user.keyboard("{Tab}");
expect(yearEndSegment).toHaveFocus();
await user.keyboard("{Tab}");
expect(clearButton).toHaveFocus();
});
it("picks a date range", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
/>
</CunninghamProvider>
);
const [input, toggleButton] = await screen.findAllByRole("button");
await user.click(input);
// Select all grid-cells.
const gridCells = await screen.findAllByRole("gridcell");
// Select the first clickable grid-cell.
const startGridCellButton = within(
gridCells.filter(
(gridCell) => !gridCell.getAttribute("aria-disabled")
)![0]
).getByRole("button")!;
// Pick a start date.
const gridCellStartDate = startGridCellButton.getAttribute("aria-label");
await user.click(startGridCellButton);
expectCalendarToBeOpen();
// Select the second clickable grid-cell.
const endGridCellButton = within(
gridCells.filter(
(gridCell) => !gridCell.getAttribute("aria-disabled")
)![1]
).getByRole("button")!;
// Pick an end date.
const gridCellEndDate = endGridCellButton.getAttribute("aria-label");
await user.click(endGridCellButton);
// Calendar should close on range's selection.
expectCalendarToBeClosed();
expectDateFieldsToBeDisplayed();
// Reopen the calendar.
await user.click(toggleButton);
// Get the selected cells in calendar grid.
const selectedCells = screen.queryAllByRole("gridcell", {
selected: true,
})!;
// Extract the selected range
const selectedRange = within(selectedCells[0])
.getByRole("button")!
.getAttribute("aria-label")
?.replace("selected", "");
// Make sure start and end dates are in the selected range,
// that describes the range with its start and end date.
expect(selectedRange).contains(gridCellStartDate);
expect(selectedRange).contains(gridCellEndDate);
// Get the selected date in the date field.
const [startInput, endInput] = await screen.queryAllByRole("presentation");
expectDatesToBeEqual(gridCellStartDate, startInput.textContent);
expectDatesToBeEqual(gridCellEndDate, endInput.textContent);
});
it("picks a date range with start and end date equal", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
/>
</CunninghamProvider>
);
const [input, toggleButton] = await screen.findAllByRole("button");
await user.click(input);
// Select all grid-cells.
const gridCells = await screen.findAllByRole("gridcell");
// Select the first clickable grid-cell.
const gridCellButton = within(
gridCells.filter(
(gridCell) => !gridCell.getAttribute("aria-disabled")
)![0]
).getByRole("button")!;
// Pick a start date.
const gridCellDate = gridCellButton.getAttribute("aria-label");
await user.click(gridCellButton);
expectCalendarToBeOpen();
// Click again on the same date, to select the end date.
await user.click(gridCellButton);
// Calendar should close on range's selection.
expectCalendarToBeClosed();
expectDateFieldsToBeDisplayed();
// Reopen the calendar.
await user.click(toggleButton);
// Get the selected cells in calendar grid.
const selectedCells = screen.queryAllByRole("gridcell", {
selected: true,
})!;
// Extract the selected range
const selectedRange = within(selectedCells[0])
.getByRole("button")!
.getAttribute("aria-label")
?.replace("selected", "");
// Make sure start and end dates are in the selected range,
// that describes the range with its start and end date.
expect(selectedRange).contains(gridCellDate);
expect(selectedRange).contains(gridCellDate);
// Get the selected date in the date field.
const [startInput, endInput] = await screen.queryAllByRole("presentation");
expectDatesToBeEqual(gridCellDate, startInput.textContent);
expectDatesToBeEqual(gridCellDate, endInput.textContent);
});
it("picks a date range using keyboard", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
defaultValue={["2023-01-01", "2023-01-01"]}
name="datepicker"
/>
</CunninghamProvider>
);
const input = (await screen.findAllByRole("button"))![0];
await user.click(input);
expectCalendarToBeOpen();
// Start range selection using keyboard.
await user.keyboard("{Enter}");
expectCalendarToBeOpen();
expectedSelectedCells(1);
// Select the next cell.
await user.keyboard("{ArrowRight}");
expectCalendarToBeOpen();
expectedSelectedCells(2);
// Select the next cell.
await user.keyboard("{ArrowRight}");
expectCalendarToBeOpen();
expectedSelectedCells(3);
// End range selection using keyboard.
await user.keyboard("{Enter}");
expectCalendarToBeClosed();
await user.click(input);
expectCalendarToBeOpen();
expectedSelectedCells(3);
const selectedCells = screen.getAllByRole("gridcell", {
selected: true,
});
// Extract the selected range
const selectedRange = within(selectedCells[0])
.getByRole("button")!
.getAttribute("aria-label")
?.replace("selected", "");
// Make sure start and end dates are in the selected range.
expect(selectedRange).contains("January 1");
expect(selectedRange).not.contains("January 2");
expect(selectedRange).contains("January 3");
// Get the selected date in the date field.
const [startInput, endInput] = await screen.queryAllByRole("presentation");
expectDatesToBeEqual("2023-01-01", startInput.textContent);
expectDatesToBeEqual("2023-01-03", endInput.textContent);
});
it("picks a date range spanning multiple months", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={["2023-01-01", "2023-01-01"]}
/>
</CunninghamProvider>
);
const input = (await screen.findAllByRole("button"))![0];
await user.click(input);
expectCalendarToBeOpen();
const startDate = "Tuesday, January 3, 2023";
const endDate = "Tuesday, February 28, 2023";
// Select the start date.
const startGridCellButton = await screen.getByRole("button", {
name: startDate,
})!;
await user.click(startGridCellButton);
expectCalendarToBeOpen();
// Navigate to the next month.
const nextMonthButton = screen.getByRole("button", {
name: "Next month",
});
await user.click(nextMonthButton);
expectCalendarToBeOpen();
// Select the end date.
const endGridCellButton = await screen.getByRole("button", {
name: endDate,
})!;
await user.click(endGridCellButton);
expectCalendarToBeClosed();
// Reopen calendar.
await user.click(input);
// Get the selected date in the date field.
const [startInput, endInput] = await screen.queryAllByRole("presentation");
expectDatesToBeEqual(startDate, startInput.textContent);
expectDatesToBeEqual(endDate, endInput.textContent);
});
it("picks a date range spanning multiple years", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={["2023-01-01", "2023-01-01"]}
/>
</CunninghamProvider>
);
const input = (await screen.findAllByRole("button"))![0];
await user.click(input);
expectCalendarToBeOpen();
const startDate = "Tuesday, January 3, 2023";
const endDate = "Thursday, January 4, 2024";
// Select the start date.
const startGridCellButton = await screen.getByRole("button", {
name: startDate,
})!;
await user.click(startGridCellButton);
expectCalendarToBeOpen();
// Navigate to the next year.
const nextYearButton = screen.getByRole("button", {
name: "Next year",
});
await user.click(nextYearButton);
expectCalendarToBeOpen();
// Select the end date.
const endGridCellButton = await screen.getByRole("button", {
name: endDate,
})!;
await user.click(endGridCellButton);
expectCalendarToBeClosed();
// Reopen calendar.
await user.click(input);
// Get the selected date in the date field.
const [startInput, endInput] = await screen.queryAllByRole("presentation");
expectDatesToBeEqual(startDate, startInput.textContent);
expectDatesToBeEqual(endDate, endInput.textContent);
});
it("types a date range", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
/>
</CunninghamProvider>
);
// Open calendar to display text segment
const input = (await screen.findAllByRole("button"))![0];
await user.click(input);
const [
monthStartSegment,
dayStartSegment,
yearStartSegment,
monthEndSegment,
dayEndSegment,
yearEndSegment,
] = await screen.findAllByRole("spinbutton")!;
// Select the first segment, month one.
await user.click(monthStartSegment);
expect(monthStartSegment).toHaveFocus();
// Type month's start value.
await user.keyboard("{1}{2}");
expect(dayStartSegment).toHaveFocus();
// Type day's start value.
await user.keyboard("{5}");
expect(yearStartSegment).toHaveFocus();
// Type year's start value.
await user.keyboard("{2}{0}{2}{3}");
expect(monthEndSegment).toHaveFocus();
// Type month's end value.
await user.keyboard("{1}{2}");
expect(dayEndSegment).toHaveFocus();
// Type day's end value.
await user.keyboard("{6}");
expect(yearEndSegment).toHaveFocus();
// Type year's end value.
await user.keyboard("{2}{0}{2}{3}");
// Check date field value.
expectDateFieldsToBeDisplayed();
const [startInput, endInput] = await screen.queryAllByRole("presentation");
expect(startInput.textContent).eq("12/5/2023");
expect(endInput.textContent).eq("12/6/2023");
});
it("types an invalid date range", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
/>
</CunninghamProvider>
);
// Open calendar to display text segment
const input = (await screen.findAllByRole("button"))![0];
await user.click(input);
const [
monthStartSegment,
dayStartSegment,
yearStartSegment,
monthEndSegment,
dayEndSegment,
yearEndSegment,
] = await screen.findAllByRole("spinbutton")!;
// Select the first segment, month one.
await user.click(monthStartSegment);
expect(monthStartSegment).toHaveFocus();
// Type month's start value.
await user.keyboard("{1}{2}");
expect(dayStartSegment).toHaveFocus();
// Type day's start value.
await user.keyboard("{6}");
expect(yearStartSegment).toHaveFocus();
// Type year's start value.
await user.keyboard("{2}{0}{2}{3}");
expect(monthEndSegment).toHaveFocus();
// Type month's end value.
await user.keyboard("{1}{2}");
expect(dayEndSegment).toHaveFocus();
// Type day's end value.
await user.keyboard("{5}");
expect(yearEndSegment).toHaveFocus();
// Type year's end value.
await user.keyboard("{2}{0}{2}{3}");
// Check date field value.
expectDateFieldsToBeDisplayed();
const [startInput, endInput] = await screen.queryAllByRole("presentation");
expect(startInput.textContent).eq("12/6/2023");
expect(endInput.textContent).eq("12/5/2023");
// Make sure the date picker is showing error.
await expectDateRangePickerStateToBe("invalid");
});
it("has an uncontrolled and a controlled value", async () => {
vi.spyOn(console, "error").mockImplementation(() => undefined);
expect(() =>
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={["2022-05-25", "2022-05-26"]}
value={["2022-05-25", "2022-05-26"]}
/>
</CunninghamProvider>
)
).toThrow(
"You cannot use both defaultValue and value props on DateRangePicker component"
);
});
it.each([
["this_not_a_valid_date", "2022-05-12"],
["2022-05-12", "2023-13-13"],
["2025-25-05", "2022-05-12"],
])("has not a valid range value", async (start: string, end: string) => {
vi.spyOn(console, "error").mockImplementation(() => undefined);
expect(() =>
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={[start, end]}
/>
</CunninghamProvider>
)
).toThrow(
"Invalid date format when initializing props on DatePicker component"
);
});
it("has not a valid range value", async () => {
// Start date is superior to end date in the default range.
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={["2024-05-25", "2022-05-26"]}
/>
</CunninghamProvider>
);
await expectDateRangePickerStateToBe("invalid");
});
it.each([[new Date(2022, 5, 25), new Date(2022, 5, 27)]])(
"clears date",
async (start: Date, end: Date) => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={[start, end]}
/>
</CunninghamProvider>
);
const clearButton = screen.getByRole("button", {
name: "Clear date",
});
await user.click(clearButton);
expectCalendarToBeOpen();
// Date field's value should be set to a placeholder value.
const [startInput, endInput] = await screen.queryAllByRole(
"presentation"
);
expect(startInput.textContent).eq("mm/dd/yyyy");
expect(endInput.textContent).eq("mm/dd/yyyy");
const startGridCell = screen.getByRole("gridcell", {
name: `${start.getDate()}`,
})!;
// Make sure start grid-cell is not selected anymore.
expect(startGridCell.getAttribute("aria-selected")).toBeNull();
expect(
startGridCell.classList.contains(
"c__calendar__wrapper__grid__week-row__background--range--start"
)
).toBe(false);
// Make sure end grid-cell is not selected anymore.
const endGridCell = screen.getByRole("gridcell", {
name: `${end.getDate()}`,
})!;
expect(endGridCell.getAttribute("aria-selected")).toBeNull();
expect(
endGridCell.classList.contains(
"c__calendar__wrapper__grid__week-row__background--range--end"
)
).toBe(false);
// Close the calendar.
const toggleButton = (await screen.findAllByRole("button"))![1];
await user.click(toggleButton);
// Make sure the empty date field is hidden when closing the calendar.
await expectDateFieldsToBeHidden();
}
);
it.each([
["2023-01-01", "2023-01-01"],
["2023-01-01", "2023-03-01"],
])(
"has a start or a end date inferior to minValue",
async (start: string, end: string) => {
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={[start, end]}
minValue="2023-02-01"
/>
</CunninghamProvider>
);
await expectDateRangePickerStateToBe("invalid");
}
);
it.each([
["2023-01-01", "2023-03-01"],
["2023-03-01", "2023-03-01"],
])(
"has a start or a end date superior to maxValue",
async (start: string, end: string) => {
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={[start, end]}
maxValue="2023-02-01"
/>
</CunninghamProvider>
);
await expectDateRangePickerStateToBe("invalid");
}
);
it("renders disabled", async () => {
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={["2023-01-01", "2023-01-01"]}
disabled={true}
/>
</CunninghamProvider>
);
await expectDateRangePickerStateToBe("disabled");
const [input, button] = await screen.findAllByRole("button");
// Make sure toggle button and click on input are disabled.
expect(input.getAttribute("aria-disabled")).eq("true");
expect(button).toBeDisabled();
// Make sure the clear button is not visible and disabled.
expect(
screen.queryByRole("button", { name: "Clear date", hidden: true })
).toBeDisabled();
// Make sure each segment of the date field is disabled.
const dateFieldInputs = await screen.queryAllByRole("spinbutton");
dateFieldInputs.forEach((dateFieldInput) =>
expect(dateFieldInput).toHaveAttribute("aria-disabled")
);
});
it("renders focused", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={["2023-01-01", "2023-01-01"]}
/>
</CunninghamProvider>
);
const toggleButton = (await screen.findAllByRole("button"))![1];
await user.click(toggleButton);
expectCalendarToBeOpen();
await expectDateRangePickerStateToBe("focused");
});
it("renders a selected range", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
name="datepicker"
defaultValue={["2023-01-01", "2023-01-10"]}
/>
</CunninghamProvider>
);
// Toggle button opens the calendar.
const button = (await screen.findAllByRole("button"))![0];
await user.click(button);
const selectedCells = screen.queryAllByRole("gridcell", {
selected: true,
});
// Make sure all selected cells render the selected styling.
selectedCells.forEach((selectedCell) => {
const cellButton = within(selectedCell).getByRole("button")!;
expect(Array.from(cellButton!.classList)).contains(
"c__calendar__wrapper__grid__week-row__button--selected"
);
});
const commonClassName =
"c__calendar__wrapper__grid__week-row__background--range";
// Make sure the start of selection has the start styling.
const startCellButton = within(selectedCells[0]).getByRole("button")!;
expect(Array.from(startCellButton.parentElement!.classList)).contains(
`${commonClassName}--start`
);
// Make sure the end of selection has the end styling.
const endCellButton = within(
selectedCells[selectedCells.length - 1]
).getByRole("button")!;
expect(Array.from(endCellButton.parentElement!.classList)).contains(
`${commonClassName}--end`
);
});
it("works controlled", async () => {
const user = userEvent.setup();
const Wrapper = () => {
const [value, setValue] = useState<[string, string] | null>([
"2023-04-25",
"2023-04-26",
]);
return (
<CunninghamProvider>
<div>
<div>Value = {value?.join(" ")}|</div>
<Button onClick={() => setValue(null)}>Clear</Button>
<DateRangePicker
startLabel="Start date"
endLabel="End date"
value={value}
onChange={(e) => setValue(e)}
/>
</div>
</CunninghamProvider>
);
};
render(<Wrapper />);
// Make sure value is selected.
screen.getByText("Value = 2023-04-25 2023-04-26|");
// Make sure value is initially render in the date field component.
const [startInput, endInput] = await screen.queryAllByRole("presentation");
expectDatesToBeEqual("2023-04-25", startInput.textContent);
expectDatesToBeEqual("2023-04-26", endInput.textContent);
// Open the calendar grid.
const toggleButton = (await screen.findAllByRole("button"))![1];
await user.click(toggleButton);
expectCalendarToBeOpen();
const startGridCell = within(
await screen.getByRole("gridcell", { name: "12" })
).getByRole("button")!;
const endGridCell = within(
await screen.getByRole("gridcell", { name: "14" })
).getByRole("button")!;
// Select a new value in the calendar grid.
await user.click(startGridCell);
await user.click(endGridCell);
expectCalendarToBeClosed();
// Make sure value is selected.
screen.getByText(`Value = 2023-04-12 2023-04-14|`);
// Clear value.
const clearButton = screen.getByRole("button", {
name: "Clear",
});
await user.click(clearButton);
// Make sure value is cleared.
await expectDateFieldsToBeHidden();
screen.getByText("Value = |");
});
it("submits forms data", async () => {
let formData: any;
const Wrapper = () => {
const onSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const data = new FormData(e.currentTarget);
formData = {
datepickerStart: data.get("datepicker_start"),
datepickerEnd: data.get("datepicker_end"),
};
};
return (
<CunninghamProvider>
<div>
<form onSubmit={onSubmit}>
<DateRangePicker
startLabel="Pick a date"
endLabel="Pick a date"
name="datepicker"
/>
<Button>Submit</Button>
</form>
</div>
</CunninghamProvider>
);
};
render(<Wrapper />);
const user = userEvent.setup();
const submitButton = screen.getByRole("button", {
name: "Submit",
});
// Submit the form being empty.
await user.click(submitButton);
expect(formData).toEqual({
datepickerStart: "",
datepickerEnd: "",
});
// Open calendar
const toggleButton = (await screen.findAllByRole("button"))![1];
await user.click(toggleButton);
const allSegments = await screen.getAllByRole("spinbutton");
const startMonthSegment = allSegments![0];
// Select the first segment, month one.
await user.click(startMonthSegment);
expect(startMonthSegment).toHaveFocus();
// Type start date's value.
await user.keyboard("{1}{0}{5}{2}{0}{2}{3}");
// Type end date's value.
await user.keyboard("{1}{2}{5}{2}{0}{2}{3}");
// Submit form being filled with a date.
await user.click(submitButton);
expectCalendarToBeClosed();
expectDateFieldsToBeDisplayed();
// Make sure form's value matches.
expect(formData).toEqual({
datepickerStart: "2023-10-05",
datepickerEnd: "2023-12-05",
});
// Clear picked date.
const clearButton = screen.getByRole("button", {
name: "Clear date",
});
await user.click(clearButton);
expectDateFieldsToBeDisplayed();
// Submit the form being empty.
await user.click(submitButton);
// Date field disappears when the user click outside the comppnent.
await expectDateFieldsToBeHidden();
// Make sure form's value is null.
expect(formData).toEqual({
datepickerStart: "",
datepickerEnd: "",
});
});
});