diff --git a/src/test/calendar_icon.test.tsx b/src/test/calendar_icon.test.tsx
index 27f5c241e..1235d0c04 100644
--- a/src/test/calendar_icon.test.tsx
+++ b/src/test/calendar_icon.test.tsx
@@ -4,6 +4,7 @@ import React from "react";
import CalendarIcon from "../calendar_icon";
import { IconParkSolidApplication } from "./helper_components/calendar_icon";
+import { safeQuerySelector } from "./test_utils";
describe("CalendarIcon", () => {
let onClickMock: jest.Mock;
@@ -38,9 +39,11 @@ describe("CalendarIcon", () => {
it("should fire onClick event when the icon is clicked", () => {
const { container } = render();
- const icon = container.querySelector("svg.react-datepicker__calendar-icon");
- expect(icon).not.toBeNull();
- fireEvent.click(icon ?? new Element());
+ const icon = safeQuerySelector(
+ container,
+ "svg.react-datepicker__calendar-icon",
+ );
+ fireEvent.click(icon);
expect(onClickMock).toHaveBeenCalledTimes(1);
});
@@ -50,9 +53,8 @@ describe("CalendarIcon", () => {
,
);
- const icon = container.querySelector("i.fa-example-icon");
- expect(icon).not.toBeNull();
- fireEvent.click(icon ?? new Element());
+ const icon = safeQuerySelector(container, "i.fa-example-icon");
+ fireEvent.click(icon);
expect(onClickMock).toHaveBeenCalledTimes(1);
});
@@ -75,8 +77,11 @@ describe("CalendarIcon", () => {
/>,
);
- const icon = container.querySelector("svg.react-datepicker__calendar-icon");
- fireEvent.click(icon ?? new Element());
+ const icon = safeQuerySelector(
+ container,
+ "svg.react-datepicker__calendar-icon",
+ );
+ fireEvent.click(icon);
expect(onClickMock).toHaveBeenCalledTimes(1);
expect(onClickCustomIcon).toHaveBeenCalledTimes(1);
diff --git a/src/test/calendar_test.test.tsx b/src/test/calendar_test.test.tsx
index 0e55b3b83..f0912d721 100644
--- a/src/test/calendar_test.test.tsx
+++ b/src/test/calendar_test.test.tsx
@@ -31,7 +31,12 @@ import {
} from "../date_utils";
import DatePicker from "../index";
-import { getKey } from "./test_utils";
+import {
+ getKey,
+ SafeElementWrapper,
+ safeQuerySelector,
+ safeQuerySelectorAll,
+} from "./test_utils";
import type { ReactDatePickerCustomHeaderProps } from "../calendar";
import type { Locale } from "../date_utils";
@@ -229,8 +234,9 @@ describe("Calendar", () => {
it("should render month and year as a header of datepicker by default", () => {
const { calendar } = getCalendar();
- const header = calendar.querySelector("h2.react-datepicker__current-month");
- expect(header).not.toBeNull();
+ expect(() =>
+ calendar.querySelector("h2.react-datepicker__current-month"),
+ ).not.toThrow();
});
it("should not show the year dropdown menu by default", () => {
@@ -652,8 +658,7 @@ describe("Calendar", () => {
});
const selected = newDate(instance?.state.date);
- const prevMonth =
- calendar.querySelector(".prevMonth") ?? new HTMLElement();
+ const prevMonth = safeQuerySelector(calendar, ".prevMonth");
fireEvent.click(prevMonth);
@@ -668,8 +673,7 @@ describe("Calendar", () => {
});
const selected = newDate(instance?.state.date);
- const nextMonth =
- calendar.querySelector(".nextMonth") ?? new HTMLElement();
+ const nextMonth = safeQuerySelector(calendar, ".nextMonth");
fireEvent.click(nextMonth);
@@ -717,8 +721,7 @@ describe("Calendar", () => {
renderCustomHeader,
});
- const monthSelect =
- calendar.querySelector(".month-select") ?? new HTMLElement();
+ const monthSelect = safeQuerySelector(calendar, ".month-select");
fireEvent.change(monthSelect, { target: { value: 4 } });
const selected = newDate(instance?.state.date);
@@ -731,8 +734,7 @@ describe("Calendar", () => {
renderCustomHeader,
});
- const yearSelect =
- calendar.querySelector(".year-select") ?? new HTMLElement();
+ const yearSelect = safeQuerySelector(calendar, ".year-select");
fireEvent.change(yearSelect, { target: { value: 2017 } });
@@ -877,13 +879,15 @@ describe("Calendar", () => {
showDisabledMonthNavigation: true,
onMonthChange: onMonthChangeSpy,
});
- const prevNavigationButton =
- calendar.querySelector(".react-datepicker__navigation--previous") ??
- new HTMLElement();
+ const prevNavigationButton = safeQuerySelector(
+ calendar,
+ ".react-datepicker__navigation--previous",
+ );
- const nextNavigationButton =
- calendar.querySelector(".react-datepicker__navigation--next") ??
- new HTMLElement();
+ const nextNavigationButton = safeQuerySelector(
+ calendar,
+ ".react-datepicker__navigation--next",
+ );
fireEvent.click(prevNavigationButton);
@@ -902,13 +906,15 @@ describe("Calendar", () => {
showDisabledMonthNavigation: true,
onMonthChange: onMonthChangeSpy,
});
- const prevNavigationButton =
- calendar.querySelector(".react-datepicker__navigation--previous") ??
- new HTMLElement();
+ const prevNavigationButton = safeQuerySelector(
+ calendar,
+ ".react-datepicker__navigation--previous",
+ );
- const nextNavigationButton =
- calendar.querySelector(".react-datepicker__navigation--next") ??
- new HTMLElement();
+ const nextNavigationButton = safeQuerySelector(
+ calendar,
+ ".react-datepicker__navigation--next",
+ );
fireEvent.click(prevNavigationButton);
fireEvent.click(nextNavigationButton);
@@ -996,9 +1002,10 @@ describe("Calendar", () => {
it("should set the date when pressing todayButton", () => {
const { calendar, instance } = getCalendar({ todayButton: "Vandaag" });
- const todayButton =
- calendar.querySelector(".react-datepicker__today-button") ??
- new HTMLElement();
+ const todayButton = safeQuerySelector(
+ calendar,
+ ".react-datepicker__today-button",
+ );
fireEvent.click(todayButton);
expect(isSameDay(instance?.state.date, newDate())).toBeTruthy();
});
@@ -1031,8 +1038,7 @@ describe("Calendar", () => {
/>,
);
- const day =
- container.querySelector(".react-datepicker__day") ?? new HTMLElement();
+ const day = safeQuerySelector(container, ".react-datepicker__day");
fireEvent.mouseEnter(day);
expect(onDayMouseEnterSpy).toHaveBeenLastCalledWith(
@@ -1054,8 +1060,7 @@ describe("Calendar", () => {
/>,
);
- const day =
- container.querySelector(".react-datepicker__day") ?? new HTMLElement();
+ const day = safeQuerySelector(container, ".react-datepicker__day");
fireEvent.pointerEnter(day);
expect(onDayMouseEnterSpy).toHaveBeenLastCalledWith(
@@ -1094,11 +1099,11 @@ describe("Calendar", () => {
onSelect={() => {}}
/>,
);
- const month = container.querySelector(".react-datepicker__month");
+ const month = safeQuerySelector(container, ".react-datepicker__month");
expect(
month?.classList.contains("react-datepicker__month--selecting-range"),
).toBeTruthy();
- fireEvent.mouseLeave(month ?? new HTMLElement());
+ fireEvent.mouseLeave(month);
expect(
container
@@ -1153,10 +1158,12 @@ describe("Calendar", () => {
}}
/>,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
- const previousButton =
- container.querySelector(".react-datepicker__navigation--previous") ??
- new HTMLElement();
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+ const previousButton = safeQuerySelector(
+ container,
+ ".react-datepicker__navigation--previous",
+ );
fireEvent.click(previousButton);
expect(date).not.toBeNull();
@@ -1175,11 +1182,14 @@ describe("Calendar", () => {
}}
/>,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
- const nextButton = container.querySelector(
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+ const nextButton = safeQuerySelector(
+ container,
".react-datepicker__navigation--next",
);
- fireEvent.click(nextButton ?? new HTMLElement());
+ fireEvent.click(nextButton);
expect(date).not.toBeNull();
expect(formatDate(date!, "dd.MM.yyyy")).toBe(expectedDate);
});
@@ -1196,11 +1206,14 @@ describe("Calendar", () => {
}}
/>,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
- const previousButton = container.querySelector(
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+ const previousButton = safeQuerySelector(
+ container,
".react-datepicker__navigation--previous",
);
- fireEvent.click(previousButton ?? new HTMLElement());
+ fireEvent.click(previousButton);
expect(date).not.toBeNull();
expect(formatDate(date!, "dd.MM.yyyy")).toBe(expectedDate);
});
@@ -1216,7 +1229,7 @@ describe("Calendar", () => {
/>,
);
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
fireEvent.focus(input);
expect(onCalendarOpen).toHaveBeenCalled();
@@ -1246,28 +1259,31 @@ describe("Calendar", () => {
});
it("calls onMonthChange prop when previous month button clicked", () => {
- const select =
- calendar.querySelector(".react-datepicker__navigation--previous") ??
- new HTMLElement();
+ const select = safeQuerySelector(
+ calendar,
+ ".react-datepicker__navigation--previous",
+ );
fireEvent.click(select);
expect(onMonthChangeSpy).toHaveBeenCalled();
});
it("calls onMonthChange prop when next month button clicked", () => {
- const select =
- calendar.querySelector(".react-datepicker__navigation--next") ??
- new HTMLElement();
+ const select = safeQuerySelector(
+ calendar,
+ ".react-datepicker__navigation--next",
+ );
fireEvent.click(select);
expect(onMonthChangeSpy).toHaveBeenCalled();
});
it("calls onMonthChange prop when month changed from month dropdown", () => {
- const select =
- calendar
- .querySelector(".react-datepicker__month-dropdown-container")
- ?.querySelector("select") ?? new HTMLElement();
+ const select = new SafeElementWrapper(calendar)
+ .safeQuerySelector(".react-datepicker__month-dropdown-container")
+ .safeQuerySelector("select")
+ .getElement();
+
fireEvent.change(select, {
target: {
value: Array.from(
@@ -1299,10 +1315,11 @@ describe("Calendar", () => {
});
it("calls onYearChange prop when year changed from year dropdown", () => {
- const select =
- calendar
- .querySelector(".react-datepicker__year-dropdown-container")
- ?.querySelector("select") ?? new HTMLElement();
+ const yearDropdownContainer = safeQuerySelector(
+ calendar,
+ ".react-datepicker__year-dropdown-container",
+ );
+ const select = safeQuerySelector(yearDropdownContainer, "select");
fireEvent.change(select, {
target: {
value: Array.from(
@@ -1351,12 +1368,20 @@ describe("Calendar", () => {
it("calls onYearChange prop when selection is changed from month-year dropdown", () => {
const { calendar } = renderCalendar();
- const select =
- calendar
- .querySelector(".react-datepicker__month-year-dropdown-container")
- ?.querySelector("select") ?? new HTMLElement();
- const option =
- select?.querySelectorAll("option")[3] ?? new HTMLOptionElement();
+ const monthYearDropdownContainer = safeQuerySelector(
+ calendar,
+ ".react-datepicker__month-year-dropdown-container",
+ );
+
+ const select = safeQuerySelector(monthYearDropdownContainer, "select");
+ const minMonthYearOptionsLen = 4;
+ const options = safeQuerySelectorAll(
+ select,
+ "option",
+ minMonthYearOptionsLen,
+ );
+
+ const option = options[3]!;
fireEvent.change(select, {
target: {
value: option.value,
@@ -1368,12 +1393,18 @@ describe("Calendar", () => {
it("calls onMonthChange prop when selection is changed from month-year dropdown", () => {
const { calendar } = renderCalendar();
- const select =
- calendar
- .querySelector(".react-datepicker__month-year-dropdown-container")
- ?.querySelector("select") ?? new HTMLElement();
- const option =
- select.querySelectorAll("option")[3] ?? new HTMLOptionElement();
+
+ const monthYearDropdownContainer = safeQuerySelector(
+ calendar,
+ ".react-datepicker__month-year-dropdown-container",
+ );
+ const select = safeQuerySelector(monthYearDropdownContainer, "select");
+ const options = safeQuerySelectorAll(select, "option");
+ const option = options[3];
+ if (!option) {
+ throw new Error("option is undefined");
+ }
+
fireEvent.change(select, {
target: {
value: option.value,
@@ -1407,36 +1438,40 @@ describe("Calendar", () => {
});
it("calls onDropdownFocus prop when year select is focused", () => {
- const select =
- calendar.querySelector(".react-datepicker__year-select") ??
- new HTMLElement();
+ const select = safeQuerySelector(
+ calendar,
+ ".react-datepicker__year-select",
+ );
fireEvent.focus(select);
expect(onDropdownFocusSpy).toHaveBeenCalled();
});
it("calls onDropdownFocus prop when month select is focused", () => {
- const select =
- calendar.querySelector(".react-datepicker__month-select") ??
- new HTMLElement();
+ const select = safeQuerySelector(
+ calendar,
+ ".react-datepicker__month-select",
+ );
fireEvent.focus(select);
expect(onDropdownFocusSpy).toHaveBeenCalled();
});
it("calls onDropdownFocus prop when year-month select is focused", () => {
- const select =
- calendar.querySelector(".react-datepicker__month-year-select") ??
- new HTMLElement();
+ const select = safeQuerySelector(
+ calendar,
+ ".react-datepicker__month-year-select",
+ );
fireEvent.focus(select);
expect(onDropdownFocusSpy).toHaveBeenCalled();
});
it("does not call onDropdownFocus prop when the dropdown container div is focused", () => {
- const select =
- calendar.querySelector(".react-datepicker__header__dropdown") ??
- new HTMLElement();
+ const select = safeQuerySelector(
+ calendar,
+ ".react-datepicker__header__dropdown",
+ );
fireEvent.focus(select);
expect(onDropdownFocusSpy).toHaveBeenCalledTimes(0);
@@ -2272,10 +2307,12 @@ describe("Calendar", () => {
onKeyDown={onKeyDownSpy}
/>,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
- const prevMonthButton =
- container.querySelector(".react-datepicker__navigation--previous") ??
- new HTMLElement();
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+ const prevMonthButton = safeQuerySelector(
+ container,
+ ".react-datepicker__navigation--previous",
+ );
fireEvent.keyDown(prevMonthButton, getKey(KeyType.Tab));
expect(onKeyDownSpy).toHaveBeenCalledTimes(1);
});
@@ -2288,10 +2325,12 @@ describe("Calendar", () => {
onKeyDown={onKeyDownSpy}
/>,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
- const nextMonthButton =
- container.querySelector(".react-datepicker__navigation--next") ??
- new HTMLElement();
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+ const nextMonthButton = safeQuerySelector(
+ container,
+ ".react-datepicker__navigation--next",
+ );
fireEvent.keyDown(nextMonthButton, getKey(KeyType.Tab));
expect(onKeyDownSpy).toHaveBeenCalledTimes(1);
});
@@ -2347,11 +2386,13 @@ describe("Calendar", () => {
describe("should render aria live region after month/year change", () => {
it("should render aria live region after month change", () => {
const { container } = render();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
- const nextNavigationButton =
- container.querySelector(".react-datepicker__navigation--next") ??
- new HTMLElement();
+ const nextNavigationButton = safeQuerySelector(
+ container,
+ ".react-datepicker__navigation--next",
+ );
fireEvent.click(nextNavigationButton);
const currentMonthText = container.querySelector(
diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx
index d395e82b1..ec3f7ccbf 100644
--- a/src/test/datepicker_test.test.tsx
+++ b/src/test/datepicker_test.test.tsx
@@ -27,7 +27,7 @@ import DatePicker, { registerLocale } from "../index";
import CustomInput from "./helper_components/custom_input";
import TestWrapper from "./helper_components/test_wrapper";
-import { getKey } from "./test_utils";
+import { getKey, safeQuerySelector } from "./test_utils";
function getSelectedDayNode(container: HTMLElement) {
return (
@@ -87,7 +87,7 @@ describe("DatePicker", () => {
it("should retain the calendar open status when the document visibility change", () => {
const { container } = render();
- const input = container.querySelector("input");
+ const input = safeQuerySelector(container, "input");
if (!input) {
throw new Error("Input element not found");
@@ -104,12 +104,7 @@ describe("DatePicker", () => {
it("should retain the calendar close status when the document visibility change", () => {
const { container } = render();
- const input = container.querySelector("input");
-
- if (!input) {
- throw new Error("Input element not found");
- }
-
+ const input = safeQuerySelector(container, "input");
fireEvent.click(input);
expect(container.querySelector(".react-datepicker")).toBeTruthy();
@@ -124,14 +119,17 @@ describe("DatePicker", () => {
it("should show the calendar when focusing on the date input", () => {
const { container } = render();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
});
it("should allow the user to supply a wrapper component for the popper", () => {
const { container } = render();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(container.querySelectorAll(".test-wrapper").length).toBe(1);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
@@ -142,7 +140,8 @@ describe("DatePicker", () => {
,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(container.querySelectorAll(".test-wrapper").length).toBe(1);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
@@ -153,7 +152,8 @@ describe("DatePicker", () => {
,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
const popper = container.querySelectorAll(".react-datepicker-popper");
expect(popper.length).toBe(1);
@@ -163,7 +163,8 @@ describe("DatePicker", () => {
it("should show the calendar when clicking on the date input", () => {
const { container } = render();
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
});
@@ -198,7 +199,8 @@ describe("DatePicker", () => {
it("should not set open state when it is disabled and gets clicked", () => {
const { container } = render();
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
expect(container.querySelector(".react-datepicker")).toBeNull();
});
@@ -226,15 +228,13 @@ describe("DatePicker", () => {
fireEvent.click(instance!.input!);
// user may tab or arrow down to the current day (or some other element in the popper)
- const today = div.querySelector(
- ".react-datepicker__day--today",
- );
+ const today = safeQuerySelector(div, ".react-datepicker__day--today");
act(() => {
today?.focus();
});
// user hits Escape
- fireEvent.keyDown(today ?? new HTMLElement(), getKey(KeyType.Escape));
+ fireEvent.keyDown(today, getKey(KeyType.Escape));
expect(instance!.calendar).toBeFalsy();
@@ -267,15 +267,13 @@ describe("DatePicker", () => {
fireEvent.focus(instance!.input!);
// user may tab or arrow down to the current day (or some other element in the popper)
- const today = div.querySelector(
- ".react-datepicker__day--today",
- );
+ const today = safeQuerySelector(div, ".react-datepicker__day--today");
act(() => {
today?.focus();
});
// user hits Enter
- fireEvent.keyDown(today ?? new HTMLElement(), getKey(KeyType.Enter));
+ fireEvent.keyDown(today, getKey(KeyType.Enter));
expect(instance!.calendar).toBeFalsy();
@@ -307,15 +305,13 @@ describe("DatePicker", () => {
fireEvent.focus(instance!.input!);
// user may tab or arrow down to the current day (or some other element in the popper)
- const today = div.querySelector(
- ".react-datepicker__day--today",
- );
+ const today = safeQuerySelector(div, ".react-datepicker__day--today");
act(() => {
- today?.focus();
+ today.focus();
});
// user hits Enter
- fireEvent.keyDown(today ?? new HTMLElement(), getKey(KeyType.Enter));
+ fireEvent.keyDown(today, getKey(KeyType.Enter));
expect(instance!.calendar).toBeTruthy();
@@ -334,14 +330,15 @@ describe("DatePicker", () => {
onBlur={onBlurSpy}
/>,
);
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
const focusSpy = jest.spyOn(input, "focus");
fireEvent.focus(input);
- const yearSelect =
- container.querySelector(".react-datepicker__year-select") ??
- new HTMLElement();
+ const yearSelect = safeQuerySelector(
+ container,
+ ".react-datepicker__year-select",
+ );
fireEvent.blur(input);
fireEvent.focus(yearSelect);
@@ -358,12 +355,13 @@ describe("DatePicker", () => {
onYearChange={onYearChangeSpy}
/>,
);
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
fireEvent.click(input);
- const yearSelect =
- container.querySelector(".react-datepicker__year-select") ??
- new HTMLElement();
+ const yearSelect = safeQuerySelector(
+ container,
+ ".react-datepicker__year-select",
+ );
fireEvent.change(yearSelect, {
target: {
value: Array.from(yearSelect.querySelectorAll("option")).at(-2)?.value,
@@ -374,7 +372,7 @@ describe("DatePicker", () => {
it("should keep the calendar shown when clicking the calendar", () => {
const { container } = render();
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
fireEvent.focus(input);
fireEvent.click(input);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
@@ -382,31 +380,33 @@ describe("DatePicker", () => {
it("should not set open state when it is disabled and gets clicked.", () => {
const { container } = render();
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
expect(container.querySelector(".react-datepicker")).toBeNull();
});
it("should not set open state when it is readOnly and gets clicked", () => {
const { container } = render();
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
expect(container.querySelector(".react-datepicker")).toBeNull();
});
it("should hide the calendar when clicking a day on the calendar", () => {
const { container } = render();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
- fireEvent.click(
- container.querySelector(".react-datepicker__day") ?? new HTMLElement(),
- );
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+ const day = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.click(day);
expect(container.querySelector(".react-datepicker")).toBeNull();
});
it("should not hide the calendar when clicking a day on the calendar and shouldCloseOnSelect prop is false", () => {
const { container } = render();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
- fireEvent.click(
- container.querySelector(".react-datepicker__day") ?? new HTMLElement(),
- );
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+ const day = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.click(day);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
});
@@ -418,19 +418,18 @@ describe("DatePicker", () => {
});
// user focuses the input field, the calendar opens
- const dateInput = div.querySelector("input") ?? new HTMLElement();
+ const dateInput = safeQuerySelector(div, "input");
fireEvent.focus(dateInput);
// user may tab or arrow down to the current day (or some other element in the popper)
- const today = div.querySelector(
- ".react-datepicker__day--today",
- );
+
+ const today = safeQuerySelector(div, ".react-datepicker__day--today");
act(() => {
today?.focus();
});
// user hits Enter
- fireEvent.keyDown(today ?? new HTMLElement(), getKey(KeyType.Enter));
+ fireEvent.keyDown(today, getKey(KeyType.Enter));
expect(document.activeElement).toBe(today);
});
@@ -538,7 +537,7 @@ describe("DatePicker", () => {
it("should hide the calendar when pressing enter in the date input", () => {
const { container } = render();
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
fireEvent.focus(input);
fireEvent.keyDown(input, getKey(KeyType.Enter));
expect(container.querySelector(".react-datepicker")).toBeNull();
@@ -546,7 +545,7 @@ describe("DatePicker", () => {
it("should hide the calendar when the pressing escape in the date input", () => {
const { container } = render();
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
fireEvent.focus(input);
fireEvent.keyDown(input, getKey(KeyType.Escape));
expect(container.querySelector(".react-datepicker")).toBeNull();
@@ -590,7 +589,7 @@ describe("DatePicker", () => {
onBlurSpy(event);
};
const { container } = render();
- const input = container.querySelector("input") ?? new HTMLInputElement();
+ const input = safeQuerySelector(container, "input");
onBlurSpy = jest.spyOn(input, "blur");
fireEvent.focus(input);
fireEvent.keyDown(input, getKey(KeyType.Tab, true));
@@ -600,7 +599,7 @@ describe("DatePicker", () => {
it("should not apply the react-datepicker-ignore-onclickoutside class to the date input when closed", () => {
const { container } = render();
- const input = container.querySelector("input");
+ const input = safeQuerySelector(container, "input");
expect(
input?.classList.contains("react-datepicker-ignore-onclickoutside"),
).toBeFalsy();
@@ -608,8 +607,8 @@ describe("DatePicker", () => {
it("should apply the react-datepicker-ignore-onclickoutside class to date input when open", () => {
const { container } = render();
- const input = container.querySelector("input");
- fireEvent.focus(input ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(
input?.classList.contains("react-datepicker-ignore-onclickoutside"),
).toBeTruthy();
@@ -624,10 +623,11 @@ describe("DatePicker", () => {
/>,
);
- const calendarIcon = container.querySelector(
+ const calendarIcon = safeQuerySelector(
+ container,
"svg.react-datepicker__calendar-icon",
);
- fireEvent.click(calendarIcon ?? new HTMLElement());
+ fireEvent.click(calendarIcon);
const reactCalendar = container.querySelector(
"div.react-datepicker-popper .react-datepicker",
@@ -645,10 +645,11 @@ describe("DatePicker", () => {
/>,
);
- const calendarIcon = container.querySelector(
+ const calendarIcon = safeQuerySelector(
+ container,
"svg.react-datepicker__calendar-icon",
);
- fireEvent.click(calendarIcon ?? new HTMLElement());
+ fireEvent.click(calendarIcon);
const reactCalendar = container.querySelector(
"div.react-datepicker-popper .react-datepicker",
@@ -681,12 +682,14 @@ describe("DatePicker", () => {
/>,
);
- let calendarIcon = container.querySelector(
+ let calendarIcon = safeQuerySelector(
+ container,
"svg.react-datepicker__calendar-icon",
);
- fireEvent.click(calendarIcon ?? new HTMLElement());
+ fireEvent.click(calendarIcon);
- calendarIcon = container.querySelector(
+ calendarIcon = safeQuerySelector(
+ container,
"svg.react-datepicker__calendar-icon",
);
@@ -782,10 +785,12 @@ describe("DatePicker", () => {
onChange={handleChange}
/>,
);
- const clearButton = container.querySelector(
+
+ const clearButton = safeQuerySelector(
+ container,
".react-datepicker__close-icon",
);
- fireEvent.click(clearButton ?? new HTMLElement());
+ fireEvent.click(clearButton);
expect(cleared).toBe(true);
});
@@ -801,10 +806,12 @@ describe("DatePicker", () => {
/>,
);
expect(instance).toBeTruthy();
- const clearButton = container.querySelector(
+
+ const clearButton = safeQuerySelector(
+ container,
".react-datepicker__close-icon",
);
- fireEvent.click(clearButton ?? new HTMLElement());
+ fireEvent.click(clearButton);
expect(instance!.state.inputValue).toBeNull();
});
@@ -835,10 +842,11 @@ describe("DatePicker", () => {
},
);
- const clearButton = container.querySelector(
+ const clearButton = safeQuerySelector(
+ container,
".react-datepicker__close-icon",
);
- fireEvent.click(clearButton ?? new HTMLElement());
+ fireEvent.click(clearButton);
await waitFor(() => {
expect(document.activeElement).toBe(div.querySelector("input"));
@@ -888,8 +896,9 @@ describe("DatePicker", () => {
}}
/>,
);
- const dayButton = container.querySelector(".react-datepicker__day");
- fireEvent.click(dayButton ?? new HTMLElement());
+
+ const dayButton = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.click(dayButton);
expect(date).toBeTruthy();
expect(getHours(date!)).toBe(10);
@@ -909,8 +918,8 @@ describe("DatePicker", () => {
}}
/>,
);
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLInputElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: {
value: newDate("2014-01-02"),
},
@@ -986,7 +995,8 @@ describe("DatePicker", () => {
it("should render Calendar in portal when withPortal is set and input has focus", () => {
const { container } = render();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(
document.body.querySelector(".react-datepicker__portal"),
@@ -1037,7 +1047,8 @@ describe("DatePicker", () => {
,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(document.body.querySelector("#portal-id-dom-test")).not.toBeNull();
});
@@ -1687,9 +1698,8 @@ describe("DatePicker", () => {
it("should auto update calendar when the updated date text is after props.minDate", () => {
const { container } = getCalendar();
- const input = container.querySelector("input");
-
- fireEvent.change(input ?? new HTMLElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: {
value: "1801/01/01",
},
@@ -1703,9 +1713,9 @@ describe("DatePicker", () => {
it("should not auto update calendar when the updated date text is before props.minDate", () => {
const { container } = getCalendar();
- const input = container.querySelector("input");
+ const input = safeQuerySelector(container, "input");
- fireEvent.change(input ?? new HTMLElement(), {
+ fireEvent.change(input, {
target: {
value: "1799/01/01",
},
@@ -1895,7 +1905,7 @@ describe("DatePicker", () => {
});
// user focuses the input field, the calendar opens
- const dateInput = div.querySelector("input") ?? new HTMLElement();
+ const dateInput = safeQuerySelector(div, "input");
fireEvent.focus(dateInput);
fireEvent.keyDown(dateInput, getKey(KeyType.ArrowDown));
@@ -2058,8 +2068,8 @@ describe("DatePicker", () => {
const { container } = render(
,
);
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: {
value: "",
},
@@ -2174,8 +2184,8 @@ describe("DatePicker", () => {
);
expect(onChangeRawSpy).not.toHaveBeenCalled();
expect(onSelectSpy).not.toHaveBeenCalled();
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: {
value: inputValue,
},
@@ -2197,10 +2207,10 @@ describe("DatePicker", () => {
);
expect(onChangeRawSpy).not.toHaveBeenCalled();
expect(onSelectSpy).not.toHaveBeenCalled();
- const input = container.querySelector("input");
- fireEvent.focus(input ?? new HTMLElement());
- const day = container.querySelector(".react-datepicker__day");
- fireEvent.click(day ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+ const day = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.click(day);
expect(onChangeRawSpy).toHaveBeenCalledTimes(1);
expect(onSelectSpy).toHaveBeenCalledTimes(1);
});
@@ -2212,7 +2222,7 @@ describe("DatePicker", () => {
(event.target as unknown as HTMLInputElement).value > "2" &&
event.preventDefault();
const { container } = render();
- const input = container.querySelector("input") ?? new HTMLInputElement();
+ const input = safeQuerySelector(container, "input");
expect(input.value).toBe("");
fireEvent.change(input, {
target: {
@@ -2239,8 +2249,8 @@ describe("DatePicker", () => {
/>,
);
expect(onChangeRawSpy).not.toHaveBeenCalled();
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: {
value: inputValue,
},
@@ -2264,8 +2274,8 @@ describe("DatePicker", () => {
/>,
);
expect(onChangeRawSpy).not.toHaveBeenCalled();
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: {
value: inputValue,
},
@@ -2303,11 +2313,15 @@ describe("DatePicker", () => {
,
);
expect(container.querySelector(".react-datepicker")).toBeNull();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+
expect(container.querySelector(".react-datepicker")).not.toBeNull();
- fireEvent.mouseDown(
- container.querySelector(".testText") ?? new HTMLElement(),
- );
+
+ const testText = safeQuerySelector(container, ".testText");
+ fireEvent.mouseDown(testText);
+
expect(container.querySelector(".react-datepicker")).toBeNull();
expect(onClickOutsideSpy).toHaveBeenCalledTimes(1);
});
@@ -2318,9 +2332,11 @@ describe("DatePicker", () => {
,
);
expect(container.querySelector(".react-datepicker")).toBeNull();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
- fireEvent.mouseDown(container.querySelector("input") ?? new HTMLElement());
+
+ fireEvent.mouseDown(input);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
expect(onClickOutsideSpy).not.toHaveBeenCalled();
});
@@ -2513,15 +2529,16 @@ describe("DatePicker", () => {
});
it("should not set open state when focusing on the date input and the preventOpenOnFocus prop is set", () => {
const { container } = render();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(container.querySelector(".react-datepicker")).toBeNull();
});
it("should not set open state onInputKeyDown when preventOpenOnFocus prop is set", () => {
const { container } = render();
- fireEvent.keyDown(
- container.querySelector("input") ?? new HTMLElement(),
- getKey(KeyType.ArrowLeft),
- );
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.keyDown(input, getKey(KeyType.ArrowLeft));
+
expect(container.querySelector(".react-datepicker")).toBeNull();
});
it("should clear the input when clear() member function is called", () => {
@@ -2543,7 +2560,8 @@ describe("DatePicker", () => {
});
it("should not open when open is false and input is focused", () => {
const { container } = render();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(container.querySelector(".react-datepicker")).toBeNull();
});
it("should open when open is true", () => {
@@ -2553,7 +2571,8 @@ describe("DatePicker", () => {
it("should fire onInputClick when input is clicked", () => {
const onInputClickSpy = jest.fn();
const { container } = render();
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
expect(onInputClickSpy).toHaveBeenCalledTimes(1);
});
@@ -2612,8 +2631,8 @@ describe("DatePicker", () => {
it("should show the popper arrow when showPopperArrow is true", () => {
const { container } = render();
- const input = container.querySelector("input");
- fireEvent.click(input ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
const arrow = container.querySelector(".react-datepicker__triangle");
@@ -2622,8 +2641,8 @@ describe("DatePicker", () => {
it("should not show the popper arrow when showPopperArrow is false", () => {
const { container } = render();
- const input = container.querySelector("input");
- fireEvent.click(input ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
const arrows = container.querySelectorAll(".react-datepicker__triangle");
@@ -2694,8 +2713,8 @@ describe("DatePicker", () => {
it("should close the calendar after scrolling", () => {
const { container } = render();
- const input = container.querySelector("input");
- fireEvent.focus(input ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
fireEvent.scroll(document);
expect(container.querySelector(".react-datepicker")).toBeNull();
@@ -2707,8 +2726,8 @@ describe("DatePicker", () => {
const { container } = render(, {
container: div,
});
- const input = container.querySelector("input");
- fireEvent.focus(input ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
fireEvent.scroll(div);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
@@ -2716,8 +2735,8 @@ describe("DatePicker", () => {
it("should close the calendar after scrolling.", () => {
const { container } = render( true} />);
- const input = container.querySelector("input");
- fireEvent.focus(input ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
fireEvent.scroll(document);
expect(container.querySelector(".react-datepicker")).toBeNull();
@@ -2725,8 +2744,8 @@ describe("DatePicker", () => {
it("should not close the calendar after scrolling.", () => {
const { container } = render( false} />);
- const input = container.querySelector("input");
- fireEvent.focus(input ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
fireEvent.scroll(document);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
});
@@ -2753,7 +2772,8 @@ describe("DatePicker", () => {
onChange={onChange}
/>,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
const days = container.querySelectorAll(".react-datepicker__day");
@@ -2775,7 +2795,10 @@ describe("DatePicker", () => {
onChange={onChange}
/>,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+
const days = container.querySelectorAll(".react-datepicker__day");
expect(days[5]).toBeTruthy();
@@ -2797,7 +2820,10 @@ describe("DatePicker", () => {
onChange={onChange}
/>,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+
const days = container.querySelectorAll(".react-datepicker__day");
expect(days[5]).toBeTruthy();
@@ -2830,8 +2856,11 @@ describe("DatePicker", () => {
/>,
);
- const day = container.querySelector(".react-datepicker__day--selected");
- fireEvent.click(day ?? new HTMLElement());
+ const selectedDay = safeQuerySelector(
+ container,
+ ".react-datepicker__day--selected",
+ );
+ fireEvent.click(selectedDay);
expect(startDate).toBeTruthy();
expect(formatDate(startDate!, "yyyy-MM-dd")).toBe(
formatDate(selected, "yyyy-MM-dd"),
@@ -2858,10 +2887,11 @@ describe("DatePicker", () => {
/>,
);
- const day = container.querySelector(
+ const day = safeQuerySelector(
+ container,
".react-datepicker__day--selected + .react-datepicker__day",
);
- fireEvent.click(day ?? new HTMLElement());
+ fireEvent.click(day);
expect(formatDate(startDate, "yyyy-MM-dd")).toBe(
formatDate(startDate, "yyyy-MM-dd"),
);
@@ -2892,8 +2922,11 @@ describe("DatePicker", () => {
/>,
);
- const day = container.querySelector(".react-datepicker__day--selected");
- fireEvent.click(day ?? new HTMLElement());
+ const day = safeQuerySelector(
+ container,
+ ".react-datepicker__day--selected",
+ );
+ fireEvent.click(day);
expect(formatDate(startDate, "yyyy-MM-dd")).toBe(
formatDate(selected, "yyyy-MM-dd"),
);
@@ -3008,10 +3041,15 @@ describe("DatePicker", () => {
const { container } = render(
,
);
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
- fireEvent.click(
- container.querySelector(".react-datepicker__day") ?? new HTMLElement(),
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
+
+ const datePickerDay = safeQuerySelector(
+ container,
+ ".react-datepicker__day",
);
+ fireEvent.click(datePickerDay);
expect(container.querySelector(".react-datepicker")).not.toBeNull();
});
@@ -3022,7 +3060,9 @@ describe("DatePicker", () => {
const { container } = render(
,
);
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
const days = container.querySelectorAll(".react-datepicker__day");
const day = days[Math.floor(days.length / 2)];
@@ -3042,7 +3082,9 @@ describe("DatePicker", () => {
endDate={endDate}
/>,
);
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
const days = container.querySelectorAll(".react-datepicker__day");
const day = days[Math.floor(days.length / 2)];
@@ -3113,9 +3155,9 @@ describe("DatePicker", () => {
/>,
);
- const input = container.querySelector("input");
+ const input = safeQuerySelector(container, "input");
expect(input).toBeTruthy();
- fireEvent.click(input ?? new HTMLElement());
+ fireEvent.click(input);
const calendar = container.querySelector(".react-datepicker");
expect(calendar).toBeTruthy();
@@ -3124,10 +3166,11 @@ describe("DatePicker", () => {
const startDatePrefixedWithZeros = formatDayWithZeros(
startDate.getDate(),
);
- const endDateElement = container.querySelector(
+ const endDateElement = safeQuerySelector(
+ container,
`.react-datepicker__day--${startDatePrefixedWithZeros}`,
);
- fireEvent.click(endDateElement ?? new HTMLElement());
+ fireEvent.click(endDateElement);
expect(onChangeSpy).toHaveBeenCalled();
});
@@ -3155,7 +3198,7 @@ describe("DatePicker", () => {
/>,
);
- const input = container.querySelector("input");
+ const input = safeQuerySelector(container, "input");
expect(input).toBeTruthy();
fireEvent.click(input!);
@@ -3166,10 +3209,12 @@ describe("DatePicker", () => {
const startDatePrefixedWithZeros = formatDayWithZeros(
startDate.getDate(),
);
- const endDateElement = container.querySelector(
+
+ const endDateElement = safeQuerySelector(
+ container,
`.react-datepicker__day--${startDatePrefixedWithZeros}`,
);
- fireEvent.click(endDateElement ?? new HTMLElement());
+ fireEvent.click(endDateElement);
calendar = container.querySelector(".react-datepicker");
expect(calendar).toBeFalsy();
@@ -3186,7 +3231,8 @@ describe("DatePicker", () => {
const { container, rerender } = render(
,
);
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
const months = container.querySelectorAll(".react-datepicker__month");
expect(months).toHaveLength(2);
// 2023-05 monthShowsDuplicateDaysEnd:true
@@ -3206,7 +3252,7 @@ describe("DatePicker", () => {
// moreThanTwoMonths
rerender();
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+ fireEvent.click(input);
const monthsMore = container.querySelectorAll(".react-datepicker__month");
expect(monthsMore).toHaveLength(4);
// 2023-05 monthShowsDuplicateDaysEnd:true
@@ -3244,7 +3290,8 @@ describe("DatePicker", () => {
const { container, rerender } = render(
,
);
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
const months = container.querySelectorAll(".react-datepicker__month");
expect(months).toHaveLength(2);
@@ -3261,7 +3308,7 @@ describe("DatePicker", () => {
// moreThanTwoMonths
rerender();
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+ fireEvent.click(input);
const monthsMore = container.querySelectorAll(".react-datepicker__month");
expect(monthsMore).toHaveLength(4);
// 2023-05 monthShowsDuplicateDaysStart:false
@@ -3288,7 +3335,8 @@ describe("DatePicker", () => {
it("should not find duplicates when single month displayed", () => {
const { container } = render();
- fireEvent.click(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.click(input);
const months = container.querySelectorAll(".react-datepicker__month");
expect(months).toHaveLength(1);
@@ -3476,7 +3524,7 @@ describe("DatePicker", () => {
registerLocale("en-GB", enGB);
const { container } = render();
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
jest.spyOn(input, "focus");
fireEvent.focus(input);
@@ -3489,7 +3537,7 @@ describe("DatePicker", () => {
registerLocale("en-US", enUS);
const { container } = render();
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
jest.spyOn(input, "focus");
fireEvent.focus(input);
@@ -3518,7 +3566,7 @@ describe("DatePicker", () => {
/>,
);
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
fireEvent.change(input, {
target: {
value: "8:22 AM",
@@ -3547,9 +3595,10 @@ describe("DatePicker", () => {
/>,
);
- const input =
- datepicker.querySelector(".react-datepicker__input-container > input") ??
- new HTMLElement();
+ const input = safeQuerySelector(
+ datepicker,
+ ".react-datepicker__input-container > input",
+ );
fireEvent.change(input, { target: { value: "" } });
expect(date).toBe(null);
@@ -3573,9 +3622,10 @@ describe("DatePicker", () => {
/>,
);
- const input =
- datepicker.querySelector(".react-datepicker__input-container > input") ??
- new HTMLElement();
+ const input = safeQuerySelector(
+ datepicker,
+ ".react-datepicker__input-container > input",
+ );
fireEvent.change(input, { target: { value: "" } });
expect(date).toBe(null);
@@ -3594,7 +3644,7 @@ describe("DatePicker", () => {
/>,
);
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
fireEvent.change(input, {
target: {
value: "11/2022",
@@ -3623,7 +3673,7 @@ describe("DatePicker", () => {
/>,
);
- const input = container.querySelector("input") ?? new HTMLElement();
+ const input = safeQuerySelector(container, "input");
fireEvent.change(input, {
target: {
value: "2021",
@@ -3741,11 +3791,12 @@ describe("DatePicker", () => {
/>,
);
- const dateInput = container.querySelector("input");
- fireEvent.focus(dateInput ?? new HTMLElement());
- const selectedYear =
- container.querySelector(".react-datepicker__year-text--selected") ??
- new HTMLElement();
+ const dateInput = safeQuerySelector(container, "input");
+ fireEvent.focus(dateInput);
+ const selectedYear = safeQuerySelector(
+ container,
+ ".react-datepicker__year-text--selected",
+ );
fireEvent.mouseEnter(selectedYear);
fireEvent.mouseLeave(selectedYear);
@@ -3767,11 +3818,12 @@ describe("DatePicker", () => {
/>,
);
- const dateInput = container.querySelector("input");
- fireEvent.focus(dateInput ?? new HTMLElement());
- const selectedYear =
- container.querySelector(".react-datepicker__year-text--selected") ??
- new HTMLElement();
+ const dateInput = safeQuerySelector(container, "input");
+ fireEvent.focus(dateInput);
+ const selectedYear = safeQuerySelector(
+ container,
+ ".react-datepicker__year-text--selected",
+ );
fireEvent.pointerEnter(selectedYear);
fireEvent.pointerLeave(selectedYear);
diff --git a/src/test/day_test.test.tsx b/src/test/day_test.test.tsx
index 3fff9254e..12d2692a0 100644
--- a/src/test/day_test.test.tsx
+++ b/src/test/day_test.test.tsx
@@ -15,6 +15,8 @@ import {
} from "../date_utils";
import Day from "../day";
+import { safeQuerySelector } from "./test_utils";
+
function renderDay(day: Date, props = {}) {
return render(
{}} {...props} />,
@@ -1226,9 +1228,9 @@ describe("Day", () => {
onClick={onClick}
/>,
);
- fireEvent.click(
- container.querySelector(".react-datepicker__day") ?? new HTMLElement(),
- );
+
+ const dayElement = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.click(dayElement);
expect(onClickCalled).toBe(true);
});
@@ -1243,9 +1245,9 @@ describe("Day", () => {
onClick={onClick}
/>,
);
- fireEvent.click(
- container.querySelector(".react-datepicker__day") ?? new HTMLElement(),
- );
+
+ const dayElement = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.click(dayElement);
expect(onClickCalled).toBe(false);
});
@@ -1262,9 +1264,9 @@ describe("Day", () => {
onClick={onClick}
/>,
);
- fireEvent.click(
- container.querySelector(".react-datepicker__day") ?? new HTMLElement(),
- );
+
+ const dayElement = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.click(dayElement);
expect(onClickCalled).toBe(false);
});
});
@@ -1284,9 +1286,8 @@ describe("Day", () => {
/>,
);
- fireEvent.mouseEnter(
- container.querySelector(".react-datepicker__day") ?? new HTMLElement(),
- );
+ const dayElement = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.mouseEnter(dayElement);
expect(onMouseEnterSpy).toHaveBeenCalled();
});
@@ -1305,9 +1306,8 @@ describe("Day", () => {
/>,
);
- fireEvent.pointerEnter(
- container.querySelector(".react-datepicker__day") ?? new HTMLElement(),
- );
+ const dayElement = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.pointerEnter(dayElement);
expect(onMouseEnterSpy).toHaveBeenCalled();
});
});
diff --git a/src/test/min_time_test.test.tsx b/src/test/min_time_test.test.tsx
index c73051bd3..0360a1022 100644
--- a/src/test/min_time_test.test.tsx
+++ b/src/test/min_time_test.test.tsx
@@ -3,6 +3,8 @@ import React, { useState } from "react";
import DatePicker from "../index";
+import { safeQuerySelector } from "./test_utils";
+
import type { DatePickerProps } from "../index";
// see https://github.com/microsoft/TypeScript/issues/31501
@@ -78,7 +80,7 @@ describe("Datepicker minTime", () => {
const { container } = render(
,
);
- const input = container.querySelector("input") ?? new HTMLInputElement();
+ const input = safeQuerySelector(container, "input");
fireEvent.change(input, { target: { value: "2023-03-10 16:00" } });
fireEvent.focusOut(input);
diff --git a/src/test/month_dropdown_test.test.tsx b/src/test/month_dropdown_test.test.tsx
index a6344719f..ac3d918c1 100644
--- a/src/test/month_dropdown_test.test.tsx
+++ b/src/test/month_dropdown_test.test.tsx
@@ -8,12 +8,12 @@ import { getMonthInLocale, registerLocale } from "../date_utils";
import MonthDropdown from "../month_dropdown";
import MonthDropdownOptions from "../month_dropdown_options";
-import { range } from "./test_utils";
+import { range, safeQuerySelector, safeQuerySelectorAll } from "./test_utils";
type MonthDropdownProps = React.ComponentProps;
describe("MonthDropdown", () => {
- let monthDropdown: HTMLElement | null = null;
+ let monthDropdown: HTMLElement;
let handleChangeResult: number | null;
const mockHandleChange = function (changeInput: number) {
handleChangeResult = changeInput;
@@ -49,10 +49,11 @@ describe("MonthDropdown", () => {
});
it("opens a list when read view is clicked", () => {
- fireEvent.click(
- monthDropdown?.querySelector(".react-datepicker__month-read-view") ??
- new HTMLElement(),
+ const monthReadView = safeQuerySelector(
+ monthDropdown,
+ ".react-datepicker__month-read-view",
);
+ fireEvent.click(monthReadView);
const optionsView = monthDropdown?.querySelector(
".react-datepicker__month-dropdown",
);
@@ -63,10 +64,11 @@ describe("MonthDropdown", () => {
let selectedMonth: HTMLSelectElement | null | undefined;
beforeEach(() => {
- fireEvent.click(
- monthDropdown?.querySelector(".react-datepicker__month-read-view") ??
- new HTMLElement(),
+ const monthReadView = safeQuerySelector(
+ monthDropdown,
+ ".react-datepicker__month-read-view",
);
+ fireEvent.click(monthReadView);
selectedMonth = monthDropdown?.querySelector(
".react-datepicker__month-option--selected_month",
);
@@ -90,7 +92,8 @@ describe("MonthDropdown", () => {
monthDropdown?.querySelector(".react-datepicker__month-read-view") ??
new HTMLSelectElement(),
);
- notSelectedMonth = monthDropdown?.querySelector(
+ notSelectedMonth = safeQuerySelector(
+ monthDropdown,
".react-datepicker__month-option",
);
});
@@ -106,14 +109,20 @@ describe("MonthDropdown", () => {
});
it("closes the dropdown when a month is clicked", () => {
- fireEvent.click(
- monthDropdown?.querySelector(".react-datepicker__month-read-view") ??
- new HTMLElement(),
+ const monthReadView = safeQuerySelector(
+ monthDropdown,
+ ".react-datepicker__month-read-view",
);
- fireEvent.click(
- (monthDropdown?.querySelectorAll(".react-datepicker__month-option") ??
- [])[1] ?? new HTMLElement(),
+ fireEvent.click(monthReadView);
+
+ const minMonthOptionsLen = 2;
+ const monthOptions = safeQuerySelectorAll(
+ monthDropdown,
+ ".react-datepicker__month-option",
+ minMonthOptionsLen,
);
+
+ fireEvent.click(monthOptions[1]!);
expect(
monthDropdown?.querySelectorAll(".react-datepicker__month-dropdown"),
).toHaveLength(0);
@@ -137,26 +146,36 @@ describe("MonthDropdown", () => {
});
it("does not call the supplied onChange function when the same month is clicked", () => {
- fireEvent.click(
- monthDropdown?.querySelector(".react-datepicker__month-read-view") ??
- new HTMLElement(),
+ const monthReadView = safeQuerySelector(
+ monthDropdown,
+ ".react-datepicker__month-read-view",
);
- fireEvent.click(
- (monthDropdown?.querySelectorAll(".react-datepicker__month-option") ??
- [])[11] ?? new HTMLElement(),
+ fireEvent.click(monthReadView);
+
+ const monthOptionsLen = 12;
+ const monthOptions = safeQuerySelectorAll(
+ monthDropdown,
+ ".react-datepicker__month-option",
+ monthOptionsLen,
);
+ fireEvent.click(monthOptions[11]!);
expect(handleChangeResult).toBeNull();
});
it("calls the supplied onChange function when a different month is clicked", () => {
- fireEvent.click(
- monthDropdown?.querySelector(".react-datepicker__month-read-view") ??
- new HTMLElement(),
+ const monthReadView = safeQuerySelector(
+ monthDropdown,
+ ".react-datepicker__month-read-view",
);
- fireEvent.click(
- (monthDropdown?.querySelectorAll(".react-datepicker__month-option") ??
- [])[2] ?? new HTMLElement(),
+ fireEvent.click(monthReadView);
+
+ const minRequiredMonthsLen = 3;
+ const monthOptions = safeQuerySelectorAll(
+ monthDropdown,
+ ".react-datepicker__month-option",
+ minRequiredMonthsLen,
);
+ fireEvent.click(monthOptions[2]!);
expect(handleChangeResult).toEqual(2);
});
diff --git a/src/test/month_year_dropdown_test.test.tsx b/src/test/month_year_dropdown_test.test.tsx
index 916e12d96..ea5067eed 100644
--- a/src/test/month_year_dropdown_test.test.tsx
+++ b/src/test/month_year_dropdown_test.test.tsx
@@ -13,10 +13,12 @@ import {
import MonthYearDropdown from "../month_year_dropdown";
import MonthYearDropdownOptions from "../month_year_dropdown_options";
+import { safeQuerySelector, safeQuerySelectorAll } from "./test_utils";
+
type MonthYearDropdownProps = React.ComponentProps;
describe("MonthYearDropdown", () => {
- let monthYearDropdown: HTMLElement | null = null;
+ let monthYearDropdown: HTMLElement;
let handleChangeResult: Date | null = null;
const mockHandleChange = function (changeInput: Date) {
handleChangeResult = changeInput;
@@ -81,11 +83,11 @@ describe("MonthYearDropdown", () => {
});
it("opens a list when read view is clicked", () => {
- fireEvent.click(
- monthYearDropdown?.querySelector(
- ".react-datepicker__month-year-read-view",
- ) ?? new HTMLElement(),
+ const monthYearReadView = safeQuerySelector(
+ monthYearDropdown,
+ ".react-datepicker__month-year-read-view",
);
+ fireEvent.click(monthYearReadView);
const optionsView = monthYearDropdown?.querySelector(
".react-datepicker__month-year-dropdown",
);
@@ -93,16 +95,18 @@ describe("MonthYearDropdown", () => {
});
it("closes the dropdown when a month year is clicked", () => {
- fireEvent.click(
- monthYearDropdown?.querySelector(
- ".react-datepicker__month-year-read-view",
- ) ?? new HTMLElement(),
+ const monthYearReadView = safeQuerySelector(
+ monthYearDropdown,
+ ".react-datepicker__month-year-read-view",
);
- fireEvent.click(
- (monthYearDropdown?.querySelectorAll(
- ".react-datepicker__month-year-option",
- ) ?? [])[1] ?? new HTMLElement(),
+ fireEvent.click(monthYearReadView);
+
+ const monthYearOptions = safeQuerySelectorAll(
+ monthYearDropdown,
+ ".react-datepicker__month-year-option",
);
+ const monthYearOption = monthYearOptions[0]!;
+ fireEvent.click(monthYearOption);
expect(
monthYearDropdown?.querySelectorAll(
".react-datepicker__month-year-dropdown",
@@ -131,25 +135,27 @@ describe("MonthYearDropdown", () => {
});
it("does not call the supplied onChange function when the same month year is clicked", () => {
- fireEvent.click(
- monthYearDropdown?.querySelector(
- ".react-datepicker__month-year-read-view",
- ) ?? new HTMLElement(),
+ const monthYearReadView = safeQuerySelector(
+ monthYearDropdown,
+ ".react-datepicker__month-year-read-view",
);
- fireEvent.click(
- monthYearDropdown?.querySelector(
- ".react-datepicker__month-year-option--selected_month-year",
- ) ?? new HTMLElement(),
+ fireEvent.click(monthYearReadView);
+
+ const selectedMonthYear = safeQuerySelector(
+ monthYearDropdown,
+ ".react-datepicker__month-year-option--selected_month-year",
);
+ fireEvent.click(selectedMonthYear);
+
expect(handleChangeResult).toBeNull();
});
it("adds aria-selected to selected option", () => {
- fireEvent.click(
- monthYearDropdown?.querySelector(
- ".react-datepicker__month-year-read-view",
- ) ?? new HTMLElement(),
+ const monthYearReadView = safeQuerySelector(
+ monthYearDropdown,
+ ".react-datepicker__month-year-read-view",
);
+ fireEvent.click(monthYearReadView);
const ariaSelected = monthYearDropdown
?.querySelector(
@@ -161,12 +167,11 @@ describe("MonthYearDropdown", () => {
});
it("does not add aria-selected to non-selected option", () => {
- fireEvent.click(
- monthYearDropdown?.querySelector(
- ".react-datepicker__month-year-read-view",
- ) ?? new HTMLElement(),
+ const monthYearReadView = safeQuerySelector(
+ monthYearDropdown,
+ ".react-datepicker__month-year-read-view",
);
-
+ fireEvent.click(monthYearReadView);
const ariaSelected = monthYearDropdown
?.querySelector(".react-datepicker__month-year-option")
?.getAttribute("aria-selected");
@@ -177,18 +182,22 @@ describe("MonthYearDropdown", () => {
it("calls the supplied onChange function when a different month year is clicked", () => {
const expected_date = newDate("2017-12");
- fireEvent.click(
- monthYearDropdown?.querySelector(
- ".react-datepicker__month-year-read-view",
- ) ?? new HTMLElement(),
+ const monthYearReadView = safeQuerySelector(
+ monthYearDropdown,
+ ".react-datepicker__month-year-read-view",
);
+ fireEvent.click(monthYearReadView);
- fireEvent.click(
- (monthYearDropdown?.querySelectorAll(
- ".react-datepicker__month-year-option",
- ) ?? [])[5] ?? new HTMLElement(),
+ const minRequiredMonthYearOptionsLen = 6;
+ const monthYearOptions = safeQuerySelectorAll(
+ monthYearDropdown,
+ ".react-datepicker__month-year-option",
+ minRequiredMonthYearOptionsLen,
);
+ const monthYearOption = monthYearOptions[5]!;
+ fireEvent.click(monthYearOption);
+
expect(handleChangeResult?.toString()).toBe(expected_date.toString());
});
@@ -297,10 +306,11 @@ describe("MonthYearDropdown", () => {
dropdownMode: "select",
date: selectedMonth,
});
- const select = monthYearDropdown.querySelector(
+ const select = safeQuerySelector(
+ monthYearDropdown,
".react-datepicker__month-year-select",
);
- fireEvent.change(select ?? new HTMLElement(), {
+ fireEvent.change(select, {
target: { value: selectedMonth.valueOf() },
});
expect(handleChangeResult).toBeFalsy();
@@ -313,10 +323,11 @@ describe("MonthYearDropdown", () => {
dropdownMode: "select",
date: selectedMonth,
});
- const select = monthYearDropdown.querySelector(
+ const select = safeQuerySelector(
+ monthYearDropdown,
".react-datepicker__month-year-select",
);
- fireEvent.change(select ?? new HTMLElement(), {
+ fireEvent.change(select, {
target: { value: monthToClick.valueOf() },
});
expect(handleChangeResult?.valueOf()).toBe(monthToClick.valueOf());
diff --git a/src/test/show_time_test.test.tsx b/src/test/show_time_test.test.tsx
index 742cc7ab5..0fdfbf442 100644
--- a/src/test/show_time_test.test.tsx
+++ b/src/test/show_time_test.test.tsx
@@ -4,6 +4,8 @@ import React from "react";
import DatePicker from "../index";
import TimeComponent from "../time";
+import { safeQuerySelector } from "./test_utils";
+
describe("DatePicker", () => {
it("should show time component when showTimeSelect prop is present", () => {
const { container } = render();
@@ -26,7 +28,9 @@ describe("DatePicker", () => {
datePicker = render(
,
).container;
- fireEvent.click(datePicker.querySelector("input") ?? new HTMLElement());
+
+ const input = safeQuerySelector(datePicker, "input");
+ fireEvent.click(input);
});
it("should not show month container when showTimeSelectOnly prop is present", () => {
diff --git a/src/test/test_utils.test.ts b/src/test/test_utils.test.ts
new file mode 100644
index 000000000..4503cb0cf
--- /dev/null
+++ b/src/test/test_utils.test.ts
@@ -0,0 +1,174 @@
+import {
+ SafeElementWrapper,
+ safeQuerySelector,
+ safeQuerySelectorAll,
+} from "./test_utils";
+
+describe("test_utils", () => {
+ describe("safeQuerySelector", () => {
+ let container: HTMLElement;
+
+ beforeEach(() => {
+ container = document.createElement("div");
+ container.innerHTML = `
+
+ `;
+ document.body.appendChild(container);
+ });
+
+ afterEach(() => {
+ document.body.removeChild(container);
+ });
+
+ it("should return the element when the selector matches", () => {
+ const result = safeQuerySelector(container, ".childDiv");
+ expect(result).toBeInstanceOf(HTMLDivElement);
+ expect(result.className).toBe("childDiv");
+ });
+
+ it("should throw an error if the element is not found", () => {
+ expect(() => safeQuerySelector(container, ".nonExistent")).toThrow(
+ "Element with selector '.nonExistent' not found",
+ );
+ });
+ });
+
+ describe("safeQuerySelectorAll", () => {
+ let container: HTMLElement;
+
+ beforeEach(() => {
+ container = document.createElement("div");
+ container.innerHTML = `
+
+ `;
+ document.body.appendChild(container);
+ });
+
+ afterEach(() => {
+ document.body.removeChild(container);
+ });
+
+ it("should return an array of elements when the selector matches", () => {
+ const results = safeQuerySelectorAll(
+ container,
+ ".childSpan",
+ );
+ expect(results).toHaveLength(2);
+ expect(results[0]!.textContent).toBe("Span 1");
+ expect(results[1]!.textContent).toBe("Span 2");
+ });
+
+ it("should throw an error if no elements are found", () => {
+ expect(() => safeQuerySelectorAll(container, ".nonExistent")).toThrow(
+ "Element with selector '.nonExistent' not found",
+ );
+ });
+
+ it("should throw an error if fewer elements than expected are found", () => {
+ expect(() => safeQuerySelectorAll(container, ".childSpan", 3)).toThrow(
+ "Expected at least 3 element(s) for selector '.childSpan'. Only 2 found",
+ );
+ });
+
+ it("should return elements if the minimum expected number of elements are found", () => {
+ const results = safeQuerySelectorAll(
+ container,
+ ".childSpan",
+ 2,
+ );
+ expect(results).toHaveLength(2);
+ });
+ });
+
+ describe("SafeElementWrapper", () => {
+ let container: HTMLElement;
+
+ beforeEach(() => {
+ container = document.createElement("div");
+ container.innerHTML = `
+
+ `;
+ document.body.appendChild(container);
+ });
+
+ afterEach(() => {
+ document.body.removeChild(container);
+ });
+
+ it("should wrap an element using getElement", () => {
+ const element = document.getElementById("parentDiv");
+ const wrapper = new SafeElementWrapper(element!);
+
+ expect(wrapper).toBeInstanceOf(SafeElementWrapper);
+ expect(wrapper.getElement()).toBe(element);
+ });
+
+ it("should find a child element using safeQuerySelector", () => {
+ const element = document.getElementById("parentDiv");
+ const wrapper = new SafeElementWrapper(element!);
+ const childWrapper = wrapper.safeQuerySelector(".childDiv");
+
+ expect(childWrapper).toBeInstanceOf(SafeElementWrapper);
+ expect(childWrapper.getElement().className).toBe("childDiv");
+ });
+
+ it("should throw an error if child element is not found using safeQuerySelector", () => {
+ const element = document.getElementById("parentDiv");
+ const wrapper = new SafeElementWrapper(element!);
+
+ expect(() => wrapper.safeQuerySelector(".nonExistent")).toThrow(
+ "Element with selector '.nonExistent' not found",
+ );
+ });
+
+ it("should find all matching child elements using safeQuerySelectorAll", () => {
+ const element = document.getElementById("parentDiv");
+ const wrapper = new SafeElementWrapper(element!);
+ const childWrappers = wrapper.safeQuerySelectorAll(".childSpan");
+
+ expect(childWrappers.length).toBe(2);
+ expect(childWrappers[0]!.getElement().textContent).toBe("Span 1");
+ expect(childWrappers[1]!.getElement().textContent).toBe("Span 2");
+ });
+
+ it("should throw an error if no matching elements are found using safeQuerySelectorAll", () => {
+ const element = document.getElementById("parentDiv");
+ const wrapper = new SafeElementWrapper(element!);
+
+ expect(() => wrapper.safeQuerySelectorAll(".nonExistent")).toThrow(
+ "Element with selector '.nonExistent' not found",
+ );
+ });
+
+ it("should throw an error if fewer elements than expected are found using safeQuerySelectorAll", () => {
+ const element = document.getElementById("parentDiv");
+ const wrapper = new SafeElementWrapper(element!);
+
+ expect(() => wrapper.safeQuerySelectorAll(".childSpan", 3)).toThrow(
+ "Expected at least 3 element(s) for selector '.childSpan'. Only 2 found",
+ );
+ });
+
+ it("should pass if expected number of elements are found using safeQuerySelectorAll", () => {
+ const element = document.getElementById("parentDiv");
+ const wrapper = new SafeElementWrapper(element!);
+
+ const childWrappers = wrapper.safeQuerySelectorAll(".childSpan", 2);
+ expect(childWrappers.length).toBe(2);
+ });
+ });
+});
diff --git a/src/test/test_utils.ts b/src/test/test_utils.ts
index 72cf1fbb9..5e576795b 100644
--- a/src/test/test_utils.ts
+++ b/src/test/test_utils.ts
@@ -80,3 +80,71 @@ export const gotoNextView = (container: Element) => {
)!;
fireEvent.click(nextButton);
};
+
+export const safeQuerySelector = (
+ container: HTMLElement,
+ selector: string,
+): T => {
+ const element = container.querySelector(selector);
+ if (element) {
+ return element as T;
+ }
+
+ throw new Error(`Element with selector '${selector}' not found`);
+};
+
+export const safeQuerySelectorAll = (
+ container: HTMLElement,
+ selector: string,
+ minExpected: number = 1,
+): T[] => {
+ const elements = Array.from(container.querySelectorAll(selector)) as T[];
+
+ if (!elements.length) {
+ throw new Error(`Element with selector '${selector}' not found`);
+ }
+ if (elements.length < minExpected) {
+ throw new Error(
+ `Expected at least ${minExpected} element(s) for selector '${selector}'. Only ${elements.length} found`,
+ );
+ }
+
+ return elements;
+};
+
+export class SafeElementWrapper {
+ constructor(private element: T) {}
+
+ getElement(): T {
+ return this.element;
+ }
+
+ safeQuerySelector(
+ selector: string,
+ ): SafeElementWrapper {
+ const element = this.element.querySelector(selector) as E;
+ if (element) {
+ return new SafeElementWrapper(element);
+ }
+
+ throw new Error(`Element with selector '${selector}' not found`);
+ }
+
+ safeQuerySelectorAll(
+ selector: string,
+ minExpected = 1,
+ ): SafeElementWrapper[] {
+ const elements = Array.from(this.element.querySelectorAll(selector)) as E[];
+
+ if (!elements.length) {
+ throw new Error(`Element with selector '${selector}' not found`);
+ }
+ if (elements.length < minExpected) {
+ throw new Error(
+ `Expected at least ${minExpected} element(s) for selector '${selector}'. Only ${elements.length} found`,
+ );
+ }
+
+ return elements.map((element) => new SafeElementWrapper(element));
+ }
+}
diff --git a/src/test/time_input_test.test.tsx b/src/test/time_input_test.test.tsx
index a04ba8906..7dd8fb049 100644
--- a/src/test/time_input_test.test.tsx
+++ b/src/test/time_input_test.test.tsx
@@ -5,6 +5,7 @@ import DatePicker from "../index";
import InputTimeComponent from "../input_time";
import CustomTimeInput from "./helper_components/custom_time_input";
+import { safeQuerySelector } from "./test_utils";
describe("timeInput", () => {
afterEach(() => {
@@ -30,11 +31,11 @@ describe("timeInput", () => {
it("should trigger onChange event", () => {
const onChangeSpy = jest.fn();
const { container } = render();
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: { value: "13:00" },
});
- expect(input?.value).toEqual("13:00");
+ expect(input.value).toEqual("13:00");
});
it("should retain the focus on onChange event", () => {
@@ -42,18 +43,18 @@ describe("timeInput", () => {
const { container } = render(
,
);
- const input = container.querySelector("input");
+ const input = safeQuerySelector(container, "input");
act(() => {
input?.focus();
});
expect(document.activeElement).toBe(input);
- fireEvent.change(input ?? new HTMLElement(), {
+ fireEvent.change(input, {
target: { value: "13:00" },
});
- expect(input?.value).toEqual("13:00");
+ expect(input.value).toEqual("13:00");
expect(document.activeElement).toBe(input);
});
@@ -61,9 +62,9 @@ describe("timeInput", () => {
const { container } = render(
{}} />,
);
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLElement(), { target: { value: "" } });
- expect(input?.value).toEqual("13:00");
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, { target: { value: "" } });
+ expect(input.value).toEqual("13:00");
});
it("should trigger onChange event on a custom time input without using the last valid timeString", () => {
@@ -79,8 +80,8 @@ describe("timeInput", () => {
);
const newTime = "14:00";
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: { value: newTime },
});
@@ -104,8 +105,8 @@ describe("timeInput", () => {
);
const newTime = "14:00";
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: { value: newTime },
});
@@ -121,8 +122,8 @@ describe("timeInput", () => {
);
const newTime = "13:00";
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: { value: newTime },
});
@@ -146,8 +147,8 @@ describe("timeInput", () => {
);
const newTime = "13:00";
- const input = container.querySelector("input");
- fireEvent.change(input ?? new HTMLElement(), {
+ const input = safeQuerySelector(container, "input");
+ fireEvent.change(input, {
target: { value: newTime },
});
diff --git a/src/test/timepicker_test.test.tsx b/src/test/timepicker_test.test.tsx
index 0c51ed079..8db6f4baf 100644
--- a/src/test/timepicker_test.test.tsx
+++ b/src/test/timepicker_test.test.tsx
@@ -4,11 +4,13 @@ import React from "react";
import { formatDate, KeyType } from "../date_utils";
import DatePicker from "../index";
-import { getKey } from "./test_utils";
+import { getKey, safeQuerySelector, safeQuerySelectorAll } from "./test_utils";
+
+const MIN_TIME_LI_LEN = 2;
describe("TimePicker", () => {
- let datePicker: HTMLDivElement | undefined;
- let div: HTMLDivElement | undefined;
+ let datePicker: HTMLDivElement;
+ let div: HTMLDivElement;
let onChangeMoment: Date | undefined;
let instance: DatePicker | null = null;
@@ -29,39 +31,55 @@ describe("TimePicker", () => {
it("should allow time changes after input change", () => {
renderDatePicker("February 28, 2018 4:43 PM");
setManually("February 28, 2018 4:45 PM");
- fireEvent.focus(instance?.input ?? new HTMLElement());
- const time =
- datePicker?.querySelector(".react-datepicker__time-container") ??
- new HTMLElement();
- const lis = time?.querySelectorAll("li");
- fireEvent.click(lis[1] ?? new HTMLElement());
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+
+ fireEvent.focus(instance.input);
+
+ const time = safeQuerySelector(
+ datePicker,
+ ".react-datepicker__time-container",
+ );
+ const lis = safeQuerySelectorAll(time, "li", MIN_TIME_LI_LEN);
+ fireEvent.click(lis[1]!);
expect(getInputString()).toBe("February 28, 2018 12:30 AM");
});
it("should allow for injected date if input does not have focus", () => {
renderDatePicker("February 28, 2018 4:43 PM");
setManually("February 28, 2018 4:45 PM");
- fireEvent.blur(instance?.input ?? new HTMLElement());
+
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+
+ fireEvent.blur(instance.input);
renderDatePicker("February 28, 2018 4:43 PM");
expect(getInputString()).toBe("February 28, 2018 4:43 PM");
});
it("should not close datepicker after time clicked when shouldCloseOnSelect is false", () => {
- let instance: DatePicker | null;
+ let instance: DatePicker;
const { container } = render(
{
- instance = node;
+ if (node) {
+ instance = node;
+ }
}}
shouldCloseOnSelect={false}
showTimeSelect
/>,
);
fireEvent.focus(instance!.input!);
- const time = container.querySelector(".react-datepicker__time-container");
- const lis = time?.querySelectorAll("li") ?? [];
- fireEvent.click(lis?.[0] ?? new HTMLElement());
+ const time = safeQuerySelector(
+ container,
+ ".react-datepicker__time-container",
+ );
+ const lis = safeQuerySelectorAll(time, "li");
+ fireEvent.click(lis[0]!);
expect(instance!.state.open).toBe(true);
});
@@ -95,7 +113,10 @@ describe("TimePicker", () => {
});
expect(getInputString()).toBe("February 28, 2018 9:00 AM");
- fireEvent.focus(instance?.input ?? new HTMLElement());
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+ fireEvent.focus(instance.input);
setManually("February 28, 2018 9:20 AM");
expect(getInputString()).toBe("February 28, 2018 9:20 AM");
@@ -108,7 +129,10 @@ describe("TimePicker", () => {
});
expect(getInputString()).toBe("February 28, 2018 9:00 AM");
- fireEvent.focus(instance?.input ?? new HTMLElement());
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+ fireEvent.focus(instance.input);
setManually("February 28, 2018 9:53 AM");
expect(getInputString()).toBe("February 28, 2018 9:53 AM");
@@ -121,7 +145,10 @@ describe("TimePicker", () => {
});
expect(getInputString()).toBe("July 13, 2020 2:59 PM");
- fireEvent.focus(instance?.input ?? new HTMLElement());
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+ fireEvent.focus(instance.input);
setManually("July 13, 2020 3:00 PM");
expect(getInputString()).toBe("July 13, 2020 3:00 PM");
@@ -147,36 +174,50 @@ describe("TimePicker", () => {
it("should select time when Enter is pressed", () => {
renderDatePicker("February 28, 2018 4:43 PM");
- fireEvent.focus(instance?.input ?? new HTMLElement());
- const time =
- datePicker?.querySelector(".react-datepicker__time-container") ??
- new HTMLElement();
- const lis = time.querySelectorAll("li");
- fireEvent.keyDown(lis[1] ?? new HTMLElement(), getKey(KeyType.Enter));
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+ fireEvent.focus(instance.input);
+ const time = safeQuerySelector(
+ datePicker,
+ ".react-datepicker__time-container",
+ );
+ const lis = safeQuerySelectorAll(time, "li", MIN_TIME_LI_LEN);
+ fireEvent.keyDown(lis[1]!, getKey(KeyType.Enter));
expect(getInputString()).toBe("February 28, 2018 12:30 AM");
});
it("should select time when Space is pressed", () => {
renderDatePicker("February 28, 2018 4:43 PM");
- fireEvent.focus(instance?.input ?? new HTMLElement());
- const time =
- datePicker?.querySelector(".react-datepicker__time-container") ??
- new HTMLElement();
- const lis = time.querySelectorAll("li");
- fireEvent.keyDown(lis[1] ?? new HTMLElement(), getKey(KeyType.Space));
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+ fireEvent.focus(instance.input);
+ const time = safeQuerySelector(
+ datePicker,
+ ".react-datepicker__time-container",
+ );
+ const lis = safeQuerySelectorAll(time, "li", MIN_TIME_LI_LEN);
+ fireEvent.keyDown(lis[1]!, getKey(KeyType.Space));
expect(getInputString()).toBe("February 28, 2018 12:30 AM");
});
it("should return focus to input once time is selected", async () => {
- document.body.appendChild(div ?? new HTMLElement()); // So we can check the dom later for activeElement
+ document.body.appendChild(div); // So we can check the dom later for activeElement
renderDatePicker("February 28, 2018 4:43 PM");
- const input = datePicker?.querySelector("input") ?? new HTMLElement();
- fireEvent.focus(instance?.input ?? new HTMLElement());
- const time =
- datePicker?.querySelector(".react-datepicker__time-container") ??
- new HTMLElement();
- const lis = time.querySelectorAll("li");
- fireEvent.keyDown(lis[1] ?? new HTMLElement(), getKey(KeyType.Enter));
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+
+ const input = safeQuerySelector(datePicker, "input");
+
+ fireEvent.focus(instance.input);
+ const time = safeQuerySelector(
+ datePicker,
+ ".react-datepicker__time-container",
+ );
+ const lis = safeQuerySelectorAll(time, "li", MIN_TIME_LI_LEN);
+ fireEvent.keyDown(lis[1]!, getKey(KeyType.Enter));
await waitFor(() => {
expect(document.activeElement).toBe(input);
@@ -185,12 +226,16 @@ describe("TimePicker", () => {
it("should not select time when Escape is pressed", () => {
renderDatePicker("February 28, 2018 4:43 PM");
- fireEvent.focus(instance?.input ?? new HTMLElement());
- const time =
- datePicker?.querySelector(".react-datepicker__time-container") ??
- new HTMLElement();
- const lis = time.querySelectorAll("li");
- fireEvent.keyDown(lis[1] ?? new HTMLElement(), getKey(KeyType.Escape));
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+ fireEvent.focus(instance.input);
+ const time = safeQuerySelector(
+ datePicker,
+ ".react-datepicker__time-container",
+ );
+ const lis = safeQuerySelectorAll(time, "li", MIN_TIME_LI_LEN);
+ fireEvent.keyDown(lis[1]!, getKey(KeyType.Escape));
expect(getInputString()).toBe("February 28, 2018 4:43 PM");
});
@@ -199,12 +244,16 @@ describe("TimePicker", () => {
renderDatePicker("February 28, 2018 4:43 PM", {
onKeyDown: onKeyDownSpy,
});
- fireEvent.focus(instance?.input ?? new HTMLElement());
- const time =
- datePicker?.querySelector(".react-datepicker__time-container") ??
- new HTMLElement();
- const lis = time.querySelectorAll("li");
- fireEvent.keyDown(lis[1] ?? new HTMLElement(), getKey(KeyType.Escape));
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+ fireEvent.focus(instance.input);
+ const time = safeQuerySelector(
+ datePicker,
+ ".react-datepicker__time-container",
+ );
+ const lis = safeQuerySelectorAll(time, "li", MIN_TIME_LI_LEN);
+ fireEvent.keyDown(lis[1]!, getKey(KeyType.Escape));
expect(onKeyDownSpy).toHaveBeenCalledTimes(1);
});
@@ -213,12 +262,16 @@ describe("TimePicker", () => {
renderDatePicker("February 28, 2018 4:43 PM", {
onKeyDown: onKeyDownSpy,
});
- fireEvent.focus(instance?.input ?? new HTMLElement());
- const time =
- datePicker?.querySelector(".react-datepicker__time-container") ??
- new HTMLElement();
- const lis = time.querySelectorAll("li");
- fireEvent.keyDown(lis[1] ?? new HTMLElement(), getKey(KeyType.Enter));
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+ fireEvent.focus(instance.input);
+ const time = safeQuerySelector(
+ datePicker,
+ ".react-datepicker__time-container",
+ );
+ const lis = safeQuerySelectorAll(time, "li", MIN_TIME_LI_LEN);
+ fireEvent.keyDown(lis[1]!, getKey(KeyType.Enter));
expect(onKeyDownSpy).toHaveBeenCalledTimes(1);
});
@@ -227,12 +280,16 @@ describe("TimePicker", () => {
renderDatePicker("February 28, 2018 4:43 PM", {
onKeyDown: onKeyDownSpy,
});
- fireEvent.focus(instance?.input ?? new HTMLElement());
- const time =
- datePicker?.querySelector(".react-datepicker__time-container") ??
- new HTMLElement();
- const lis = time.querySelectorAll("li");
- fireEvent.keyDown(lis[1] ?? new HTMLElement(), getKey(KeyType.Space));
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+ fireEvent.focus(instance.input);
+ const time = safeQuerySelector(
+ datePicker,
+ ".react-datepicker__time-container",
+ );
+ const lis = safeQuerySelectorAll(time, "li", MIN_TIME_LI_LEN);
+ fireEvent.keyDown(lis[1]!, getKey(KeyType.Space));
expect(onKeyDownSpy).toHaveBeenCalledTimes(1);
});
@@ -242,17 +299,22 @@ describe("TimePicker", () => {
onKeyDown: onKeyDownSpy,
showTimeSelectOnly: true,
});
- fireEvent.focus(instance?.input ?? new HTMLElement());
- fireEvent.keyDown(
- instance?.input ?? new HTMLElement(),
- getKey(KeyType.ArrowDown),
- );
+
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+
+ fireEvent.focus(instance.input);
+ fireEvent.keyDown(instance.input, getKey(KeyType.ArrowDown));
expect(onKeyDownSpy).toHaveBeenCalledTimes(1);
});
function setManually(string: string) {
- fireEvent.focus(instance?.input ?? new HTMLElement());
- fireEvent.change(instance?.input ?? new HTMLElement(), {
+ if (!instance?.input) {
+ throw new Error("input is null/undefined");
+ }
+ fireEvent.focus(instance.input);
+ fireEvent.change(instance.input, {
target: { value: string },
});
}
diff --git a/src/test/week_number_test.test.tsx b/src/test/week_number_test.test.tsx
index ab2d33f6f..baa704cfa 100644
--- a/src/test/week_number_test.test.tsx
+++ b/src/test/week_number_test.test.tsx
@@ -4,6 +4,8 @@ import React from "react";
import { KeyType, addWeeks, newDate } from "../date_utils";
import WeekNumber from "../week_number";
+import { safeQuerySelector } from "./test_utils";
+
type WeekNumberProps = React.ComponentProps;
function renderWeekNumber(
@@ -37,11 +39,11 @@ describe("WeekNumber", () => {
const { container } = render(
,
);
- const weekNumber = container.querySelector(
+ const weekNumber = safeQuerySelector(
+ container,
".react-datepicker__week-number",
);
- expect(weekNumber).not.toBeNull();
- fireEvent.click(weekNumber ?? new HTMLDivElement());
+ fireEvent.click(weekNumber);
expect(onClickMock).toHaveBeenCalledTimes(1);
});
@@ -104,11 +106,11 @@ describe("WeekNumber", () => {
const { container } = render(
,
);
- const weekNumber = container.querySelector(
+ const weekNumber = safeQuerySelector(
+ container,
".react-datepicker__week-number",
);
- expect(weekNumber).not.toBeNull();
- fireEvent.click(weekNumber ?? new HTMLDivElement());
+ fireEvent.click(weekNumber);
expect(onClickMock).toHaveBeenCalled();
});
diff --git a/src/test/week_picker_test.test.tsx b/src/test/week_picker_test.test.tsx
index 76b3f2a60..e5ecb0bc1 100644
--- a/src/test/week_picker_test.test.tsx
+++ b/src/test/week_picker_test.test.tsx
@@ -3,6 +3,8 @@ import React from "react";
import DatePicker from "../index";
+import { safeQuerySelector } from "./test_utils";
+
describe("WeekPicker", () => {
it("should change the week when clicked on any option in the picker", () => {
const onChangeSpy = jest.fn();
@@ -10,10 +12,12 @@ describe("WeekPicker", () => {
,
);
expect(onChangeSpy).not.toHaveBeenCalled();
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
- fireEvent.click(
- container.querySelector(".react-datepicker__day") ?? new HTMLElement(),
- );
+
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+
+ const dayElement = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.click(dayElement);
expect(onChangeSpy).toHaveBeenCalled();
});
@@ -23,14 +27,13 @@ describe("WeekPicker", () => {
,
);
expect(onChangeSpy).not.toHaveBeenCalled();
- const input = container.querySelector("input");
- expect(input).not.toBeNull();
- fireEvent.focus(input ?? new HTMLElement());
- const weekNumber = container.querySelector(
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
+ const weekNumber = safeQuerySelector(
+ container,
".react-datepicker__week-number",
);
- expect(weekNumber).not.toBeNull();
- fireEvent.click(weekNumber ?? new HTMLElement());
+ fireEvent.click(weekNumber);
expect(onChangeSpy).toHaveBeenCalled();
});
diff --git a/src/test/week_test.test.tsx b/src/test/week_test.test.tsx
index dedd97367..1a6200c3e 100644
--- a/src/test/week_test.test.tsx
+++ b/src/test/week_test.test.tsx
@@ -13,6 +13,8 @@ import {
} from "../date_utils";
import Week from "../week";
+import { safeQuerySelector } from "./test_utils";
+
describe("Week", () => {
it("should have the week CSS class", () => {
const { container } = render(
@@ -109,11 +111,12 @@ describe("Week", () => {
month={getMonth(weekStart)}
/>,
);
- const weekNumberElement = container.querySelector(
+
+ const weekNumberElement = safeQuerySelector(
+ container,
".react-datepicker__week-number",
);
- expect(weekNumberElement).not.toBeNull();
- fireEvent.click(weekNumberElement ?? new HTMLElement());
+ fireEvent.click(weekNumberElement);
expect(isEqual(firstDayReceived, weekStart)).toBe(true);
});
@@ -131,11 +134,11 @@ describe("Week", () => {
month={getMonth(weekStart)}
/>,
);
- const weekNumberElement = container.querySelector(
+ const weekNumberElement = safeQuerySelector(
+ container,
".react-datepicker__week-number",
);
- expect(weekNumberElement).not.toBeNull();
- fireEvent.click(weekNumberElement ?? new HTMLElement());
+ fireEvent.click(weekNumberElement);
expect(setOpenSpy).toHaveBeenCalledTimes(1);
});
@@ -155,12 +158,12 @@ describe("Week", () => {
/>,
);
- const weekNumberElement = container.querySelector(
+ const weekNumberElement = safeQuerySelector(
+ container,
".react-datepicker__week-number",
);
- expect(weekNumberElement).not.toBeNull();
+ fireEvent.click(weekNumberElement);
- fireEvent.click(weekNumberElement ?? new HTMLElement());
expect(setOnWeekSelect).toHaveBeenCalledTimes(1);
expect(setOpenSpy).toHaveBeenCalledTimes(0);
});
@@ -183,11 +186,12 @@ describe("Week", () => {
month={getMonth(weekStart)}
/>,
);
- const weekNumberElement = container.querySelector(
+
+ const weekNumberElement = safeQuerySelector(
+ container,
".react-datepicker__week-number",
);
- expect(weekNumberElement).not.toBeNull();
- fireEvent.click(weekNumberElement ?? new HTMLElement());
+ fireEvent.click(weekNumberElement);
expect(weekNumberReceived).toBe(realWeekNumber);
});
@@ -227,9 +231,8 @@ describe("Week", () => {
/>,
);
- const day = container.querySelector(".react-datepicker__day");
- expect(day).not.toBeNull();
- fireEvent.mouseEnter(day ?? new HTMLElement());
+ const day = safeQuerySelector(container, ".react-datepicker__day");
+ fireEvent.mouseEnter(day);
expect(onDayMouseEnterSpy).toHaveBeenLastCalledWith(
getStartOfWeek(weekStart),
diff --git a/src/test/year_dropdown_options_test.test.tsx b/src/test/year_dropdown_options_test.test.tsx
index b9ce438f0..370124cdd 100644
--- a/src/test/year_dropdown_options_test.test.tsx
+++ b/src/test/year_dropdown_options_test.test.tsx
@@ -4,9 +4,10 @@ import React from "react";
import { addYears, getYear, newDate, subYears } from "../date_utils";
import YearDropdownOptions from "../year_dropdown_options";
+import { safeQuerySelector, safeQuerySelectorAll } from "./test_utils";
+
describe("YearDropdownOptions", () => {
- let yearDropdown: HTMLElement | null = null,
- handleChangeResult: number;
+ let yearDropdown: HTMLElement, handleChangeResult: number;
const mockHandleChange = function (changeInput: number) {
handleChangeResult = changeInput;
};
@@ -57,11 +58,11 @@ describe("YearDropdownOptions", () => {
});
it("increments the available years when the 'upcoming years' button is clicked", () => {
- fireEvent.click(
- yearDropdown?.querySelector(
- ".react-datepicker__navigation--years-upcoming",
- ) ?? new HTMLElement(),
+ const navigationYearsUpcoming = safeQuerySelector(
+ yearDropdown,
+ ".react-datepicker__navigation--years-upcoming",
);
+ fireEvent.click(navigationYearsUpcoming);
const textContents = Array.from(
yearDropdown?.querySelectorAll(".react-datepicker__year-option") ?? [],
@@ -87,11 +88,11 @@ describe("YearDropdownOptions", () => {
});
it("decrements the available years when the 'previous years' button is clicked", () => {
- fireEvent.click(
- yearDropdown?.querySelector(
- ".react-datepicker__navigation--years-previous",
- ) ?? new HTMLElement(),
+ const navigationYearsPrevious = safeQuerySelector(
+ yearDropdown,
+ ".react-datepicker__navigation--years-previous",
);
+ fireEvent.click(navigationYearsPrevious);
const textContents = Array.from(
yearDropdown?.querySelectorAll(".react-datepicker__year-option") ?? [],
@@ -117,11 +118,17 @@ describe("YearDropdownOptions", () => {
});
it("calls the supplied onChange function when a year is clicked", () => {
- fireEvent.click(
- Array.from(
- yearDropdown?.querySelectorAll(".react-datepicker__year-option") ?? [],
- ).find((node) => node.textContent?.includes("2015")) ?? new HTMLElement(),
+ const yearOptions = safeQuerySelectorAll(
+ yearDropdown,
+ ".react-datepicker__year-option",
);
+ const year = yearOptions.find((node) => node.textContent?.includes("2015"));
+
+ if (!year) {
+ throw new Error("Year 2015 not found!");
+ }
+
+ fireEvent.click(year);
expect(handleChangeResult).toBe(2015);
});
@@ -310,11 +317,11 @@ describe("YearDropdownOptions with scrollable dropwdown", () => {
),
).toBeUndefined();
- fireEvent.click(
- container.querySelector(
- ".react-datepicker__navigation--years-previous",
- ) ?? new HTMLElement(),
+ const navigationYearsPrevious = safeQuerySelector(
+ container,
+ ".react-datepicker__navigation--years-previous",
);
+ fireEvent.click(navigationYearsPrevious);
textContents = Array.from(
container.querySelectorAll(".react-datepicker__year-option"),
@@ -335,11 +342,12 @@ describe("YearDropdownOptions with scrollable dropwdown", () => {
).length,
).toBe(0);
- fireEvent.click(
- container.querySelector(
- ".react-datepicker__navigation--years-upcoming",
- ) ?? new HTMLElement(),
+ const navigationYearsUpcoming = safeQuerySelector(
+ container,
+ ".react-datepicker__navigation--years-upcoming",
);
+ fireEvent.click(navigationYearsUpcoming);
+
textContents = Array.from(
container.querySelectorAll(".react-datepicker__year-option"),
).filter((node) => node.textContent);
@@ -391,11 +399,11 @@ describe("YearDropdownOptions with scrollable dropwdown", () => {
),
).toBeUndefined();
- fireEvent.click(
- container.querySelector(
- ".react-datepicker__navigation--years-previous",
- ) ?? new HTMLElement(),
+ const navigationYearsPrevious = safeQuerySelector(
+ container,
+ ".react-datepicker__navigation--years-previous",
);
+ fireEvent.click(navigationYearsPrevious);
textContents = Array.from(
container.querySelectorAll(".react-datepicker__year-option"),
@@ -453,11 +461,11 @@ describe("YearDropdownOptions with scrollable dropwdown", () => {
),
).toBeUndefined();
- fireEvent.click(
- container.querySelector(
- ".react-datepicker__navigation--years-upcoming",
- ) ?? new HTMLElement(),
+ const navigationYearsUpcoming = safeQuerySelector(
+ container,
+ ".react-datepicker__navigation--years-upcoming",
);
+ fireEvent.click(navigationYearsUpcoming);
textContents = Array.from(
container.querySelectorAll(".react-datepicker__year-option"),
diff --git a/src/test/year_dropdown_test.test.tsx b/src/test/year_dropdown_test.test.tsx
index b91a9c841..784a7ac21 100644
--- a/src/test/year_dropdown_test.test.tsx
+++ b/src/test/year_dropdown_test.test.tsx
@@ -4,10 +4,10 @@ import React from "react";
import { newDate } from "../date_utils";
import YearDropdown from "../year_dropdown";
-import { range } from "./test_utils";
+import { range, safeQuerySelector, safeQuerySelectorAll } from "./test_utils";
describe("YearDropdown", () => {
- let yearDropdown: HTMLElement | null = null;
+ let yearDropdown: HTMLElement;
let lastOnChangeValue: number | null;
function onChangeMock(value: number) {
@@ -50,10 +50,11 @@ describe("YearDropdown", () => {
});
it("opens a list when read view is clicked", () => {
- fireEvent.click(
- yearDropdown?.querySelector(".react-datepicker__year-read-view") ??
- new HTMLElement(),
+ const yearReadView = safeQuerySelector(
+ yearDropdown,
+ ".react-datepicker__year-read-view",
);
+ fireEvent.click(yearReadView);
const optionsView = yearDropdown?.querySelectorAll(
"react-datepicker__year-dropdown",
);
@@ -61,40 +62,58 @@ describe("YearDropdown", () => {
});
it("closes the dropdown when a year is clicked", () => {
- fireEvent.click(
- yearDropdown?.querySelector(".react-datepicker__year-read-view") ??
- new HTMLElement(),
+ const yearReadView = safeQuerySelector(
+ yearDropdown,
+ ".react-datepicker__year-read-view",
);
- fireEvent.click(
- (yearDropdown?.querySelectorAll(".react-datepicker__year-option") ??
- [])[0] ?? new HTMLElement(),
+ fireEvent.click(yearReadView);
+
+ const yearOptions = safeQuerySelectorAll(
+ yearDropdown,
+ ".react-datepicker__year-option",
);
+ const yearOption = yearOptions[0]!;
+ fireEvent.click(yearOption);
expect(
yearDropdown?.querySelectorAll("react-datepicker__year-dropdown"),
).toHaveLength(0);
});
it("does not call the supplied onChange function when the same year is clicked", () => {
- fireEvent.click(
- yearDropdown?.querySelector(".react-datepicker__year-read-view") ??
- new HTMLElement(),
+ const yearReadView = safeQuerySelector(
+ yearDropdown,
+ ".react-datepicker__year-read-view",
);
- fireEvent.click(
- (yearDropdown?.querySelectorAll(".react-datepicker__year-option") ??
- [])[6] ?? new HTMLElement(),
+ fireEvent.click(yearReadView);
+
+ const minYearOptionsLen = 7;
+ const yearOptions = safeQuerySelectorAll(
+ yearDropdown,
+ ".react-datepicker__year-option",
+ minYearOptionsLen,
);
+
+ const yearOption = yearOptions[6]!;
+ fireEvent.click(yearOption);
expect(lastOnChangeValue).toBeNull();
});
it("calls the supplied onChange function when a different year is clicked", () => {
- fireEvent.click(
- yearDropdown?.querySelector(".react-datepicker__year-read-view") ??
- new HTMLElement(),
+ const yearReadView = safeQuerySelector(
+ yearDropdown,
+ ".react-datepicker__year-read-view",
);
- fireEvent.click(
- (yearDropdown?.querySelectorAll(".react-datepicker__year-option") ??
- [])[7] ?? new HTMLElement(),
+ fireEvent.click(yearReadView);
+
+ const minYearOptionsLen = 7;
+ const yearOptions = safeQuerySelectorAll(
+ yearDropdown,
+ ".react-datepicker__year-option",
+ minYearOptionsLen,
);
+
+ const yearOption = yearOptions[7]!;
+ fireEvent.click(yearOption);
expect(lastOnChangeValue).toEqual(2014);
});
});
diff --git a/src/test/year_picker_test.test.tsx b/src/test/year_picker_test.test.tsx
index abfe3e27d..4ea99267c 100644
--- a/src/test/year_picker_test.test.tsx
+++ b/src/test/year_picker_test.test.tsx
@@ -14,7 +14,13 @@ import {
import DatePicker from "../index";
import Year from "../year";
-import { getKey, gotoNextView, openDateInput } from "./test_utils";
+import {
+ getKey,
+ gotoNextView,
+ openDateInput,
+ safeQuerySelector,
+ safeQuerySelectorAll,
+} from "./test_utils";
const getYearOffset = (calendar: Element, date: Date): number => {
const dateNode = calendar.querySelector(
@@ -71,10 +77,16 @@ describe("YearPicker", () => {
onYearMouseLeave={() => {}}
/>,
);
- const firstYearDiv = container.querySelectorAll(
+
+ const minRequiredYearLen = 2;
+ const yearDivs = safeQuerySelectorAll(
+ container,
".react-datepicker__year-text",
- )[1];
- fireEvent.click(firstYearDiv ?? new HTMLElement());
+ minRequiredYearLen,
+ );
+
+ const firstYearDiv = yearDivs[1]!;
+ fireEvent.click(firstYearDiv);
expect(onYearChangeSpy).toHaveBeenCalled();
});
@@ -563,13 +575,15 @@ describe("YearPicker", () => {
/>,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
- const calendar = container.querySelector(".react-datepicker");
- const previousButton = calendar?.querySelector(
+ const calendar = safeQuerySelector(container, ".react-datepicker");
+ const previousButton = safeQuerySelector(
+ calendar,
".react-datepicker__navigation--previous",
);
- fireEvent.click(previousButton ?? new HTMLElement());
+ fireEvent.click(previousButton);
const year = container.querySelector(".react-datepicker__year");
const allPreselectedYears = year?.querySelectorAll(`.${className}`) ?? [];
@@ -594,14 +608,16 @@ describe("YearPicker", () => {
/>,
);
- fireEvent.focus(container.querySelector("input") ?? new HTMLElement());
+ const input = safeQuerySelector(container, "input");
+ fireEvent.focus(input);
- const calendar = container.querySelector(".react-datepicker");
- const nextButton = calendar?.querySelector(
+ const calendar = safeQuerySelector(container, ".react-datepicker");
+ const nextButton = safeQuerySelector(
+ calendar,
".react-datepicker__navigation--next",
);
- fireEvent.click(nextButton ?? new HTMLElement());
+ fireEvent.click(nextButton);
const year = container.querySelector(".react-datepicker__year");
const allPreselectedYears = year?.querySelectorAll(`.${className}`) ?? [];
@@ -683,131 +699,144 @@ describe("YearPicker", () => {
it("should preSelect and set 2020 on left arrow press", () => {
const yearPicker = getPicker("2021-01-01");
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateLeft(target ?? new HTMLElement());
+ simulateLeft(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2020);
});
it("should preSelect and set 2022 on left arrow press", () => {
const yearPicker = getPicker("2021-01-01");
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateRight(target ?? new HTMLElement());
+ simulateRight(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2022);
});
it("should preSelect and set 2021 on up arrow press", () => {
const yearPicker = getPicker("2024-01-01");
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateUp(target ?? new HTMLElement());
+ simulateUp(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2021);
});
it("should preSelect and set 2027 on down arrow press", () => {
const yearPicker = getPicker("2024-01-01");
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateDown(target ?? new HTMLElement());
+ simulateDown(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2027);
});
it("should paginate from 2018 to 2015", () => {
const yearPicker = getPicker("2018-01-01");
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateUp(target ?? new HTMLElement());
+ simulateUp(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2015);
});
it("should paginate from 2018 to 2016 with custom yearItemNumber", () => {
const yearPicker = getPicker("2018-01-01", { yearItemNumber: 8 });
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateUp(target ?? new HTMLElement());
+ simulateUp(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2016);
});
it("should paginate from 2019 to 2014 with custom yearItemNumber", () => {
const yearPicker = getPicker("2019-01-01", { yearItemNumber: 8 });
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateUp(target ?? new HTMLElement());
+ simulateUp(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2014);
});
it("should paginate from 2028 to 2031", () => {
const yearPicker = getPicker("2028-01-01");
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateDown(target ?? new HTMLElement());
+ simulateDown(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2031);
});
it("should paginate from 2024 to 2026 with custom yearItemNumber", () => {
const yearPicker = getPicker("2024-01-01", { yearItemNumber: 8 });
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateDown(target ?? new HTMLElement());
+ simulateDown(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2026);
});
it("should paginate from 2022 to 2027 with custom yearItemNumber", () => {
const yearPicker = getPicker("2022-01-01", { yearItemNumber: 8 });
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateDown(target ?? new HTMLElement());
+ simulateDown(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2027);
});
it("should paginate from 2017 to 2016", () => {
const yearPicker = getPicker("2017-01-01");
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateLeft(target ?? new HTMLElement());
+ simulateLeft(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2016);
});
it("should paginate from 2028 to 2029", () => {
const yearPicker = getPicker("2028-01-01");
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateRight(target ?? new HTMLElement());
+ simulateRight(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2029);
});
it("should select 2021 when Enter key is pressed", () => {
const yearPicker = getPicker("2021-01-01");
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- fireEvent.keyDown(target ?? new HTMLElement(), getKey(KeyType.Enter));
+ fireEvent.keyDown(target, getKey(KeyType.Enter));
expect(selectedDay ? getYear(selectedDay) : selectedDay).toBe(2021);
});
@@ -823,12 +852,12 @@ describe("YearPicker", () => {
/>,
);
- const dateInput = container.querySelector("input");
- fireEvent.focus(dateInput ?? new HTMLElement());
+ const dateInput = safeQuerySelector(container, "input");
+ fireEvent.focus(dateInput);
- const year = container.querySelector(".react-datepicker__year-text");
+ const year = safeQuerySelector(container, ".react-datepicker__year-text");
- fireEvent.keyDown(year ?? new HTMLElement(), getKey(KeyType.ArrowDown));
+ fireEvent.keyDown(year, getKey(KeyType.ArrowDown));
expect(onKeyDownSpy).toHaveBeenCalledTimes(1);
});
@@ -836,11 +865,12 @@ describe("YearPicker", () => {
it("should select 2021 when Space key is pressed", () => {
const yearPicker = getPicker("2021-01-01");
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- fireEvent.keyDown(target ?? new HTMLElement(), getKey(KeyType.Space));
+ fireEvent.keyDown(target, getKey(KeyType.Space));
expect(selectedDay ? getYear(selectedDay) : selectedDay).toBe(2021);
});
@@ -849,10 +879,11 @@ describe("YearPicker", () => {
disabledKeyboardNavigation: true,
});
- const target = yearPicker.querySelector(
+ const target = safeQuerySelector(
+ yearPicker,
".react-datepicker__year-text--selected",
);
- simulateRight(target ?? new HTMLElement());
+ simulateRight(target);
expect(preSelected ? getYear(preSelected) : preSelected).toBe(2021);
});