diff --git a/src/tests/calendar/Calendar.spec.ts b/src/tests/calendar/Calendar.spec.ts index 9e6802317..e3da9d617 100644 --- a/src/tests/calendar/Calendar.spec.ts +++ b/src/tests/calendar/Calendar.spec.ts @@ -308,4 +308,247 @@ describe("Calendar", () => { expect(calendar.querySelector("[data-selected]")).toHaveTextContent("21"); expect(calendar.querySelectorAll("[data-selected]").length).toBe(1); }); + + it("should change view when controlled placeholder changes", async () => { + const { getByTestId, user } = setup({ + placeholder: calendarDate + }); + + const heading = getByTestId("heading"); + expect(heading).toHaveTextContent("January 1980"); + const addMonthBtn = getByTestId("add-month"); + await user.click(addMonthBtn); + expect(heading).toHaveTextContent("February 1980"); + const addYearBtn = getByTestId("add-year"); + await user.click(addYearBtn); + expect(heading).toHaveTextContent("February 1981"); + await user.click(addMonthBtn); + await user.click(addMonthBtn); + await user.click(addMonthBtn); + expect(heading).toHaveTextContent("May 1981"); + }); + + it("should not allow navigation before the `minValue` (prev button)", async () => { + const { getByTestId, user } = setup({ + value: calendarDate, + minValue: new CalendarDate(1979, 11, 25) + }); + + const prevBtn = getByTestId("prev-button"); + await user.click(prevBtn); + const heading = getByTestId("heading"); + expect(heading).toHaveTextContent("December 1979"); + expect(prevBtn).not.toHaveAttribute("aria-disabled", "true"); + expect(prevBtn).not.toHaveAttribute("data-disabled"); + + await user.click(prevBtn); + expect(heading).toHaveTextContent("November 1979"); + expect(prevBtn).toHaveAttribute("aria-disabled", "true"); + expect(prevBtn).toHaveAttribute("data-disabled"); + + await user.click(prevBtn); + expect(heading).toHaveTextContent("November 1979"); + }); + + it("should not allow navigation after the `maxValue` (next button)", async () => { + const { getByTestId, user } = setup({ + value: calendarDate, + maxValue: new CalendarDate(1980, 3, 25) + }); + + const nextBtn = getByTestId("next-button"); + await user.click(nextBtn); + const heading = getByTestId("heading"); + expect(heading).toHaveTextContent("February 1980"); + expect(nextBtn).not.toHaveAttribute("aria-disabled", "true"); + expect(nextBtn).not.toHaveAttribute("data-disabled"); + + await user.click(nextBtn); + expect(heading).toHaveTextContent("March 1980"); + expect(nextBtn).toHaveAttribute("aria-disabled", "true"); + expect(nextBtn).toHaveAttribute("data-disabled"); + + await user.click(nextBtn); + expect(heading).toHaveTextContent("March 1980"); + }); + + it("does not navigate after `maxValue` (with keyboard)", async () => { + const { getByTestId, user } = setup({ + value: calendarDate, + maxValue: new CalendarDate(1980, 3, 31) + }); + + const firstDayInMonth = getByTestId("date-1-1"); + firstDayInMonth.focus(); + expect(firstDayInMonth).toHaveFocus(); + + const heading = getByTestId("heading"); + expect(heading).toHaveTextContent("January 1980"); + + // five keypresses to February 1980 + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-1-8")).toHaveFocus(); + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-1-15")).toHaveFocus(); + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-1-22")).toHaveFocus(); + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-1-29")).toHaveFocus(); + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-2-5")).toHaveFocus(); + expect(heading).toHaveTextContent("February 1980"); + + // four keypresses to March 1980 + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-2-12")).toHaveFocus(); + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-2-19")).toHaveFocus(); + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-2-26")).toHaveFocus(); + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-3-4")).toHaveFocus(); + expect(heading).toHaveTextContent("March 1980"); + + // four keypresses to April 1980 + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-3-11")).toHaveFocus(); + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-3-18")).toHaveFocus(); + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-3-25")).toHaveFocus(); + await user.keyboard(kbd.ARROW_DOWN); + expect(getByTestId("date-3-25")).toHaveFocus(); + expect(heading).toHaveTextContent("March 1980"); + }); + + it("does not navigate before `minValue` (with keyboard)", async () => { + const { getByTestId, user } = setup({ + value: calendarDate, + minValue: new CalendarDate(1979, 12, 1) + }); + + const firstDayInMonth = getByTestId("date-1-1"); + firstDayInMonth.focus(); + expect(firstDayInMonth).toHaveFocus(); + + const heading = getByTestId("heading"); + expect(heading).toHaveTextContent("January 1980"); + + // one keypress to get to December 1979 + await user.keyboard(kbd.ARROW_UP); + expect(getByTestId("date-12-25")).toHaveFocus(); + expect(heading).toHaveTextContent("December 1979"); + + // four keypresses to November 1979 + await user.keyboard(kbd.ARROW_UP); + expect(getByTestId("date-12-18")).toHaveFocus(); + await user.keyboard(kbd.ARROW_UP); + expect(getByTestId("date-12-11")).toHaveFocus(); + await user.keyboard(kbd.ARROW_UP); + expect(getByTestId("date-12-4")).toHaveFocus(); + await user.keyboard(kbd.ARROW_UP); + expect(getByTestId("date-12-4")).toHaveFocus(); + expect(heading).toHaveTextContent("December 1979"); + }); + + it("handles unavailable dates appropriately", async () => { + const { getByTestId, user } = setup({ + placeholder: calendarDate, + isDateUnavailable: (date) => { + return date.day === 3; + } + }); + + const thirdDayInMonth = getByTestId("date-1-3"); + expect(thirdDayInMonth).toHaveTextContent("3"); + expect(thirdDayInMonth).toHaveAttribute("data-unavailable"); + expect(thirdDayInMonth).toHaveAttribute("aria-disabled", "true"); + await user.click(thirdDayInMonth); + expect(thirdDayInMonth).not.toHaveAttribute("data-selected"); + }); + + it("doesnt allow focus or interaction when `disabled` is `true`", async () => { + const { getByTestId, user } = setup({ + placeholder: calendarDate, + disabled: true + }); + + const grid = getByTestId("grid-1"); + expect(grid).toHaveAttribute("aria-disabled", "true"); + expect(grid).toHaveAttribute("data-disabled"); + + const firstDayOfMonth = getByTestId("date-1-1"); + expect(firstDayOfMonth).toHaveAttribute("aria-disabled", "true"); + expect(firstDayOfMonth).toHaveAttribute("data-disabled"); + await user.click(firstDayOfMonth); + expect(firstDayOfMonth).not.toHaveAttribute("data-selected"); + firstDayOfMonth.focus(); + expect(firstDayOfMonth).not.toHaveFocus(); + + const tenthDayOfMonth = getByTestId("date-1-10"); + expect(tenthDayOfMonth).toHaveAttribute("aria-disabled", "true"); + expect(tenthDayOfMonth).toHaveAttribute("data-disabled"); + await user.click(tenthDayOfMonth); + expect(tenthDayOfMonth).not.toHaveAttribute("data-selected"); + tenthDayOfMonth.focus(); + expect(tenthDayOfMonth).not.toHaveFocus(); + }); + + it("prevents selection but allows focus when `readonly` is `true`", async () => { + const { getByTestId, user } = setup({ + placeholder: calendarDate, + readonly: true + }); + + const grid = getByTestId("grid-1"); + expect(grid).toHaveAttribute("aria-readonly", "true"); + expect(grid).toHaveAttribute("data-readonly"); + + const firstDayOfMonth = getByTestId("date-1-1"); + await user.click(firstDayOfMonth); + expect(firstDayOfMonth).not.toHaveAttribute("data-selected"); + firstDayOfMonth.focus(); + expect(firstDayOfMonth).toHaveFocus(); + + const tenthDayOfMonth = getByTestId("date-1-10"); + await user.click(tenthDayOfMonth); + expect(tenthDayOfMonth).not.toHaveAttribute("data-selected"); + tenthDayOfMonth.focus(); + expect(tenthDayOfMonth).toHaveFocus(); + }); + + it("formats the weekday labels correctly - `'narrow'`", async () => { + const { getByTestId } = setup({ + placeholder: calendarDate, + weekdayFormat: "narrow" + }); + for (const [i, weekday] of narrowWeekdays.entries()) { + const weekdayEl = getByTestId(`weekday-1-${i}`); + expect(weekdayEl).toHaveTextContent(weekday); + } + }); + + it("formats the weekday labels correctly - `'short'`", async () => { + const { getByTestId } = setup({ + placeholder: calendarDate, + weekdayFormat: "short" + }); + for (const [i, weekday] of shortWeekdays.entries()) { + const weekdayEl = getByTestId(`weekday-1-${i}`); + expect(weekdayEl).toHaveTextContent(weekday); + } + }); + + it("formats the weekday labels correctly - `'long'`", async () => { + const { getByTestId } = setup({ + placeholder: calendarDate, + weekdayFormat: "long" + }); + for (const [i, weekday] of longWeekdays.entries()) { + const weekdayEl = getByTestId(`weekday-1-${i}`); + expect(weekdayEl).toHaveTextContent(weekday); + } + }); }); + +describe.todo("Calendar - `multiple`"); diff --git a/src/tests/calendar/CalendarTest.svelte b/src/tests/calendar/CalendarTest.svelte index a1c513c9c..1d79b83a8 100644 --- a/src/tests/calendar/CalendarTest.svelte +++ b/src/tests/calendar/CalendarTest.svelte @@ -9,6 +9,8 @@ function changeValue(field: "day" | "month" | "year") { if (value) { value = value.cycle(field, 1); + } else if (placeholder) { + placeholder = placeholder.cycle(field, 1); } } @@ -44,7 +46,7 @@ {#each weekdays as day, i} - + {day} {/each}