| import { render } from "@testing-library/react"; | |
| import React from "react"; | |
| import { setTestTime } from "@/test/setTestTime"; | |
| import { user } from "@/test/user"; | |
| import { nextButton, previousButton } from "../test/elements"; | |
| import { DayPicker } from "./DayPicker"; | |
| setTestTime(new Date(2025, 1, 10)); | |
| const getRootContainer = () => document.querySelector(`.rdp-root`); | |
| const getNavContainers = () => [ | |
| ...document.querySelectorAll(`[data-animated-nav]`), | |
| ]; | |
| const getMonthContainers = () => [ | |
| ...document.querySelectorAll(`[data-animated-month]`), | |
| ]; | |
| const getMonthCaptionContainers = () => [ | |
| ...document.querySelectorAll(`[data-animated-caption]`), | |
| ]; | |
| const getMonthWeekdaysContainers = () => [ | |
| ...document.querySelectorAll(`[data-animated-weekdays]`), | |
| ]; | |
| const getMonthWeeksContainers = () => [ | |
| ...document.querySelectorAll(`[data-animated-weeks]`), | |
| ]; | |
| describe("useAnimation", () => { | |
| describe("animate prop is falsy", () => { | |
| it("should not render elements with data-animated-* attributes", () => { | |
| render(<DayPicker />); | |
| expect(getMonthContainers()).toHaveLength(0); | |
| expect(getMonthCaptionContainers()).toHaveLength(0); | |
| expect(getMonthWeekdaysContainers()).toHaveLength(0); | |
| expect(getMonthWeeksContainers()).toHaveLength(0); | |
| }); | |
| }); | |
| describe("animate prop is true", () => { | |
| it("should render elements with data-animated-* attributes", () => { | |
| render(<DayPicker animate={true} numberOfMonths={2} />); | |
| expect(getMonthContainers()).toHaveLength(2); | |
| expect(getMonthCaptionContainers()).toHaveLength(2); | |
| expect(getMonthWeekdaysContainers()).toHaveLength(2); | |
| expect(getMonthWeeksContainers()).toHaveLength(2); | |
| }); | |
| it("should add dom snapshots for each month for animation", async () => { | |
| render(<DayPicker animate={true} numberOfMonths={2} />); | |
| await user.click(nextButton()); | |
| expect(getMonthContainers()).toHaveLength(4); | |
| expect(getMonthCaptionContainers()).toHaveLength(4); | |
| expect(getMonthWeekdaysContainers()).toHaveLength(4); | |
| expect(getMonthWeeksContainers()).toHaveLength(4); | |
| }); | |
| it("should continue animating the same exiting month if month changed during animation", async () => { | |
| render(<DayPicker animate={true} />); | |
| await user.click(nextButton()); | |
| expect(getMonthCaptionContainers()[0]).toHaveTextContent("February 2025"); | |
| expect(getMonthCaptionContainers()[1]).toHaveTextContent("March 2025"); | |
| await user.click(nextButton()); | |
| expect(getMonthCaptionContainers()[0]).toHaveTextContent("February 2025"); | |
| expect(getMonthCaptionContainers()[1]).toHaveTextContent("April 2025"); | |
| }); | |
| it("should handle month changes during animation to correctly animate the next month change", async () => { | |
| render(<DayPicker animate={true} />); | |
| await user.click(nextButton()); | |
| await user.click(nextButton()); | |
| const animationEndEvent = new Event("animationend"); | |
| getMonthCaptionContainers()[0].dispatchEvent(animationEndEvent); | |
| await user.click(nextButton()); | |
| expect(getMonthCaptionContainers()[0]).toHaveTextContent("April 2025"); | |
| expect(getMonthCaptionContainers()[1]).toHaveTextContent("May 2025"); | |
| expect(getMonthContainers()).toHaveLength(2); | |
| expect(getMonthCaptionContainers()).toHaveLength(2); | |
| expect(getMonthWeekdaysContainers()).toHaveLength(2); | |
| expect(getMonthWeeksContainers()).toHaveLength(2); | |
| expect(getMonthCaptionContainers()[0]).not.toHaveClass( | |
| "rdp-caption_after_enter", | |
| ); | |
| expect(getMonthWeeksContainers()[0]).not.toHaveClass( | |
| "rdp-weeks_after_enter", | |
| ); | |
| }); | |
| it("should apply the correct animation class when entering month is after the exiting month", async () => { | |
| render(<DayPicker animate={true} />); | |
| await user.click(nextButton()); | |
| expect(getMonthCaptionContainers()[0]).toHaveClass( | |
| "rdp-caption_before_exit", | |
| ); | |
| expect(getMonthCaptionContainers()[1]).toHaveClass( | |
| "rdp-caption_after_enter", | |
| ); | |
| expect(getMonthWeeksContainers()[0]).toHaveClass("rdp-weeks_before_exit"); | |
| expect(getMonthWeeksContainers()[1]).toHaveClass("rdp-weeks_after_enter"); | |
| }); | |
| it("should apply the correct animation class when entering month is before the exiting month", async () => { | |
| render(<DayPicker animate={true} />); | |
| await user.click(previousButton()); | |
| expect(getMonthCaptionContainers()[0]).toHaveClass( | |
| "rdp-caption_after_exit", | |
| ); | |
| expect(getMonthCaptionContainers()[1]).toHaveClass( | |
| "rdp-caption_before_enter", | |
| ); | |
| expect(getMonthWeeksContainers()[0]).toHaveClass("rdp-weeks_after_exit"); | |
| expect(getMonthWeeksContainers()[1]).toHaveClass( | |
| "rdp-weeks_before_enter", | |
| ); | |
| }); | |
| it("should clean up the exiting month after animation ends", async () => { | |
| render(<DayPicker animate={true} />); | |
| await user.click(nextButton()); | |
| let navContainers = getNavContainers(); | |
| let monthContainers = getMonthContainers(); | |
| let monthCaptionContainers = getMonthCaptionContainers(); | |
| let monthWeekdaysContainers = getMonthWeekdaysContainers(); | |
| let monthWeeksContainers = getMonthWeeksContainers(); | |
| expect(navContainers).toHaveLength(1); | |
| expect(monthContainers).toHaveLength(2); | |
| expect(monthCaptionContainers).toHaveLength(2); | |
| expect(monthWeekdaysContainers).toHaveLength(2); | |
| expect(monthWeeksContainers).toHaveLength(2); | |
| expect(getRootContainer()).toHaveStyle("isolation: isolate"); | |
| expect(navContainers[0]).toHaveStyle("z-index: 1"); | |
| expect(monthContainers[0]).toHaveStyle("position: relative"); | |
| expect(monthContainers[0]).toHaveStyle("overflow: hidden"); | |
| expect(monthContainers[1]).toHaveStyle("overflow: hidden"); | |
| expect(monthContainers[1]).toHaveStyle("pointer-events: none"); | |
| expect(monthContainers[1]).toHaveStyle("position: absolute"); | |
| expect(monthContainers[1]).toHaveAttribute("aria-hidden", "true"); | |
| expect(monthWeekdaysContainers[0]).toHaveStyle("opacity: 0"); | |
| expect(monthCaptionContainers[1]).toHaveClass("rdp-caption_after_enter"); | |
| expect(monthWeeksContainers[1]).toHaveClass("rdp-weeks_after_enter"); | |
| const animationEndEvent = new Event("animationend"); | |
| getMonthCaptionContainers()[0].dispatchEvent(animationEndEvent); | |
| navContainers = getNavContainers(); | |
| monthContainers = getMonthContainers(); | |
| monthCaptionContainers = getMonthCaptionContainers(); | |
| monthWeekdaysContainers = getMonthWeekdaysContainers(); | |
| monthWeeksContainers = getMonthWeeksContainers(); | |
| expect(navContainers).toHaveLength(1); | |
| expect(navContainers).toHaveLength(1); | |
| expect(monthContainers).toHaveLength(1); | |
| expect(monthCaptionContainers).toHaveLength(1); | |
| expect(monthWeekdaysContainers).toHaveLength(1); | |
| expect(monthWeeksContainers).toHaveLength(1); | |
| expect(getRootContainer()).not.toHaveStyle("isolation: isolate"); | |
| expect(navContainers[0]).not.toHaveStyle("z-index: 1"); | |
| expect(monthContainers[0]).not.toHaveStyle("position: relative"); | |
| expect(monthContainers[0]).not.toHaveStyle("overflow: hidden"); | |
| expect(monthCaptionContainers[0]).not.toHaveClass( | |
| "rdp-caption_after_enter", | |
| ); | |
| expect(monthWeeksContainers[0]).not.toHaveClass("rdp-weeks_after_enter"); | |
| }); | |
| }); | |
| }); | |