diff --git a/src/test/calendar_test.test.tsx b/src/test/calendar_test.test.tsx
index 81ac627b5d..8d2814668f 100644
--- a/src/test/calendar_test.test.tsx
+++ b/src/test/calendar_test.test.tsx
@@ -45,6 +45,7 @@ import {
SafeElementWrapper,
safeQuerySelector,
safeQuerySelectorAll,
+ setupMockResizeObserver,
} from "./test_utils";
import type { ReactDatePickerCustomHeaderProps } from "../calendar";
@@ -136,6 +137,10 @@ describe("Calendar", () => {
};
}
+ beforeAll(() => {
+ setupMockResizeObserver();
+ });
+
it("should start with the current date in view if no date range", () => {
const now = newDate();
const { instance } = getCalendar();
diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx
index eeb3d83976..21548de05e 100644
--- a/src/test/datepicker_test.test.tsx
+++ b/src/test/datepicker_test.test.tsx
@@ -29,7 +29,11 @@ import DatePicker, { registerLocale } from "../index";
import CustomInput from "./helper_components/custom_input";
import ShadowRoot from "./helper_components/shadow_root";
import TestWrapper from "./helper_components/test_wrapper";
-import { getKey, safeQuerySelector } from "./test_utils";
+import {
+ getKey,
+ safeQuerySelector,
+ setupMockResizeObserver,
+} from "./test_utils";
function getSelectedDayNode(container: HTMLElement) {
return (
@@ -83,6 +87,10 @@ const showDocument = (calendarInput: HTMLElement) => {
};
describe("DatePicker", () => {
+ beforeEach(() => {
+ setupMockResizeObserver();
+ });
+
afterEach(() => {
jest.resetAllMocks();
});
diff --git a/src/test/exclude_time_period_test.test.tsx b/src/test/exclude_time_period_test.test.tsx
index 6531bf649f..68bc3acc0f 100644
--- a/src/test/exclude_time_period_test.test.tsx
+++ b/src/test/exclude_time_period_test.test.tsx
@@ -2,9 +2,14 @@ import { render } from "@testing-library/react";
import React from "react";
import { newDate, setTime } from "../date_utils";
+import { setupMockResizeObserver } from "./test_utils";
import DatePicker from "../index";
describe("DatePicker", () => {
+ beforeAll(() => {
+ setupMockResizeObserver();
+ });
+
it("should only display times between minTime and maxTime", () => {
const now = newDate();
const { container } = render(
diff --git a/src/test/exclude_times_test.test.tsx b/src/test/exclude_times_test.test.tsx
index 69745a3e3a..d477d80893 100644
--- a/src/test/exclude_times_test.test.tsx
+++ b/src/test/exclude_times_test.test.tsx
@@ -2,11 +2,16 @@ import { render } from "@testing-library/react";
import React from "react";
import { setTime, newDate } from "../date_utils";
+import { setupMockResizeObserver } from "./test_utils";
import DatePicker from "../index";
describe("DatePicker", () => {
let now: Date, excludeTimes: Date[];
+ beforeAll(() => {
+ setupMockResizeObserver();
+ });
+
beforeEach(() => {
now = newDate();
excludeTimes = [
diff --git a/src/test/min_time_test.test.tsx b/src/test/min_time_test.test.tsx
index 2eaf280c74..d705695294 100644
--- a/src/test/min_time_test.test.tsx
+++ b/src/test/min_time_test.test.tsx
@@ -3,7 +3,7 @@ import React, { useState } from "react";
import DatePicker from "../index";
-import { safeQuerySelector } from "./test_utils";
+import { safeQuerySelector, setupMockResizeObserver } from "./test_utils";
import type { DatePickerProps } from "../index";
@@ -44,6 +44,10 @@ const DatePickerWithState = (
};
describe("Datepicker minTime", () => {
+ beforeAll(() => {
+ setupMockResizeObserver();
+ });
+
it("should select time 12:00 AM when no minTime constraint is set.", () => {
const { getByText, container } = render();
diff --git a/src/test/show_time_test.test.tsx b/src/test/show_time_test.test.tsx
index 0fdfbf442d..a64a4785e6 100644
--- a/src/test/show_time_test.test.tsx
+++ b/src/test/show_time_test.test.tsx
@@ -4,9 +4,13 @@ import React from "react";
import DatePicker from "../index";
import TimeComponent from "../time";
-import { safeQuerySelector } from "./test_utils";
+import { safeQuerySelector, setupMockResizeObserver } from "./test_utils";
describe("DatePicker", () => {
+ beforeAll(() => {
+ setupMockResizeObserver();
+ });
+
it("should show time component when showTimeSelect prop is present", () => {
const { container } = render();
const timeComponent = container.querySelector(
diff --git a/src/test/test_utils.ts b/src/test/test_utils.ts
index 54f8073c57..83e075a00d 100644
--- a/src/test/test_utils.ts
+++ b/src/test/test_utils.ts
@@ -123,6 +123,37 @@ export const safeQuerySelectorAll = (
return elements;
};
+let _resizeObserverCallbackFn: ResizeObserverCallback | null;
+
+export const getResizeObserverCallback = () => _resizeObserverCallbackFn;
+
+export const setupMockResizeObserver = () => {
+ const mockObserve = jest.fn();
+ const mockDisconnect = jest.fn();
+ const mockUnobserve = jest.fn();
+
+ const ResizeObserverMock = jest.fn((fn) => {
+ _resizeObserverCallbackFn = fn;
+
+ return {
+ observe: mockObserve,
+ disconnect: () => {
+ _resizeObserverCallbackFn = null;
+ mockDisconnect();
+ },
+ unobserve: jest.fn(),
+ };
+ });
+
+ global.ResizeObserver = ResizeObserverMock;
+
+ return {
+ observe: mockObserve,
+ disconnect: mockDisconnect,
+ unobserve: mockUnobserve,
+ };
+};
+
export class SafeElementWrapper {
constructor(private element: T) {}
diff --git a/src/test/time_input_test.test.tsx b/src/test/time_input_test.test.tsx
index bc332753ec..ef4bf1d7bc 100644
--- a/src/test/time_input_test.test.tsx
+++ b/src/test/time_input_test.test.tsx
@@ -5,9 +5,13 @@ import DatePicker from "../index";
import InputTimeComponent from "../input_time";
import CustomTimeInput from "./helper_components/custom_time_input";
-import { safeQuerySelector } from "./test_utils";
+import { safeQuerySelector, setupMockResizeObserver } from "./test_utils";
describe("timeInput", () => {
+ beforeEach(() => {
+ setupMockResizeObserver();
+ });
+
afterEach(() => {
jest.resetAllMocks();
});
diff --git a/src/test/timepicker_test.test.tsx b/src/test/timepicker_test.test.tsx
index 3ed6d043e5..b4c8010f44 100644
--- a/src/test/timepicker_test.test.tsx
+++ b/src/test/timepicker_test.test.tsx
@@ -6,9 +6,11 @@ import DatePicker from "../index";
import {
getKey,
+ getResizeObserverCallback,
SafeElementWrapper,
safeQuerySelector,
safeQuerySelectorAll,
+ setupMockResizeObserver,
} from "./test_utils";
const MIN_TIME_LI_LEN = 2;
@@ -19,10 +21,65 @@ describe("TimePicker", () => {
let onChangeMoment: Date | undefined;
let instance: DatePicker | null = null;
+ let mockObserve: jest.Mock, mockDisconnect: jest.Mock;
+
+ beforeAll(() => {
+ const { observe, disconnect } = setupMockResizeObserver();
+ mockObserve = observe;
+ mockDisconnect = disconnect;
+ });
+
beforeEach(() => {
div = document.createElement("div");
});
+ describe("Re-adjust height on Calendar Height Change", () => {
+ beforeEach(() => {
+ mockObserve.mockReset();
+ mockDisconnect.mockReset();
+ });
+
+ it("calls observe on mount", async () => {
+ render(
+ ,
+ );
+ await waitFor(() => {
+ expect(mockObserve).toHaveBeenCalledTimes(1);
+
+ const resizeObserverCallback = getResizeObserverCallback();
+ const mockObserveElement = mockObserve.mock.calls[0][0];
+ expect(typeof resizeObserverCallback).toBe("function");
+
+ if (resizeObserverCallback) {
+ resizeObserverCallback([], mockObserveElement);
+ }
+ });
+ });
+
+ it("calls disconnect on unmount", async () => {
+ const component = render(
+ ,
+ );
+
+ component.unmount();
+ await waitFor(() => {
+ expect(mockDisconnect).toHaveBeenCalledTimes(1);
+ const resizeObserverCallback = getResizeObserverCallback();
+ expect(resizeObserverCallback).toBe(null);
+ });
+ });
+ });
+
it("should update on input time change", () => {
renderDatePicker("February 28, 2018 4:43 PM");
expect(getInputString()).toBe("February 28, 2018 4:43 PM");
diff --git a/src/time.tsx b/src/time.tsx
index 4e1bb3d513..c6ed61e4b1 100644
--- a/src/time.tsx
+++ b/src/time.tsx
@@ -62,6 +62,7 @@ export default class Time extends Component {
);
};
+ private resizeObserver?: ResizeObserver;
state: TimeState = {
height: null,
};
@@ -69,11 +70,11 @@ export default class Time extends Component {
componentDidMount(): void {
// code to ensure selected time will always be in focus within time window when it first appears
this.scrollToTheSelectedTime();
- if (this.props.monthRef && this.header) {
- this.setState({
- height: this.props.monthRef.clientHeight - this.header.clientHeight,
- });
- }
+ this.observeDatePickerHeightChanges();
+ }
+
+ componentWillUnmount(): void {
+ this.resizeObserver?.disconnect();
}
private header?: HTMLDivElement;
@@ -82,6 +83,27 @@ export default class Time extends Component {
private centerLi?: HTMLLIElement;
+ private observeDatePickerHeightChanges(): void {
+ const { monthRef } = this.props;
+ this.updateContainerHeight();
+
+ if (monthRef) {
+ this.resizeObserver = new ResizeObserver(() => {
+ this.updateContainerHeight();
+ });
+
+ this.resizeObserver.observe(monthRef);
+ }
+ }
+
+ private updateContainerHeight(): void {
+ if (this.props.monthRef && this.header) {
+ this.setState({
+ height: this.props.monthRef.clientHeight - this.header.clientHeight,
+ });
+ }
+ }
+
scrollToTheSelectedTime = (): void => {
requestAnimationFrame((): void => {
if (!this.list) return;