From bcd521500060d9dd6ad275e6644fd482589f31dd Mon Sep 17 00:00:00 2001 From: rodgobbi Date: Sun, 29 Dec 2024 01:03:56 +0100 Subject: [PATCH] feat: remove `startMonth` and `endMonth` default constraints when `dropdown-months` is set as caption layout (#2648) * examples: add DropdownMonths * refactor: getYearOptions test * feat: remove default startMonth and endMonth for dropdown-months Remove default values when captionLayout equal to dropdown-months. * refactor: Dropdown.test.tsx * chore(test): add DropdownMonths.test.tsx --------- Co-authored-by: Giampaolo Bellavite --- examples/Dropdown.test.tsx | 5 - examples/DropdownMonths.test.tsx | 26 ++ examples/DropdownMonths.tsx | 12 + examples/index.ts | 1 + src/helpers/getMonthOptions.test.ts | 374 ++++++++++++++++------------ src/helpers/getMonthOptions.ts | 3 - src/helpers/getNavMonth.test.ts | 160 +++++++++++- src/helpers/getNavMonth.ts | 8 +- src/helpers/getYearOptions.test.ts | 2 +- 9 files changed, 407 insertions(+), 184 deletions(-) create mode 100644 examples/DropdownMonths.test.tsx create mode 100644 examples/DropdownMonths.tsx diff --git a/examples/Dropdown.test.tsx b/examples/Dropdown.test.tsx index 30beda3ce..53dfc132e 100644 --- a/examples/Dropdown.test.tsx +++ b/examples/Dropdown.test.tsx @@ -6,11 +6,6 @@ import { user } from "@/test/user"; import { Dropdown } from "./Dropdown"; -const today = new Date(2015, 6, 1); - -beforeAll(() => jest.setSystemTime(today)); -afterAll(() => jest.useRealTimers()); - beforeEach(() => { render(); }); diff --git a/examples/DropdownMonths.test.tsx b/examples/DropdownMonths.test.tsx new file mode 100644 index 000000000..1628db505 --- /dev/null +++ b/examples/DropdownMonths.test.tsx @@ -0,0 +1,26 @@ +import React from "react"; + +import { grid, monthDropdown, nextButton } from "@/test/elements"; +import { render } from "@/test/render"; +import { user } from "@/test/user"; + +import { DropdownMonths } from "./DropdownMonths"; + +const today = new Date(2015, 6, 1); + +beforeAll(() => jest.setSystemTime(today)); +afterAll(() => jest.useRealTimers()); + +beforeEach(() => { + render(); +}); + +test("should display the month dropdown", () => { + expect(monthDropdown()).toBeInTheDocument(); +}); + +test("should allow all months", async () => { + expect(grid()).toHaveAccessibleName(`December 2015`); + await user.click(nextButton()); + expect(grid()).toHaveAccessibleName(`January 2016`); +}); diff --git a/examples/DropdownMonths.tsx b/examples/DropdownMonths.tsx new file mode 100644 index 000000000..89cc43922 --- /dev/null +++ b/examples/DropdownMonths.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +import { DayPicker } from "react-day-picker"; + +export function DropdownMonths() { + const decemberDate = new Date(); + decemberDate.setMonth(11); + + return ( + + ); +} diff --git a/examples/index.ts b/examples/index.ts index 82db54877..0e1910563 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -16,6 +16,7 @@ export * from "./Dialog"; export * from "./Disabled"; export * from "./DisableNavigation"; export * from "./Dropdown"; +export * from "./DropdownMonths"; export * from "./DropdownMultipleMonths"; export * from "./Fixedweeks"; export * from "./FocusRecursive"; diff --git a/src/helpers/getMonthOptions.test.ts b/src/helpers/getMonthOptions.test.ts index 1fedafa45..49e00245d 100644 --- a/src/helpers/getMonthOptions.test.ts +++ b/src/helpers/getMonthOptions.test.ts @@ -3,170 +3,224 @@ import * as formatters from "../formatters/index.js"; import { getMonthOptions } from "./getMonthOptions"; -test("return correct dropdown options", () => { - const displayMonth = new Date(2022, 0, 1); - const startMonth = new Date(2022, 0, 1); - const endMonth = new Date(2022, 11, 31); - const result = getMonthOptions( - displayMonth, - startMonth, - endMonth, - formatters, - defaultDateLib - ); - - expect(result).toEqual([ - { value: 0, label: "January", disabled: false }, - { value: 1, label: "February", disabled: false }, - { value: 2, label: "March", disabled: false }, - { value: 3, label: "April", disabled: false }, - { value: 4, label: "May", disabled: false }, - { value: 5, label: "June", disabled: false }, - { value: 6, label: "July", disabled: false }, - { value: 7, label: "August", disabled: false }, - { value: 8, label: "September", disabled: false }, - { value: 9, label: "October", disabled: false }, - { value: 10, label: "November", disabled: false }, - { value: 11, label: "December", disabled: false } - ]); -}); +describe("return correct dropdown options", () => { + test("when navStart and navEnd are defined", () => { + const displayMonth = new Date(2022, 0, 1); + const startMonth = new Date(2022, 0, 1); + const endMonth = new Date(2022, 11, 31); + const result = getMonthOptions( + displayMonth, + startMonth, + endMonth, + formatters, + defaultDateLib + ); -test("return correct dropdown options when less than 12 months", () => { - const displayMonth = new Date(2024, 9); - const startMonth = new Date(2024, 9); - const endMonth = new Date(2025, 5); - const result = getMonthOptions( - displayMonth, - startMonth, - endMonth, - formatters, - defaultDateLib - ); - - expect(result).toEqual([ - { value: 0, label: "January", disabled: true }, - { value: 1, label: "February", disabled: true }, - { value: 2, label: "March", disabled: true }, - { value: 3, label: "April", disabled: true }, - { value: 4, label: "May", disabled: true }, - { value: 5, label: "June", disabled: true }, - { value: 6, label: "July", disabled: true }, - { value: 7, label: "August", disabled: true }, - { value: 8, label: "September", disabled: true }, - { value: 9, label: "October", disabled: false }, - { value: 10, label: "November", disabled: false }, - { value: 11, label: "December", disabled: false } - ]); -}); + expect(result).toEqual([ + { value: 0, label: "January", disabled: false }, + { value: 1, label: "February", disabled: false }, + { value: 2, label: "March", disabled: false }, + { value: 3, label: "April", disabled: false }, + { value: 4, label: "May", disabled: false }, + { value: 5, label: "June", disabled: false }, + { value: 6, label: "July", disabled: false }, + { value: 7, label: "August", disabled: false }, + { value: 8, label: "September", disabled: false }, + { value: 9, label: "October", disabled: false }, + { value: 10, label: "November", disabled: false }, + { value: 11, label: "December", disabled: false } + ]); + }); -test("return undefined when navStart is undefined", () => { - const displayMonth = new Date(2022, 0, 1); - const endMonth = new Date(2022, 11, 31); - const result = getMonthOptions( - displayMonth, - undefined, - endMonth, - formatters, - defaultDateLib - ); - - expect(result).toBeUndefined(); -}); + test("when navStart and navEnd are undefined", () => { + const displayMonth = new Date(2022, 0, 1); + const result = getMonthOptions( + displayMonth, + undefined, + undefined, + formatters, + defaultDateLib + ); -test("return undefined when navEnd is undefined", () => { - const displayMonth = new Date(2022, 0, 1); - const startMonth = new Date(2022, 0, 1); - const result = getMonthOptions( - displayMonth, - startMonth, - undefined, - formatters, - defaultDateLib - ); - - expect(result).toBeUndefined(); -}); + expect(result).toEqual([ + { value: 0, label: "January", disabled: false }, + { value: 1, label: "February", disabled: false }, + { value: 2, label: "March", disabled: false }, + { value: 3, label: "April", disabled: false }, + { value: 4, label: "May", disabled: false }, + { value: 5, label: "June", disabled: false }, + { value: 6, label: "July", disabled: false }, + { value: 7, label: "August", disabled: false }, + { value: 8, label: "September", disabled: false }, + { value: 9, label: "October", disabled: false }, + { value: 10, label: "November", disabled: false }, + { value: 11, label: "December", disabled: false } + ]); + }); -test("return correct dropdown options when navStart is after displayMonth", () => { - const displayMonth = new Date(2022, 0, 1); - const startMonth = new Date(2022, 2, 1); - const endMonth = new Date(2022, 11, 31); - const result = getMonthOptions( - displayMonth, - startMonth, - endMonth, - formatters, - defaultDateLib - ); - - expect(result).toEqual([ - { value: 0, label: "January", disabled: true }, - { value: 1, label: "February", disabled: true }, - { value: 2, label: "March", disabled: false }, - { value: 3, label: "April", disabled: false }, - { value: 4, label: "May", disabled: false }, - { value: 5, label: "June", disabled: false }, - { value: 6, label: "July", disabled: false }, - { value: 7, label: "August", disabled: false }, - { value: 8, label: "September", disabled: false }, - { value: 9, label: "October", disabled: false }, - { value: 10, label: "November", disabled: false }, - { value: 11, label: "December", disabled: false } - ]); -}); + test("when less than 12 months", () => { + const displayMonth = new Date(2024, 9); + const startMonth = new Date(2024, 9); + const endMonth = new Date(2025, 5); + const result = getMonthOptions( + displayMonth, + startMonth, + endMonth, + formatters, + defaultDateLib + ); -test("return correct dropdown options when navEnd is before displayMonth", () => { - const displayMonth = new Date(2022, 6, 1); - const startMonth = new Date(2022, 0, 1); - const endMonth = new Date(2022, 5, 30); - const result = getMonthOptions( - displayMonth, - startMonth, - endMonth, - formatters, - defaultDateLib - ); - - expect(result).toEqual([ - { value: 0, label: "January", disabled: false }, - { value: 1, label: "February", disabled: false }, - { value: 2, label: "March", disabled: false }, - { value: 3, label: "April", disabled: false }, - { value: 4, label: "May", disabled: false }, - { value: 5, label: "June", disabled: false }, - { value: 6, label: "July", disabled: true }, - { value: 7, label: "August", disabled: true }, - { value: 8, label: "September", disabled: true }, - { value: 9, label: "October", disabled: true }, - { value: 10, label: "November", disabled: true }, - { value: 11, label: "December", disabled: true } - ]); -}); + expect(result).toEqual([ + { value: 0, label: "January", disabled: true }, + { value: 1, label: "February", disabled: true }, + { value: 2, label: "March", disabled: true }, + { value: 3, label: "April", disabled: true }, + { value: 4, label: "May", disabled: true }, + { value: 5, label: "June", disabled: true }, + { value: 6, label: "July", disabled: true }, + { value: 7, label: "August", disabled: true }, + { value: 8, label: "September", disabled: true }, + { value: 9, label: "October", disabled: false }, + { value: 10, label: "November", disabled: false }, + { value: 11, label: "December", disabled: false } + ]); + }); + + test("return undefined when navStart is undefined", () => { + const displayMonth = new Date(2022, 0, 1); + const endMonth = new Date(2022, 6, 31); + const result = getMonthOptions( + displayMonth, + undefined, + endMonth, + formatters, + defaultDateLib + ); + + expect(result).toEqual([ + { value: 0, label: "January", disabled: false }, + { value: 1, label: "February", disabled: false }, + { value: 2, label: "March", disabled: false }, + { value: 3, label: "April", disabled: false }, + { value: 4, label: "May", disabled: false }, + { value: 5, label: "June", disabled: false }, + { value: 6, label: "July", disabled: false }, + { value: 7, label: "August", disabled: true }, + { value: 8, label: "September", disabled: true }, + { value: 9, label: "October", disabled: true }, + { value: 10, label: "November", disabled: true }, + { value: 11, label: "December", disabled: true } + ]); + }); + + test("return undefined when navEnd is undefined", () => { + const displayMonth = new Date(2022, 6, 1); + const startMonth = new Date(2022, 3, 1); + const result = getMonthOptions( + displayMonth, + startMonth, + undefined, + formatters, + defaultDateLib + ); + + expect(result).toEqual([ + { value: 0, label: "January", disabled: true }, + { value: 1, label: "February", disabled: true }, + { value: 2, label: "March", disabled: true }, + { value: 3, label: "April", disabled: false }, + { value: 4, label: "May", disabled: false }, + { value: 5, label: "June", disabled: false }, + { value: 6, label: "July", disabled: false }, + { value: 7, label: "August", disabled: false }, + { value: 8, label: "September", disabled: false }, + { value: 9, label: "October", disabled: false }, + { value: 10, label: "November", disabled: false }, + { value: 11, label: "December", disabled: false } + ]); + }); + + test("when navStart is after displayMonth", () => { + const displayMonth = new Date(2022, 0, 1); + const startMonth = new Date(2022, 2, 1); + const endMonth = new Date(2022, 11, 31); + const result = getMonthOptions( + displayMonth, + startMonth, + endMonth, + formatters, + defaultDateLib + ); + + expect(result).toEqual([ + { value: 0, label: "January", disabled: true }, + { value: 1, label: "February", disabled: true }, + { value: 2, label: "March", disabled: false }, + { value: 3, label: "April", disabled: false }, + { value: 4, label: "May", disabled: false }, + { value: 5, label: "June", disabled: false }, + { value: 6, label: "July", disabled: false }, + { value: 7, label: "August", disabled: false }, + { value: 8, label: "September", disabled: false }, + { value: 9, label: "October", disabled: false }, + { value: 10, label: "November", disabled: false }, + { value: 11, label: "December", disabled: false } + ]); + }); + + test("when navEnd is before displayMonth", () => { + const displayMonth = new Date(2022, 6, 1); + const startMonth = new Date(2022, 0, 1); + const endMonth = new Date(2022, 5, 30); + const result = getMonthOptions( + displayMonth, + startMonth, + endMonth, + formatters, + defaultDateLib + ); + + expect(result).toEqual([ + { value: 0, label: "January", disabled: false }, + { value: 1, label: "February", disabled: false }, + { value: 2, label: "March", disabled: false }, + { value: 3, label: "April", disabled: false }, + { value: 4, label: "May", disabled: false }, + { value: 5, label: "June", disabled: false }, + { value: 6, label: "July", disabled: true }, + { value: 7, label: "August", disabled: true }, + { value: 8, label: "September", disabled: true }, + { value: 9, label: "October", disabled: true }, + { value: 10, label: "November", disabled: true }, + { value: 11, label: "December", disabled: true } + ]); + }); + + test("when navStart and navEnd are within the same year", () => { + const displayMonth = new Date(2022, 0, 1); + const startMonth = new Date(2022, 2, 1); + const endMonth = new Date(2022, 8, 30); + const result = getMonthOptions( + displayMonth, + startMonth, + endMonth, + formatters, + defaultDateLib + ); -test("return correct dropdown options when navStart and navEnd are within the same year", () => { - const displayMonth = new Date(2022, 0, 1); - const startMonth = new Date(2022, 2, 1); - const endMonth = new Date(2022, 8, 30); - const result = getMonthOptions( - displayMonth, - startMonth, - endMonth, - formatters, - defaultDateLib - ); - - expect(result).toEqual([ - { value: 0, label: "January", disabled: true }, - { value: 1, label: "February", disabled: true }, - { value: 2, label: "March", disabled: false }, - { value: 3, label: "April", disabled: false }, - { value: 4, label: "May", disabled: false }, - { value: 5, label: "June", disabled: false }, - { value: 6, label: "July", disabled: false }, - { value: 7, label: "August", disabled: false }, - { value: 8, label: "September", disabled: false }, - { value: 9, label: "October", disabled: true }, - { value: 10, label: "November", disabled: true }, - { value: 11, label: "December", disabled: true } - ]); + expect(result).toEqual([ + { value: 0, label: "January", disabled: true }, + { value: 1, label: "February", disabled: true }, + { value: 2, label: "March", disabled: false }, + { value: 3, label: "April", disabled: false }, + { value: 4, label: "May", disabled: false }, + { value: 5, label: "June", disabled: false }, + { value: 6, label: "July", disabled: false }, + { value: 7, label: "August", disabled: false }, + { value: 8, label: "September", disabled: false }, + { value: 9, label: "October", disabled: true }, + { value: 10, label: "November", disabled: true }, + { value: 11, label: "December", disabled: true } + ]); + }); }); diff --git a/src/helpers/getMonthOptions.ts b/src/helpers/getMonthOptions.ts index 80ee7ba9d..1d132324a 100644 --- a/src/helpers/getMonthOptions.ts +++ b/src/helpers/getMonthOptions.ts @@ -10,9 +10,6 @@ export function getMonthOptions( formatters: Pick, dateLib: DateLib ): DropdownOption[] | undefined { - if (!navStart) return undefined; - if (!navEnd) return undefined; - // const year = dateLib.getYear(displayMonth); const { startOfMonth, startOfYear, diff --git a/src/helpers/getNavMonth.test.ts b/src/helpers/getNavMonth.test.ts index c086a156b..118b8b303 100644 --- a/src/helpers/getNavMonth.test.ts +++ b/src/helpers/getNavMonth.test.ts @@ -56,27 +56,162 @@ describe('when "toYear" is passed in', () => { }); }); -describe('when "captionLayout" is dropdown', () => { +describe.each([["dropdown" as const], ["dropdown-years" as const]])( + 'when "captionLayout" is "%s"', + (captionLayout) => { + const today = new Date(2024, 4, 3); + const [navStartMonth, navEndMonth] = getNavMonths( + { + captionLayout, + today + }, + defaultDateLib + ); + test('"startMonth" should be 100 years ago', () => { + expect(navStartMonth).toEqual(new Date(1924, 0, 1)); + }); + test('"endMonth" should be the end of this year', () => { + expect(navEndMonth).toEqual(new Date(2024, 11, 31)); + }); + + describe('when "startMonth" is set', () => { + const today = new Date(2024, 4, 3); + const startMonth = new Date(2021, 4, 3); + const [navStartMonth, navEndMonth] = getNavMonths( + { + captionLayout, + startMonth, + today + }, + defaultDateLib + ); + test('"startMonth" should be the start of that month', () => { + expect(navStartMonth).toEqual(new Date(2021, 4, 1)); + }); + test('"endMonth" should be the end of this year', () => { + expect(navEndMonth).toEqual(new Date(2024, 11, 31)); + }); + }); + + describe('when "endMonth" is set', () => { + const today = new Date(2021, 4, 3); + const endMonth = new Date(2022, 4, 3); + const [navStartMonth, navEndMonth] = getNavMonths( + { + captionLayout, + endMonth, + today + }, + defaultDateLib + ); + test('"startMonth" should be 100 years ago', () => { + expect(navStartMonth).toEqual(new Date(1921, 0, 1)); + }); + test('"endMonth" should be the end of that month', () => { + expect(navEndMonth).toEqual(new Date(2022, 4, 31)); + }); + }); + + describe('when "fromYear" is set', () => { + const today = new Date(2024, 4, 3); + const fromYear = 2022; + const [navStartMonth, navEndMonth] = getNavMonths( + { + captionLayout, + fromYear, + today + }, + defaultDateLib + ); + test('"startMonth" should be equal to the "fromYear"', () => { + expect(navStartMonth).toEqual(new Date(2022, 0, 1)); + }); + test('"endMonth" should be the end of this year', () => { + expect(navEndMonth).toEqual(new Date(2024, 11, 31)); + }); + }); + + describe('when "toYear" is set', () => { + const today = new Date(2021, 4, 3); + const toYear = 2022; + const [navStartMonth, navEndMonth] = getNavMonths( + { + captionLayout, + toYear, + today + }, + defaultDateLib + ); + test('"startMonth" should be 100 years ago', () => { + expect(navStartMonth).toEqual(new Date(1921, 0, 1)); + }); + test('"endMonth" should be equal to "toYear"', () => { + expect(navEndMonth).toEqual(new Date(2022, 11, 31)); + }); + }); + } +); + +describe('when "captionLayout" is "dropdown-months"', () => { const today = new Date(2024, 4, 3); const [navStartMonth, navEndMonth] = getNavMonths( { - captionLayout: "dropdown", + captionLayout: "dropdown-months", today }, defaultDateLib ); - test('"startMonth" should be 100 years ago', () => { - expect(navStartMonth).toEqual(new Date(1924, 0, 1)); + test('"startMonth" should be undefined', () => { + expect(navStartMonth).toBeUndefined(); }); - test('"endMonth" should be the end of this year', () => { - expect(navEndMonth).toEqual(new Date(2024, 11, 31)); + test('"endMonth" should be undefined', () => { + expect(navEndMonth).toBeUndefined(); }); + + describe('when "startMonth" is set', () => { + const today = new Date(2024, 4, 3); + const startMonth = new Date(2021, 4, 3); + const [navStartMonth, navEndMonth] = getNavMonths( + { + captionLayout: "dropdown-months", + startMonth, + today + }, + defaultDateLib + ); + test('"startMonth" should be the start of that month', () => { + expect(navStartMonth).toEqual(new Date(2021, 4, 1)); + }); + test('"endMonth" should be undefined', () => { + expect(navEndMonth).toBeUndefined(); + }); + }); + + describe('when "endMonth" is set', () => { + const today = new Date(2021, 4, 3); + const endMonth = new Date(2022, 4, 3); + const [navStartMonth, navEndMonth] = getNavMonths( + { + captionLayout: "dropdown-months", + endMonth, + today + }, + defaultDateLib + ); + test('"startMonth" should be undefined', () => { + expect(navStartMonth).toBeUndefined(); + }); + test('"endMonth" should be the end of that month', () => { + expect(navEndMonth).toEqual(new Date(2022, 4, 31)); + }); + }); + describe('when "fromYear" is set', () => { const today = new Date(2024, 4, 3); const fromYear = 2022; const [navStartMonth, navEndMonth] = getNavMonths( { - captionLayout: "dropdown", + captionLayout: "dropdown-months", fromYear, today }, @@ -85,23 +220,24 @@ describe('when "captionLayout" is dropdown', () => { test('"startMonth" should be equal to the "fromYear"', () => { expect(navStartMonth).toEqual(new Date(2022, 0, 1)); }); - test('"endMonth" should be the end of this year', () => { - expect(navEndMonth).toEqual(new Date(2024, 11, 31)); + test('"endMonth" should be undefined', () => { + expect(navEndMonth).toBeUndefined(); }); }); + describe('when "toYear" is set', () => { const today = new Date(2021, 4, 3); const toYear = 2022; const [navStartMonth, navEndMonth] = getNavMonths( { - captionLayout: "dropdown", + captionLayout: "dropdown-months", toYear, today }, defaultDateLib ); - test('"startMonth" should be 100 years ago', () => { - expect(navStartMonth).toEqual(new Date(1921, 0, 1)); + test('"startMonth" should be undefined', () => { + expect(navStartMonth).toBeUndefined(); }); test('"endMonth" should be equal to "toYear"', () => { expect(navEndMonth).toEqual(new Date(2022, 11, 31)); diff --git a/src/helpers/getNavMonth.ts b/src/helpers/getNavMonth.ts index b16dbe92c..3019f2000 100644 --- a/src/helpers/getNavMonth.ts +++ b/src/helpers/getNavMonth.ts @@ -46,19 +46,21 @@ export function getNavMonths( endMonth = newDate(toYear, 11, 31); } - const hasDropdowns = props.captionLayout?.startsWith("dropdown"); + const hasYearDropdown = + props.captionLayout === "dropdown" || + props.captionLayout === "dropdown-years"; if (startMonth) { startMonth = startOfMonth(startMonth); } else if (fromYear) { startMonth = newDate(fromYear, 0, 1); - } else if (!startMonth && hasDropdowns) { + } else if (!startMonth && hasYearDropdown) { startMonth = startOfYear(addYears(props.today ?? today(), -100)); } if (endMonth) { endMonth = endOfMonth(endMonth); } else if (toYear) { endMonth = newDate(toYear, 11, 31); - } else if (!endMonth && hasDropdowns) { + } else if (!endMonth && hasYearDropdown) { endMonth = endOfYear(props.today ?? today()); } return [ diff --git a/src/helpers/getYearOptions.test.ts b/src/helpers/getYearOptions.test.ts index b54ff45e8..3f6015844 100644 --- a/src/helpers/getYearOptions.test.ts +++ b/src/helpers/getYearOptions.test.ts @@ -3,7 +3,7 @@ import { defaultDateLib } from "../classes/DateLib"; import { getFormatters } from "./getFormatters"; import { getYearOptions } from "./getYearOptions"; -test("return undefined if startMonth or endMonth is not provided", () => { +test("return undefined if navStart or navEnd is not provided", () => { const formatters = getFormatters({ formatYearDropdown: (date: Date) => `${date.getFullYear()}` });