Skip to content

Commit 54c5fee

Browse files
Add comprehensive keyboard navigation tests for dropdown components
- Add tests for ArrowUp/ArrowDown navigation in month dropdown - Add tests for Escape key handling in month dropdown - Add tests for month wrapping (first->last, last->first) - Add tests for Enter/Escape/Arrow keys in year dropdown - Improves test coverage to 100% line coverage for both components - Resolves Codecov coverage gaps in dropdown keyboard accessibility 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent f25a805 commit 54c5fee

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

src/test/month_dropdown_test.test.tsx

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,83 @@ describe("MonthDropdown", () => {
214214
fireEvent.keyDown(document.activeElement!, { key: "Enter" });
215215
expect(handleChangeResult).toEqual(4);
216216
});
217+
218+
it("handles ArrowUp key navigation correctly", () => {
219+
const monthReadView = safeQuerySelector(
220+
monthDropdown,
221+
".react-datepicker__month-read-view",
222+
);
223+
fireEvent.click(monthReadView);
224+
225+
const monthOptions = safeQuerySelectorAll(
226+
monthDropdown,
227+
".react-datepicker__month-option",
228+
);
229+
230+
const monthOption = monthOptions[5]!;
231+
fireEvent.keyDown(monthOption, { key: "ArrowUp" });
232+
233+
const prevMonthOption = monthOptions[4];
234+
expect(document.activeElement).toEqual(prevMonthOption);
235+
});
236+
237+
it("handles Escape key to cancel dropdown", () => {
238+
const monthReadView = safeQuerySelector(
239+
monthDropdown,
240+
".react-datepicker__month-read-view",
241+
);
242+
fireEvent.click(monthReadView);
243+
244+
const monthOptions = safeQuerySelectorAll(
245+
monthDropdown,
246+
".react-datepicker__month-option",
247+
);
248+
249+
const monthOption = monthOptions[5]!;
250+
fireEvent.keyDown(monthOption, { key: "Escape" });
251+
252+
expect(
253+
monthDropdown?.querySelectorAll(".react-datepicker__month-dropdown"),
254+
).toHaveLength(0);
255+
});
256+
257+
it("wraps around when using ArrowUp on first month", () => {
258+
const monthReadView = safeQuerySelector(
259+
monthDropdown,
260+
".react-datepicker__month-read-view",
261+
);
262+
fireEvent.click(monthReadView);
263+
264+
const monthOptions = safeQuerySelectorAll(
265+
monthDropdown,
266+
".react-datepicker__month-option",
267+
);
268+
269+
const firstMonthOption = monthOptions[0]!;
270+
fireEvent.keyDown(firstMonthOption, { key: "ArrowUp" });
271+
272+
const lastMonthOption = monthOptions[11];
273+
expect(document.activeElement).toEqual(lastMonthOption);
274+
});
275+
276+
it("wraps around when using ArrowDown on last month", () => {
277+
const monthReadView = safeQuerySelector(
278+
monthDropdown,
279+
".react-datepicker__month-read-view",
280+
);
281+
fireEvent.click(monthReadView);
282+
283+
const monthOptions = safeQuerySelectorAll(
284+
monthDropdown,
285+
".react-datepicker__month-option",
286+
);
287+
288+
const lastMonthOption = monthOptions[11]!;
289+
fireEvent.keyDown(lastMonthOption, { key: "ArrowDown" });
290+
291+
const firstMonthOption = monthOptions[0];
292+
expect(document.activeElement).toEqual(firstMonthOption);
293+
});
217294
});
218295

219296
describe("select mode", () => {

src/test/year_dropdown_options_test.test.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,76 @@ describe("YearDropdownOptions", () => {
146146
expect(onCancelSpy).toHaveBeenCalledTimes(2);
147147
});
148148

149+
it("handles Enter key to select year", () => {
150+
const yearOptions = safeQuerySelectorAll(
151+
yearDropdown,
152+
".react-datepicker__year-option",
153+
);
154+
const year2014Option = yearOptions.find((node) =>
155+
node.textContent?.includes("2014"),
156+
);
157+
158+
if (!year2014Option) {
159+
throw new Error("Year 2014 not found!");
160+
}
161+
162+
fireEvent.keyDown(year2014Option, { key: "Enter" });
163+
expect(handleChangeResult).toBe(2014);
164+
});
165+
166+
it("handles Escape key to cancel dropdown", () => {
167+
const yearOptions = safeQuerySelectorAll(
168+
yearDropdown,
169+
".react-datepicker__year-option",
170+
);
171+
const year2014Option = yearOptions.find((node) =>
172+
node.textContent?.includes("2014"),
173+
);
174+
175+
if (!year2014Option) {
176+
throw new Error("Year 2014 not found!");
177+
}
178+
179+
fireEvent.keyDown(year2014Option, { key: "Escape" });
180+
expect(onCancelSpy).toHaveBeenCalled();
181+
});
182+
183+
it("handles ArrowUp key navigation", () => {
184+
const yearOptions = safeQuerySelectorAll(
185+
yearDropdown,
186+
".react-datepicker__year-option",
187+
);
188+
const year2015Option = yearOptions.find((node) =>
189+
node.textContent?.includes("✓2015"),
190+
);
191+
192+
if (!year2015Option) {
193+
throw new Error("Year 2015 not found!");
194+
}
195+
196+
fireEvent.keyDown(year2015Option, { key: "ArrowUp" });
197+
// ArrowUp should focus year 2016 (year + 1 in the code)
198+
expect(document.activeElement?.textContent).toContain("2016");
199+
});
200+
201+
it("handles ArrowDown key navigation", () => {
202+
const yearOptions = safeQuerySelectorAll(
203+
yearDropdown,
204+
".react-datepicker__year-option",
205+
);
206+
const year2015Option = yearOptions.find((node) =>
207+
node.textContent?.includes("✓2015"),
208+
);
209+
210+
if (!year2015Option) {
211+
throw new Error("Year 2015 not found!");
212+
}
213+
214+
fireEvent.keyDown(year2015Option, { key: "ArrowDown" });
215+
// ArrowDown should focus year 2014 (year - 1 in the code)
216+
expect(document.activeElement?.textContent).toContain("2014");
217+
});
218+
149219
describe("selected", () => {
150220
const className = "react-datepicker__year-option--selected_year";
151221
let yearOptions: HTMLElement[];

0 commit comments

Comments
 (0)