Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/test/calendar_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
SafeElementWrapper,
safeQuerySelector,
safeQuerySelectorAll,
setupMockResizeObserver,
} from "./test_utils";

import type { ReactDatePickerCustomHeaderProps } from "../calendar";
Expand Down Expand Up @@ -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();
Expand Down
10 changes: 9 additions & 1 deletion src/test/datepicker_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -83,6 +87,10 @@ const showDocument = (calendarInput: HTMLElement) => {
};

describe("DatePicker", () => {
beforeEach(() => {
setupMockResizeObserver();
});

afterEach(() => {
jest.resetAllMocks();
});
Expand Down
5 changes: 5 additions & 0 deletions src/test/exclude_time_period_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
5 changes: 5 additions & 0 deletions src/test/exclude_times_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
6 changes: 5 additions & 1 deletion src/test/min_time_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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(<DatePickerWithState />);

Expand Down
6 changes: 5 additions & 1 deletion src/test/show_time_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(<DatePicker showTimeSelect open />);
const timeComponent = container.querySelector(
Expand Down
31 changes: 31 additions & 0 deletions src/test/test_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,37 @@ export const safeQuerySelectorAll = <T extends HTMLElement = HTMLElement>(
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<T extends HTMLElement> {
constructor(private element: T) {}

Expand Down
6 changes: 5 additions & 1 deletion src/test/time_input_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
Expand Down
57 changes: 57 additions & 0 deletions src/test/timepicker_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import DatePicker from "../index";

import {
getKey,
getResizeObserverCallback,
SafeElementWrapper,
safeQuerySelector,
safeQuerySelectorAll,
setupMockResizeObserver,
} from "./test_utils";

const MIN_TIME_LI_LEN = 2;
Expand All @@ -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(
<DatePicker
inline
selected={new Date()}
showTimeSelect
timeIntervals={15}
/>,
);
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(
<DatePicker
inline
selected={new Date()}
showTimeSelect
timeIntervals={15}
/>,
);

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");
Expand Down
32 changes: 27 additions & 5 deletions src/time.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,19 @@ export default class Time extends Component<TimeProps, TimeState> {
);
};

private resizeObserver?: ResizeObserver;
state: TimeState = {
height: null,
};

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;
Expand All @@ -82,6 +83,27 @@ export default class Time extends Component<TimeProps, TimeState> {

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;
Expand Down
Loading