import { render, fireEvent } from "@testing-library/react";
import React from "react";
import {
addDays,
addWeeks,
formatDate,
getMonth,
getStartOfWeek,
getWeek,
isEqual,
newDate,
} from "../date_utils";
import Week from "../week";
import { safeQuerySelector } from "./test_utils";
describe("Week", () => {
it("should have the week CSS class", () => {
const { container } = render(
,
);
expect(container.querySelector(".react-datepicker__week")).not.toBeNull();
});
it("should apply className returned from passed weekClassName prop function", () => {
const className = "customClassNameWeek";
const monthClassNameFunc = () => className;
const { container } = render(
,
);
expect(
container
.querySelector(".react-datepicker__week")
?.classList.contains(className),
).toBe(true);
});
it("should render the days of the week", () => {
const weekStart = getStartOfWeek(newDate("2015-12-20"));
const { container } = render(
,
);
const days = container.querySelectorAll(".react-datepicker__day");
expect(days.length).toBe(7);
days.forEach((day, offset) => {
const expectedDay = addDays(weekStart, offset);
expect(day.getAttribute("aria-label")).toEqual(
`Choose ${formatDate(expectedDay, "PPPP")}`,
);
});
const weekNumber = container.querySelectorAll(
".react-datepicker__week-number",
);
expect(weekNumber.length).toBe(0);
});
it("should render the week number", () => {
const weekStart = getStartOfWeek(newDate("2015-12-20"));
const { container } = render(
,
);
const days = container.querySelectorAll(".react-datepicker__day");
expect(days.length).toBe(7);
days.forEach((day, offset) => {
const expectedDay = addDays(weekStart, offset);
expect(day.getAttribute("aria-label")).toEqual(
`Choose ${formatDate(expectedDay, "PPPP")}`,
);
});
const weekNumber = container.querySelectorAll(
".react-datepicker__week-number",
);
expect(weekNumber.length).toBe(1);
});
it("should call the provided onDayClick function", () => {
let dayClicked: Date | null = null;
function onDayClick(day: Date) {
dayClicked = day;
}
const weekStart = newDate("2015-12-20");
const { container } = render(
,
);
const day = container.querySelector(".react-datepicker__day");
if (day && dayClicked) {
fireEvent.click(day);
// eslint-disable-next-line jest/no-conditional-expect
expect(day.getAttribute("aria-label")).toEqual(
`Choose ${formatDate(dayClicked, "PPPP")}`,
);
} else {
// eslint-disable-next-line jest/no-conditional-expect
expect(day).not.toBeNull();
}
});
it("should call the provided onWeekSelect function and pass the first day of the week", () => {
let firstDayReceived: Date | null = null;
function onWeekClick(newFirstWeekDay: Date) {
firstDayReceived = newFirstWeekDay;
}
const weekStart = newDate("2015-12-20");
const setOpenSpy = jest.fn();
const { container } = render(
,
);
const weekNumberElement = safeQuerySelector(
container,
".react-datepicker__week-number",
);
fireEvent.click(weekNumberElement);
expect(isEqual(firstDayReceived, weekStart)).toBe(true);
});
it("should call the provided onWeekSelect function and call the setopen function", () => {
const weekStart = newDate("2015-12-20");
const setOpenSpy = jest.fn();
const { container } = render(
{}}
setOpen={setOpenSpy}
month={getMonth(weekStart)}
/>,
);
const weekNumberElement = safeQuerySelector(
container,
".react-datepicker__week-number",
);
fireEvent.click(weekNumberElement);
expect(setOpenSpy).toHaveBeenCalledTimes(1);
});
it("should call the provided onWeekSelect function and not call the setopen function when 'shouldCloseOnSelect' is false", () => {
const weekStart = newDate("2015-12-20");
const setOpenSpy = jest.fn();
const setOnWeekSelect = jest.fn();
const { container } = render(
,
);
const weekNumberElement = safeQuerySelector(
container,
".react-datepicker__week-number",
);
fireEvent.click(weekNumberElement);
expect(setOnWeekSelect).toHaveBeenCalledTimes(1);
expect(setOpenSpy).toHaveBeenCalledTimes(0);
});
it("should call the provided onWeekSelect function and pass the week number", () => {
let weekNumberReceived: number | null = null;
function onWeekClick(_unused: Date, newWeekNumber: number) {
weekNumberReceived = newWeekNumber;
}
const weekStart = newDate("2015-12-20");
const realWeekNumber = getWeek(weekStart);
const { container } = render(
,
);
const weekNumberElement = safeQuerySelector(
container,
".react-datepicker__week-number",
);
fireEvent.click(weekNumberElement);
expect(weekNumberReceived).toBe(realWeekNumber);
});
it("should set the week number with the provided formatWeekNumber function", () => {
let firstDayReceived: Date | null = null;
function weekNumberFormatter(newFirstWeekDay: Date) {
firstDayReceived = newFirstWeekDay;
return 9;
}
const weekStart = newDate("2015-12-20");
const { container } = render(
,
);
const weekNumberElement = container.querySelector(
".react-datepicker__week-number",
);
expect(weekNumberElement).not.toBeNull();
expect(isEqual(firstDayReceived, weekStart)).toBe(true);
expect(weekNumberElement?.getAttribute("aria-label")).toBe("week 9");
});
it("should call the provided onDayMouseEnter (Mouse Event) function", () => {
const onDayMouseEnterSpy = jest.fn();
const weekStart = newDate();
const { container } = render(
,
);
const day = safeQuerySelector(container, ".react-datepicker__day");
fireEvent.mouseEnter(day);
expect(onDayMouseEnterSpy).toHaveBeenLastCalledWith(
getStartOfWeek(weekStart),
);
});
it("should call the provided onDayMouseEnter (Pointer Event) function", () => {
const onDayMouseEnterSpy = jest.fn();
const weekStart = newDate();
const { container } = render(
,
);
const day = container.querySelector(".react-datepicker__day");
if (day) {
fireEvent.pointerEnter(day);
// eslint-disable-next-line jest/no-conditional-expect
expect(onDayMouseEnterSpy).toHaveBeenLastCalledWith(
getStartOfWeek(weekStart),
);
// eslint-disable-next-line jest/no-conditional-expect
} else expect(day).not.toBeNull();
});
describe("handleWeekClick", () => {
it("should call onWeekSelect prop with correct arguments", () => {
const onWeekSelect = jest.fn();
const day = new Date("2022-02-01");
const weekNumber = 5;
const event = { target: {} } as React.MouseEvent;
let instance: Week | null;
render(
{
instance = node;
}}
day={day}
onWeekSelect={onWeekSelect}
showWeekPicker={false}
shouldCloseOnSelect={false}
setOpen={() => {}}
month={getMonth(day)}
/>,
);
instance!.handleWeekClick(day, weekNumber, event);
expect(onWeekSelect).toHaveBeenCalledWith(day, weekNumber, event);
});
it("should call handleDayClick with start of week if showWeekPicker prop is true", () => {
const day = new Date("2022-02-01");
const weekNumber = 5;
const event = { target: {} } as React.MouseEvent;
let instance: Week | null;
render(
{
instance = node;
}}
day={day}
onWeekSelect={() => {}}
showWeekPicker
shouldCloseOnSelect={false}
setOpen={() => {}}
month={getMonth(day)}
/>,
);
const handleDayClick = jest.spyOn(instance!, "handleDayClick");
instance!.handleWeekClick(day, weekNumber, event);
expect(handleDayClick).toHaveBeenCalledWith(day, event);
});
it("should call setOpen prop with false if shouldCloseOnSelect prop is true", () => {
const setOpen = jest.fn();
const day = new Date("2022-02-01");
const weekNumber = 5;
const event = { target: {} } as React.MouseEvent;
let instance: Week | null;
render(
{
instance = node;
}}
day={day}
onWeekSelect={() => {}}
showWeekPicker={false}
shouldCloseOnSelect
setOpen={setOpen}
month={getMonth(day)}
/>,
);
instance!.handleWeekClick(day, weekNumber, event);
expect(setOpen).toHaveBeenCalledWith(false);
});
});
describe("selected and keyboard-selected", () => {
it("selected is current week and preselected is also current week", () => {
const currentWeek = newDate("2023-10-22T13:09:53+02:00");
const { container } = render(
,
);
expect(
container.querySelector(".react-datepicker__week--selected"),
).not.toBeNull();
});
it("selected is current week and preselected is not current week", () => {
const currentWeek = newDate("2023-10-22T13:09:53+02:00");
const preSelection = addWeeks(currentWeek, 1);
const { container } = render(
,
);
expect(
container.querySelector(".react-datepicker__week--selected"),
).not.toBeNull();
});
it("selected is not current week and preselect is current week", () => {
const currentWeek = newDate("2023-10-22T13:09:53+02:00");
const selected = addWeeks(currentWeek, 1);
const { container } = render(
,
);
expect(
container.querySelector(".react-datepicker__week--selected"),
).toBeNull();
expect(
container.querySelector(".react-datepicker__week--keyboard-selected"),
).not.toBeNull();
});
it("select is not current week and preselect is not current week", () => {
const currentWeek = newDate("2023-10-22T13:09:53+02:00");
const selected = addWeeks(currentWeek, 1);
const { container } = render(
,
);
expect(
container.querySelector(".react-datepicker__week--selected"),
).toBeNull();
expect(
container.querySelector(".react-datepicker__week--keyboard-selected"),
).toBeNull();
});
});
describe("selected and calendarStartDay", () => {
it("should starts the selected day on the Wednesday immediately preceding that day, When the calendarStartDay Props is 3.", () => {
const calendarStartDay = 3;
const currentWeek = getStartOfWeek(
newDate("2024-03-01"),
undefined,
calendarStartDay,
);
const selected = addWeeks(currentWeek, 0);
const { container } = render(
,
);
const week = container.querySelector(".react-datepicker__week--selected");
expect(week).not.toBeNull();
const days = container.querySelectorAll(
".react-datepicker__day--selected",
);
expect(days).toHaveLength(7);
// 2024-02-28 to 2024-03-05
expect(days[0]?.textContent).toBe("28");
expect(days[1]?.textContent).toBe("29");
expect(days[2]?.textContent).toBe("1");
expect(days[3]?.textContent).toBe("2");
expect(days[4]?.textContent).toBe("3");
expect(days[5]?.textContent).toBe("4");
expect(days[6]?.textContent).toBe("5");
});
});
it("should call onDayMouseEnter when hovering over a day", () => {
const onDayMouseEnter = jest.fn();
const weekStart = newDate("2024-01-07");
const { container } = render(
,
);
const firstDay = safeQuerySelector(container, ".react-datepicker__day");
fireEvent.mouseEnter(firstDay);
expect(onDayMouseEnter).toHaveBeenCalledWith(weekStart);
});
it("should pass the first enabled day when the week starts disabled", () => {
const weekStart = newDate("2024-02-04");
const onWeekSelect = jest.fn();
const setOpenSpy = jest.fn();
const { container } = render(
,
);
const weekNumberElement = safeQuerySelector(
container,
".react-datepicker__week-number",
);
fireEvent.click(weekNumberElement);
expect(onWeekSelect).toHaveBeenCalled();
const firstEnabled = onWeekSelect.mock.calls[0][0] as Date;
expect(firstEnabled.getDate()).toBe(weekStart.getDate() + 1);
expect(setOpenSpy).toHaveBeenCalledWith(false);
});
});