From 4854e4b8368b6471641fb5c2c30a5dc2526f8a18 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 21 Mar 2023 15:41:24 -0500 Subject: [PATCH 1/4] Prevent future date selection in jump to date --- .../views/messages/JumpToDatePicker.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/components/views/messages/JumpToDatePicker.tsx b/src/components/views/messages/JumpToDatePicker.tsx index fa132358095..a8036d77b99 100644 --- a/src/components/views/messages/JumpToDatePicker.tsx +++ b/src/components/views/messages/JumpToDatePicker.tsx @@ -25,14 +25,19 @@ interface IProps { onDatePicked: (dateString: string) => void; } -const JumpToDatePicker: React.FC = ({ ts, onDatePicked }: IProps) => { - const date = new Date(ts); +function formatDateForInput(date: Date): string { const year = date.getFullYear(); const month = `${date.getMonth() + 1}`.padStart(2, "0"); const day = `${date.getDate()}`.padStart(2, "0"); - const dateDefaultValue = `${year}-${month}-${day}`; + const dateInputValue = `${year}-${month}-${day}`; + return dateInputValue; +} + +const JumpToDatePicker: React.FC = ({ ts, onDatePicked }: IProps) => { + const date = new Date(ts); + const dateInputDefaultValue = formatDateForInput(date); - const [dateValue, setDateValue] = useState(dateDefaultValue); + const [dateValue, setDateValue] = useState(dateInputDefaultValue); const [onFocus, isActive, ref] = useRovingTabIndex(); const onDateValueInput = (ev: React.ChangeEvent): void => setDateValue(ev.target.value); @@ -49,6 +54,9 @@ const JumpToDatePicker: React.FC = ({ ts, onDatePicked }: IProps) => { type="date" onInput={onDateValueInput} value={dateValue} + // Prevent people from selecting a day in the future (there won't be any + // events there anyway). + max={formatDateForInput(new Date())} className="mx_JumpToDatePicker_datePicker" label={_t("Pick a date to jump to")} onFocus={onFocus} From 4c8d1b3a4d45fea46c86d6799ee9f34f36934544 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 21 Mar 2023 16:01:43 -0500 Subject: [PATCH 2/4] Add tests --- src/DateUtils.ts | 15 +++++++++++++++ .../views/messages/JumpToDatePicker.tsx | 9 +-------- test/utils/DateUtils-test.ts | 10 ++++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/DateUtils.ts b/src/DateUtils.ts index a6a8caa9468..9116a8047d3 100644 --- a/src/DateUtils.ts +++ b/src/DateUtils.ts @@ -102,6 +102,21 @@ export function formatFullDate(date: Date, showTwelveHour = false, showSeconds = }); } +/** + * Formats dates to be compatible with attributes of a ``. Dates + * should be formatted like "2020-06-23" (formatted according to ISO8601) + * + * @param date The date to format. + * @returns The date string in ISO8601 format ready to be used with an `` + */ +export function formatDateForInput(date: Date): string { + const year = `${date.getFullYear()}`.padStart(4, "0"); + const month = `${date.getMonth() + 1}`.padStart(2, "0"); + const day = `${date.getDate()}`.padStart(2, "0"); + const dateInputValue = `${year}-${month}-${day}`; + return dateInputValue; +} + export function formatFullTime(date: Date, showTwelveHour = false): string { if (showTwelveHour) { return twelveHourTime(date, true); diff --git a/src/components/views/messages/JumpToDatePicker.tsx b/src/components/views/messages/JumpToDatePicker.tsx index a8036d77b99..8bfcebb3ae2 100644 --- a/src/components/views/messages/JumpToDatePicker.tsx +++ b/src/components/views/messages/JumpToDatePicker.tsx @@ -19,20 +19,13 @@ import React, { useState, FormEvent } from "react"; import { _t } from "../../../languageHandler"; import Field from "../elements/Field"; import { RovingAccessibleButton, useRovingTabIndex } from "../../../accessibility/RovingTabIndex"; +import { formatDateForInput } from "../../../DateUtils"; interface IProps { ts: number; onDatePicked: (dateString: string) => void; } -function formatDateForInput(date: Date): string { - const year = date.getFullYear(); - const month = `${date.getMonth() + 1}`.padStart(2, "0"); - const day = `${date.getDate()}`.padStart(2, "0"); - const dateInputValue = `${year}-${month}-${day}`; - return dateInputValue; -} - const JumpToDatePicker: React.FC = ({ ts, onDatePicked }: IProps) => { const date = new Date(ts); const dateInputDefaultValue = formatDateForInput(date); diff --git a/test/utils/DateUtils-test.ts b/test/utils/DateUtils-test.ts index aa8cf2d9941..e76b218ebcc 100644 --- a/test/utils/DateUtils-test.ts +++ b/test/utils/DateUtils-test.ts @@ -19,6 +19,7 @@ import { formatRelativeTime, formatDuration, formatFullDateNoDayISO, + formatDateForInput, formatTimeLeft, formatPreciseDuration, formatLocalDateShort, @@ -126,6 +127,15 @@ describe("formatFullDateNoDayISO", () => { }); }); +describe("formatDateForInput", () => { + it.each([["1993-11-01"], ["1066-10-14"], ["0571-04-22"], ["0062-02-05"], ["99999-09-09"]])( + "should format %s", + (dateString: string) => { + expect(formatDateForInput(new Date(dateString))).toBe(dateString); + }, + ); +}); + describe("formatTimeLeft", () => { it.each([ [0, "0s left"], From c24884248f9bd4be3eb6dc3d26729c4ffc7ed14b Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 21 Mar 2023 16:06:46 -0500 Subject: [PATCH 3/4] Remove extra digit test which requires a + --- test/utils/DateUtils-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils/DateUtils-test.ts b/test/utils/DateUtils-test.ts index e76b218ebcc..9b1fe4d8707 100644 --- a/test/utils/DateUtils-test.ts +++ b/test/utils/DateUtils-test.ts @@ -128,7 +128,7 @@ describe("formatFullDateNoDayISO", () => { }); describe("formatDateForInput", () => { - it.each([["1993-11-01"], ["1066-10-14"], ["0571-04-22"], ["0062-02-05"], ["99999-09-09"]])( + it.each([["1993-11-01"], ["1066-10-14"], ["0571-04-22"], ["0062-02-05"]])( "should format %s", (dateString: string) => { expect(formatDateForInput(new Date(dateString))).toBe(dateString); From 3dd93fa5978324fc688d8e80c93043f97c6fcf75 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 21 Mar 2023 18:46:36 -0500 Subject: [PATCH 4/4] Add snapshot test --- .../views/messages/JumpToDatePicker-test.tsx | 41 +++++++++++++++++++ .../JumpToDatePicker-test.tsx.snap | 41 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 test/components/views/messages/JumpToDatePicker-test.tsx create mode 100644 test/components/views/messages/__snapshots__/JumpToDatePicker-test.tsx.snap diff --git a/test/components/views/messages/JumpToDatePicker-test.tsx b/test/components/views/messages/JumpToDatePicker-test.tsx new file mode 100644 index 00000000000..c75c6d8ffd1 --- /dev/null +++ b/test/components/views/messages/JumpToDatePicker-test.tsx @@ -0,0 +1,41 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from "react"; +import { render } from "@testing-library/react"; + +import JumpToDatePicker from "../../../../src/components/views/messages/JumpToDatePicker"; + +describe("JumpToDatePicker", () => { + const nowDate = new Date("2021-12-17T08:09:00.000Z"); + beforeEach(() => { + // Set a stable fake time here so the test is always consistent + jest.useFakeTimers(); + jest.setSystemTime(nowDate.getTime()); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + it("renders the date picker correctly", () => { + const { asFragment } = render( + {}} />, + ); + + expect(asFragment()).toMatchSnapshot(); + }); +}); diff --git a/test/components/views/messages/__snapshots__/JumpToDatePicker-test.tsx.snap b/test/components/views/messages/__snapshots__/JumpToDatePicker-test.tsx.snap new file mode 100644 index 00000000000..02d5d3a3372 --- /dev/null +++ b/test/components/views/messages/__snapshots__/JumpToDatePicker-test.tsx.snap @@ -0,0 +1,41 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`JumpToDatePicker renders the date picker correctly 1`] = ` + +
+ + Jump to date + +
+ + +
+ +
+
+`;