Files
calendar/packages/ui/components/form/date-range-picker/dateRangeLogic.test.ts
T
Eunjae LeeGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1c3ced5b70 fix: simplify date range picker to Airbnb-style selection (#25386)
* feat: simplify date range picker to Airbnb-style selection

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* feat: apply Airbnb-style selection to allowPastDates branch

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: extract date range selection logic and add unit tests

- Extract date range selection logic into pure function (dateRangeLogic.ts)
- Remove unused allowPastDates parameter from selection logic
- Add comprehensive unit tests (11 test cases covering all scenarios)
- Simplify DateRangePicker component (30+ lines -> 5 lines)
- Improve separation of concerns: allowPastDates only controls calendar date restrictions

* style update

* feat: add hover highlighting for date range selection

When a start date is selected and user hovers over other dates,
the potential range between start and hovered date now shows
bg-emphasis background for better visual feedback.

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* memoize hovering range and update styles

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-12-03 14:52:25 +00:00

191 lines
5.0 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { calculateNewDateRange } from "./dateRangeLogic";
describe("calculateNewDateRange", () => {
// Helper dates for testing
const date1 = new Date("2024-01-01");
const date2 = new Date("2024-01-10");
const date3 = new Date("2024-01-20");
const date4 = new Date("2024-01-05"); // Between date1 and date2
describe("Airbnb-style date range selection", () => {
it("should start a new range when no start date is set", () => {
const result = calculateNewDateRange({
startDate: undefined,
endDate: undefined,
clickedDate: date1,
});
expect(result).toEqual({
startDate: date1,
endDate: undefined,
});
});
it("should start a new range when both dates are already set", () => {
const result = calculateNewDateRange({
startDate: date1,
endDate: date2,
clickedDate: date3,
});
expect(result).toEqual({
startDate: date3,
endDate: undefined,
});
});
it("should complete the range when only start date is set (clicked date is after start)", () => {
const result = calculateNewDateRange({
startDate: date1,
endDate: undefined,
clickedDate: date2,
});
expect(result).toEqual({
startDate: date1,
endDate: date2,
});
});
it("should complete the range and swap dates when clicked date is before start date", () => {
const result = calculateNewDateRange({
startDate: date2,
endDate: undefined,
clickedDate: date1,
});
expect(result).toEqual({
startDate: date1,
endDate: date2,
});
});
it("should handle same date click when only start date is set", () => {
const result = calculateNewDateRange({
startDate: date1,
endDate: undefined,
clickedDate: date1,
});
expect(result).toEqual({
startDate: date1,
endDate: date1,
});
});
it("should handle clicking a date between start and end when range is complete", () => {
const result = calculateNewDateRange({
startDate: date1,
endDate: date2,
clickedDate: date4,
});
expect(result).toEqual({
startDate: date4,
endDate: undefined,
});
});
it("should reset range when clicking any date after both dates are set", () => {
const result = calculateNewDateRange({
startDate: date1,
endDate: date2,
clickedDate: date1, // Click same as start
});
expect(result).toEqual({
startDate: date1,
endDate: undefined,
});
});
});
describe("Edge cases", () => {
it("should handle dates with different times on same day", () => {
const morning = new Date("2024-01-01T08:00:00");
const evening = new Date("2024-01-01T20:00:00");
const result = calculateNewDateRange({
startDate: morning,
endDate: undefined,
clickedDate: evening,
});
expect(result).toEqual({
startDate: morning,
endDate: evening,
});
});
it("should maintain immutability - not modify input dates", () => {
const originalStart = new Date("2024-01-01");
const originalEnd = new Date("2024-01-10");
const clickedDate = new Date("2024-01-15");
calculateNewDateRange({
startDate: originalStart,
endDate: originalEnd,
clickedDate,
});
// Original dates should not be modified
expect(originalStart.toISOString()).toBe(new Date("2024-01-01").toISOString());
expect(originalEnd.toISOString()).toBe(new Date("2024-01-10").toISOString());
});
it("should handle selecting dates in reverse order", () => {
// First click - set start
const result1 = calculateNewDateRange({
startDate: undefined,
endDate: undefined,
clickedDate: date2,
});
expect(result1).toEqual({
startDate: date2,
endDate: undefined,
});
// Second click - click earlier date, should swap
const result2 = calculateNewDateRange({
startDate: result1.startDate,
endDate: result1.endDate,
clickedDate: date1,
});
expect(result2).toEqual({
startDate: date1,
endDate: date2,
});
});
it("should start fresh after completing a range", () => {
// Complete a range
const result1 = calculateNewDateRange({
startDate: date1,
endDate: date2,
clickedDate: date3, // This should reset
});
expect(result1).toEqual({
startDate: date3,
endDate: undefined,
});
// Should be able to complete the new range
const result2 = calculateNewDateRange({
startDate: result1.startDate,
endDate: result1.endDate,
clickedDate: date2,
});
expect(result2).toEqual({
startDate: date2,
endDate: date3,
});
});
});
});