Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #4290 and #4289: Time component scroll issue #4296

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
24 changes: 16 additions & 8 deletions src/time.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,29 @@ export default class Time extends React.Component {

componentDidMount() {
// code to ensure selected time will always be in focus within time window when it first appears
this.list.scrollTop =
this.centerLi &&
Time.calcCenterPosition(
this.props.monthRef
? this.props.monthRef.clientHeight - this.header.clientHeight
: this.list.clientHeight,
this.centerLi,
);
this.scrollToTheSelectedTime();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for extracting this logic

if (this.props.monthRef && this.header) {
this.setState({
height: this.props.monthRef.clientHeight - this.header.clientHeight,
});
}
}

scrollToTheSelectedTime = () => {
requestAnimationFrame(() => {
if (!this.list) return;

this.list.scrollTop =
this.centerLi &&
Time.calcCenterPosition(
this.props.monthRef
? this.props.monthRef.clientHeight - this.header.clientHeight
: this.list.clientHeight,
this.centerLi,
);
});
};

handleClick = (time) => {
if (
((this.props.minTime || this.props.maxTime) &&
Expand Down
71 changes: 45 additions & 26 deletions test/time_format_test.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { mount } from "enzyme";
import TimeComponent from "../src/time";
import * as utils from "../src/date_utils";
import ptBR from "date-fns/locale/pt-BR";
import { waitFor } from "@testing-library/react";

describe("TimeComponent", () => {
utils.registerLocale("pt-BR", ptBR);
Expand Down Expand Up @@ -36,14 +37,18 @@ describe("TimeComponent", () => {
expect(timeListItem.at(0).text()).toBe("00:00");
});

it("should format the time based on the default locale (en-US)", () => {
it("should format the time based on the default locale (en-US)", async () => {
mount(<TimeComponent format="p" />);
expect(spy.mock.calls[0][1].innerHTML).toBe("1:00 PM");
await waitFor(() => {
expect(spy.mock.calls[0][1].innerHTML).toBe("1:00 PM");
});
});

it("should format the time based on the pt-BR locale", () => {
it("should format the time based on the pt-BR locale", async () => {
mount(<TimeComponent format="p" locale="pt-BR" />);
expect(spy.mock.calls[0][1].innerHTML).toBe("13:00");
await waitFor(() => {
expect(spy.mock.calls[0][1].innerHTML).toBe("13:00");
});
});
});

Expand All @@ -53,45 +58,55 @@ describe("TimeComponent", () => {
spy = jest.spyOn(TimeComponent, "calcCenterPosition");
});

it("should call calcCenterPosition once", () => {
it("should call calcCenterPosition once", async () => {
mount(<TimeComponent format="HH:mm" />);
expect(spy).toHaveBeenCalled();
await waitFor(() => {
expect(spy).toHaveBeenCalled();
});
});

it("should call calcCenterPosition with centerLi ref, closest to the current time", () => {
it("should call calcCenterPosition with centerLi ref, closest to the current time", async () => {
mount(<TimeComponent format="HH:mm" />);
expect(spy.mock.calls[0][1].innerHTML).toBe("13:00");
await waitFor(() => {
expect(spy.mock.calls[0][1].innerHTML).toBe("13:00");
});
});

it("with five minute time interval, should call calcCenterPosition with centerLi ref, closest to the current time", () => {
it("with five minute time interval, should call calcCenterPosition with centerLi ref, closest to the current time", async () => {
mount(<TimeComponent format="HH:mm" intervals={5} />);
expect(spy.mock.calls[0][1].innerHTML).toBe("13:25");
await waitFor(() => {
expect(spy.mock.calls[0][1].innerHTML).toBe("13:25");
});
});

it("should call calcCenterPosition with centerLi ref, closest to the selected time", () => {
it("should call calcCenterPosition with centerLi ref, closest to the selected time", async () => {
mount(
<TimeComponent
format="HH:mm"
selected={new Date("1990-06-14 08:11")}
openToDate={new Date("1990-06-14 09:11")}
/>,
);
expect(spy.mock.calls[0][1].innerHTML).toBe("08:00");
await waitFor(() => {
expect(spy.mock.calls[0][1].innerHTML).toBe("08:00");
});
});

it("should call calcCenterPosition with centerLi ref, which is selected", () => {
it("should call calcCenterPosition with centerLi ref, which is selected", async () => {
mount(
<TimeComponent
format="HH:mm"
selected={new Date("1990-06-14 08:00")}
openToDate={new Date("1990-06-14 09:00")}
/>,
);
expect(
spy.mock.calls[0][1].classList.contains(
"react-datepicker__time-list-item--selected",
),
).toBe(true);
await waitFor(() => {
expect(
spy.mock.calls[0][1].classList.contains(
"react-datepicker__time-list-item--selected",
),
).toBe(true);
});
});

it("should add the aria-selected property to the selected item", () => {
Expand Down Expand Up @@ -172,28 +187,32 @@ describe("TimeComponent", () => {
).toBe(0);
});

it("when no selected time, should call calcCenterPosition with centerLi ref, closest to the opened time", () => {
it("when no selected time, should call calcCenterPosition with centerLi ref, closest to the opened time", async () => {
mount(
<TimeComponent
format="HH:mm"
openToDate={new Date("1990-06-14 09:11")}
/>,
);
expect(spy.mock.calls[0][1].innerHTML).toBe("09:00");
await waitFor(() => {
expect(spy.mock.calls[0][1].innerHTML).toBe("09:00");
});
});

it("when no selected time, should call calcCenterPosition with centerLi ref, and no time should be selected", () => {
it("when no selected time, should call calcCenterPosition with centerLi ref, and no time should be selected", async () => {
mount(
<TimeComponent
format="HH:mm"
openToDate={new Date("1990-06-14 09:00")}
/>,
);
expect(
spy.mock.calls[0][1].classList.contains(
"react-datepicker__time-list-item--selected",
),
).toBe(false);
await waitFor(() => {
expect(
spy.mock.calls[0][1].classList.contains(
"react-datepicker__time-list-item--selected",
),
).toBe(false);
});
});

it("should calculate scroll for the first item of 4 (even) items list", () => {
Expand Down
Loading