diff --git a/src/index.tsx b/src/index.tsx index c78256aaab..1b4186971f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -452,17 +452,24 @@ export default class DatePicker extends Component< } }; + safeFocus = () => { + setTimeout(() => { + this.input?.focus?.({ preventScroll: true }); + }, 0); + }; + + safeBlur = () => { + setTimeout(() => { + this.input?.blur?.(); + }, 0); + }; + setFocus = () => { - if (this.input && this.input.focus) { - this.input.focus({ preventScroll: true }); - } + this.safeFocus(); }; setBlur = () => { - if (this.input && this.input.blur) { - this.input.blur(); - } - + this.safeBlur(); this.cancelFocusInput(); }; diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx index 02371fe875..883a6d9524 100644 --- a/src/test/datepicker_test.test.tsx +++ b/src/test/datepicker_test.test.tsx @@ -580,7 +580,24 @@ describe("DatePicker", () => { }); }); - it("should hide the calendar when the pressing Shift + Tab in the date input", () => { + it("should auto-close the datepicker and lose focus when Tab key is pressed when the date input is focused", async () => { + const { container } = render(); + const input = safeQuerySelector(container, "input"); + fireEvent.focus(input); + + let reactCalendar = container.querySelector("div.react-datepicker"); + expect(reactCalendar).not.toBeNull(); + + fireEvent.keyDown(input, getKey(KeyType.Tab)); + + reactCalendar = container.querySelector("div.react-datepicker"); + expect(reactCalendar).toBeNull(); + await waitFor(() => { + expect(document.activeElement).not.toBe(input); + }); + }); + + it("should hide the calendar when the pressing Shift + Tab in the date input", async () => { // eslint-disable-next-line prefer-const let onBlurSpy: ReturnType; const onBlur: React.FocusEventHandler = ( @@ -594,7 +611,9 @@ describe("DatePicker", () => { fireEvent.focus(input); fireEvent.keyDown(input, getKey(KeyType.Tab, true)); expect(container.querySelector(".react-datepicker")).toBeNull(); - expect(onBlurSpy).toHaveBeenCalled(); + await waitFor(() => { + expect(onBlurSpy).toHaveBeenCalled(); + }); }); it("should not apply the react-datepicker-ignore-onclickoutside class to the date input when closed", () => { @@ -1964,7 +1983,7 @@ describe("DatePicker", () => { }); expect(div.querySelector("input")).toBe(document.activeElement); }); - it("should autoFocus the input when calling the setFocus method", () => { + it("should autoFocus the input when calling the setFocus method", async () => { const div = document.createElement("div"); document.body.appendChild(div); let instance: DatePicker | null = null; @@ -1982,7 +2001,9 @@ describe("DatePicker", () => { act(() => { instance!.setFocus(); }); - expect(div.querySelector("input")).toBe(document.activeElement); + await waitFor(() => { + expect(div.querySelector("input")).toBe(document.activeElement); + }); }); it("should clear preventFocus timeout id when component is unmounted", () => { const div = document.createElement("div");