-
Notifications
You must be signed in to change notification settings - Fork 162
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: testing calentar and date-time utils more
- Loading branch information
Showing
24 changed files
with
580 additions
and
195 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
import { addYears, startOfMonth, subYears } from 'date-fns'; | ||
|
||
import { getBaseDay, moveDay, moveNextDay, moveNextWeek, movePrevDay, movePrevWeek } from '../navigation-day'; | ||
|
||
//mocked to avoid complications with timezones in the 'date-fns' package | ||
jest.mock('date-fns', () => ({ ...jest.requireActual('date-fns'), startOfMonth: () => new Date('2025-01-01') })); | ||
|
||
const startDate = new Date(`2022-01-15`); | ||
|
||
function disableDates(...blockedDates: string[]) { | ||
return (date: Date) => blockedDates.every(blocked => new Date(blocked).getTime() !== date.getTime()); | ||
} | ||
|
||
describe('getBaseDay', () => { | ||
const baseDate = new Date('2024-04-15'); | ||
|
||
test('returns first day of month when it is focusable', () => { | ||
const isDateFocusable = () => true; // All days are focusable | ||
const result = getBaseDay(baseDate, isDateFocusable); | ||
expect(result).toEqual(startOfMonth(baseDate)); | ||
}); | ||
|
||
test('returns first focusable day within the same month', () => { | ||
const isDateFocusable = (date: Date) => date.getDate() === 5; // Only the 5th of each month is focusable | ||
const result = getBaseDay(baseDate, isDateFocusable); | ||
expect(result).toEqual(new Date('2025-01-05')); //5th of month after mock | ||
}); | ||
|
||
test('returns first day of month when no days are focusable', () => { | ||
const isDateFocusable = () => false; // No days are focusable | ||
const result = getBaseDay(baseDate, isDateFocusable); | ||
expect(result).toEqual(new Date(`2025-01-01`)); //start of year of mock | ||
}); | ||
|
||
test('returns first day of month when first focusable day is in next month', () => { | ||
const isDateFocusable = (date: Date) => date >= new Date('2024-05-01'); // Only days from May 1, 2024 are focusable | ||
const result = getBaseDay(baseDate, isDateFocusable); | ||
expect(result).toEqual(startOfMonth(baseDate)); | ||
}); | ||
|
||
test('handles custom isDateFocusable function', () => { | ||
const isDateFocusable = (date: Date) => date.getDay() === 1; // Only Mondays are focusable | ||
const result = getBaseDay(baseDate, isDateFocusable); | ||
expect(result).toEqual(new Date('2025-01-06')); //first monday after mock | ||
expect(result.getDay()).toEqual(1); | ||
}); | ||
|
||
test('works with dates at the start of the month', () => { | ||
const startOfMonthDate = new Date('2024-04-01'); | ||
const isDateFocusable = (date: Date) => date.getDate() === 3; // Only the 3rd of each month is focusable | ||
const result = getBaseDay(startOfMonthDate, isDateFocusable); | ||
expect(result).toEqual(new Date('2025-01-03')); // first 3rd day after mock | ||
}); | ||
|
||
test('works with dates at the end of the month', () => { | ||
const endOfMonthDate = new Date('2024-04-30'); | ||
const isDateFocusable = (date: Date) => date.getDate() === 28; // Only the 28th of each month is focusable | ||
const result = getBaseDay(endOfMonthDate, isDateFocusable); | ||
expect(result).toEqual(new Date('2025-01-28')); // April 28, 2024 | ||
}); | ||
}); | ||
|
||
describe('moveDay', () => { | ||
const baseDate = new Date('2024-01-15'); | ||
|
||
test('moves forward to the next active day', () => { | ||
const isDateFocusable = (date: Date) => date.getDate() === 20; // Only the 20th of each month is active | ||
const result = moveDay(baseDate, isDateFocusable, 1); | ||
expect(result).toEqual(new Date('2024-01-20')); | ||
}); | ||
|
||
test('moves backward to the previous active day', () => { | ||
const isDateFocusable = (date: Date) => date.getDate() === 10; // Only the 10th of each month is active | ||
const result = moveDay(baseDate, isDateFocusable, -1); | ||
expect(result).toEqual(new Date('2024-01-10')); | ||
}); | ||
|
||
test('returns start date if no active day found within 1 year forward', () => { | ||
const isDateFocusable = () => false; // No days are active | ||
const result = moveDay(baseDate, isDateFocusable, 1); | ||
expect(result).toEqual(baseDate); | ||
}); | ||
|
||
test('returns start date if no active day found within 1 year backward', () => { | ||
const isDateFocusable = () => false; // No days are active | ||
const result = moveDay(baseDate, isDateFocusable, -1); | ||
expect(result).toEqual(baseDate); | ||
}); | ||
|
||
test('finds active day at the edge of 1 year limit', () => { | ||
const oneYearLater = addYears(baseDate, 1); | ||
const oneYearEarlier = subYears(baseDate, 1); | ||
|
||
const isDateFocusable = (date: Date) => | ||
date.getTime() === oneYearLater.getTime() || date.getTime() === oneYearEarlier.getTime(); | ||
|
||
const forwardResult = moveDay(baseDate, isDateFocusable, 1); | ||
expect(forwardResult).toEqual(oneYearLater); | ||
|
||
const backwardResult = moveDay(baseDate, isDateFocusable, -1); | ||
expect(backwardResult).toEqual(oneYearEarlier); | ||
}); | ||
|
||
test('handles custom isDateFocusable function', () => { | ||
const isDateFocusable = (date: Date) => date.getDay() === 1; // Only Mondays are active | ||
const result = moveDay(baseDate, isDateFocusable, 1); | ||
expect(result).toEqual(new Date('2024-01-22')); | ||
expect(result.getDay()).toEqual(1); | ||
}); | ||
|
||
test('moves multiple steps forward', () => { | ||
const isDateFocusable = (date: Date) => date.getDate() % 5 === 0; // Every 5th day is active | ||
const result = moveDay(baseDate, isDateFocusable, 3); | ||
expect(result).toEqual(new Date('2024-01-30')); | ||
}); | ||
|
||
test('moves multiple steps backward', () => { | ||
const isDateFocusable = (date: Date) => date.getDate() % 5 === 0; // Every 5th day is active | ||
const result = moveDay(baseDate, isDateFocusable, -3); | ||
expect(result).toEqual(new Date('2023-12-25')); | ||
}); | ||
}); | ||
|
||
test('moveNextDay', () => { | ||
expect(moveNextDay(startDate, () => true)).toEqual(new Date('2022-01-16')); | ||
expect(moveNextDay(startDate, disableDates('2022-01-16', '2022-01-17'))).toEqual(new Date('2022-01-18')); | ||
}); | ||
|
||
test('movePrevDay', () => { | ||
expect(movePrevDay(startDate, () => true)).toEqual(new Date('2022-01-14')); | ||
expect(movePrevDay(startDate, disableDates('2022-01-14', '2022-01-13'))).toEqual(new Date('2022-01-12')); | ||
}); | ||
|
||
test('moveNextWeek', () => { | ||
expect(moveNextWeek(startDate, () => true)).toEqual(new Date('2022-01-22')); | ||
expect(moveNextWeek(startDate, disableDates('2022-01-22', '2022-01-29'))).toEqual(new Date('2022-02-05')); | ||
}); | ||
|
||
test('movePrevWeek', () => { | ||
expect(movePrevWeek(startDate, () => true)).toEqual(new Date('2022-01-08')); | ||
expect(movePrevWeek(startDate, disableDates('2022-01-08', '2022-01-01'))).toEqual(new Date('2021-12-25')); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
import { addYears, subYears } from 'date-fns'; | ||
|
||
import { getBaseMonth, moveMonth } from '../navigation-month'; | ||
|
||
//mocked to avoid complications with timezones in the 'date-fns' package | ||
jest.mock('date-fns', () => ({ ...jest.requireActual('date-fns'), startOfYear: () => new Date('2025-01-01') })); | ||
|
||
const startYear = '2022', | ||
startMonth = '01', | ||
startDay = '15'; | ||
const startDate = new Date(`${startYear}-${startMonth}-${startDay}`); | ||
|
||
function disableMonths(...blockedDates: string[]) { | ||
return (date: Date) => blockedDates.every(blocked => new Date(blocked).getMonth() !== date.getMonth()); | ||
} | ||
|
||
describe('moveMonth', () => { | ||
const baseDate = new Date('2024-01-01'); | ||
4; | ||
|
||
test('moves forward to the next active month', () => { | ||
const isDateFocusable = (date: Date) => date.getMonth() === 2; // Only March is active | ||
const result = moveMonth(baseDate, isDateFocusable, 1); | ||
expect(result).toEqual(new Date('2024-03-01')); | ||
}); | ||
|
||
test('moves backward to the previous active month', () => { | ||
const isDateFocusable = (date: Date) => date.getMonth() === 10; // Only November is active | ||
const result = moveMonth(baseDate, isDateFocusable, -1); | ||
expect(result).toEqual(new Date('2023-11-01')); // November 1, 2023 | ||
}); | ||
|
||
test('returns start date if no active month found within 10 years forward', () => { | ||
const isDateFocusable = () => false; // No months are active | ||
const result = moveMonth(baseDate, isDateFocusable, 1); | ||
expect(result).toEqual(baseDate); | ||
}); | ||
|
||
test('returns start date if no active month found within 10 years backward', () => { | ||
const isDateFocusable = () => false; // No months are active | ||
const result = moveMonth(baseDate, isDateFocusable, -1); | ||
expect(result).toEqual(baseDate); | ||
}); | ||
|
||
test('finds active month at the edge of 10 year limit', () => { | ||
//set to match mock above | ||
const tenYearsLater = addYears(new Date('2025-01-01'), 10); | ||
const tenYearsEarlier = subYears(new Date('2025-01-01'), 10); | ||
|
||
const isDateFocusable = (date: Date) => | ||
date.getTime() === tenYearsLater.getTime() || date.getTime() === tenYearsEarlier.getTime(); | ||
|
||
const forwardResult = moveMonth(baseDate, isDateFocusable, 1); | ||
expect(forwardResult).toEqual(tenYearsLater); | ||
|
||
const backwardResult = moveMonth(baseDate, isDateFocusable, -1); | ||
expect(backwardResult).toEqual(tenYearsEarlier); | ||
}); | ||
}); | ||
|
||
test('getBaseMonth', () => { | ||
expect(getBaseMonth(startDate, () => true)).toEqual(new Date('2025-01-01')); //match mocked date | ||
expect(getBaseMonth(startDate, disableMonths('2022-01', '2022-02'))).toEqual(new Date('2025-03')); //match first after mocked date | ||
expect(getBaseMonth(startDate, () => false)).toEqual(new Date('2025-01-01')); | ||
}); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
import { addDays, differenceInYears, isSameMonth, startOfMonth } from 'date-fns'; | ||
|
||
import { CalendarProps } from '../interfaces'; | ||
|
||
export function moveNextDay(startDate: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction) { | ||
return moveDay(startDate, isDateFocusable, 1); | ||
} | ||
|
||
export function movePrevDay(startDate: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction) { | ||
return moveDay(startDate, isDateFocusable, -1); | ||
} | ||
|
||
export function moveNextWeek(startDate: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction) { | ||
return moveDay(startDate, isDateFocusable, 7); | ||
} | ||
|
||
export function movePrevWeek(startDate: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction) { | ||
return moveDay(startDate, isDateFocusable, -7); | ||
} | ||
|
||
// Returns first enabled date of the month corresponding to the given date. | ||
// If all month's days are disabled, the first day of the month is returned. | ||
export function getBaseDay(date: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction) { | ||
const startDate = startOfMonth(date); | ||
|
||
if (isDateFocusable(startDate)) { | ||
return startDate; | ||
} | ||
const firstEnabledDate = moveDay(startDate, isDateFocusable, 1); | ||
return isSameMonth(startDate, firstEnabledDate) ? firstEnabledDate : startDate; | ||
} | ||
|
||
// Iterates days forwards or backwards until the next active day is found. | ||
// If there is no active day in a year range, the start day is returned. | ||
export function moveDay(startDate: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction, step: number): Date { | ||
const limitYears = 1; | ||
|
||
let current = addDays(startDate, step); | ||
|
||
while (!isDateFocusable(current)) { | ||
if (Math.abs(differenceInYears(startDate, current)) > limitYears) { | ||
return startDate; | ||
} | ||
current = addDays(current, step); | ||
} | ||
|
||
return current; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
import { addMonths, differenceInYears, isSameYear, startOfYear } from 'date-fns'; | ||
|
||
import { CalendarProps } from '../interfaces'; | ||
|
||
export function moveNextMonth(startDate: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction) { | ||
return moveMonth(startDate, isDateFocusable, 1); | ||
} | ||
|
||
export function movePrevMonth(startDate: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction) { | ||
return moveMonth(startDate, isDateFocusable, -1); | ||
} | ||
|
||
export function moveMonthDown(startDate: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction) { | ||
return moveMonth(startDate, isDateFocusable, 3); | ||
} | ||
|
||
export function moveMonthUp(startDate: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction) { | ||
return moveMonth(startDate, isDateFocusable, -3); | ||
} | ||
|
||
// Returns first enabled month of the year corresponding to the given date. | ||
// If all year's months are disabled, the first month of the year is returned. | ||
export function getBaseMonth(date: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction) { | ||
const startDate = startOfYear(date); | ||
if (isDateFocusable(startDate)) { | ||
return startDate; | ||
} | ||
const firstEnabledDate = moveMonth(startDate, isDateFocusable, 1); | ||
return isSameYear(startDate, firstEnabledDate) ? firstEnabledDate : startDate; | ||
} | ||
|
||
// Iterates months forwards or backwards until the next active month is found. | ||
// If there is no active month in a 10 year range, the start month is returned. | ||
export function moveMonth(startDate: Date, isDateFocusable: CalendarProps.IsDateEnabledFunction, step: number): Date { | ||
const limitYears = 10; | ||
let current = addMonths(startDate, step); | ||
|
||
while (!isDateFocusable(current)) { | ||
if (Math.abs(differenceInYears(startDate, current)) > limitYears) { | ||
return startDate; | ||
} | ||
current = addMonths(current, step); | ||
} | ||
|
||
return current; | ||
} |
Oops, something went wrong.