Files
TREK/client/src/vacay/yearWindow.test.ts
T
Maurice f61bab3ffd fix(vacay): open on the current year instead of the last one added (#2056)
The year list comes back sorted, so picking its last element meant Vacay always
landed on the highest year — add 2030 to plan ahead and every visit from then on
opened 2030. It now opens the leave-year period today falls into, falls back to
the closest year the plan has when that period has none, and keeps the year the
viewer is on when a live update reloads the list.
2026-08-27 10:55:27 +02:00

157 lines
6.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect } from 'vitest'
import {
DEFAULT_YEAR_SETTINGS,
currentPeriodYear,
defaultPeriodYear,
gridWindow,
inGridWindow,
resolveYearWindow,
windowCalendarYears,
windowMonths,
} from './yearWindow'
import type { VacayYearSettings } from '../types'
const fiscal = (month: number, day = 1): VacayYearSettings => ({
year_type: 'fiscal', year_start_month: month, year_start_day: day, hire_date: null,
})
const anniversary = (hire: string | null): VacayYearSettings => ({
year_type: 'anniversary', year_start_month: 1, year_start_day: 1, hire_date: hire,
})
describe('resolveYearWindow', () => {
// FE-VACAY-YEARWINDOW-001
it('defaults to the plain calendar year', () => {
expect(resolveYearWindow(2026)).toEqual({ start: '2026-01-01', end: '2027-01-01' })
expect(resolveYearWindow(2026, DEFAULT_YEAR_SETTINGS)).toEqual({ start: '2026-01-01', end: '2027-01-01' })
})
// FE-VACAY-YEARWINDOW-002
it('starts a fiscal year on the configured month and day', () => {
expect(resolveYearWindow(2026, fiscal(7))).toEqual({ start: '2026-07-01', end: '2027-07-01' })
expect(resolveYearWindow(2026, fiscal(4, 6))).toEqual({ start: '2026-04-06', end: '2027-04-06' })
})
// FE-VACAY-YEARWINDOW-003
it('follows the hire date for an anniversary year, falling back to January 1 without one', () => {
expect(resolveYearWindow(2026, anniversary('2019-09-16'))).toEqual({ start: '2026-09-16', end: '2027-09-16' })
expect(resolveYearWindow(2026, anniversary(null))).toEqual({ start: '2026-01-01', end: '2027-01-01' })
})
// FE-VACAY-YEARWINDOW-004
it('matches the server: consecutive periods meet exactly', () => {
expect(resolveYearWindow(2025, fiscal(7)).end).toBe(resolveYearWindow(2026, fiscal(7)).start)
})
// FE-VACAY-YEARWINDOW-004a
it('ignores a month left behind by a previous fiscal setting when there is no hire date', () => {
// The settings UI sends the whole object, so switching to anniversary carries
// the old fiscal month along until a hire date is entered.
const stale = { year_type: 'anniversary' as const, year_start_month: 4, year_start_day: 1, hire_date: null }
expect(resolveYearWindow(2026, stale)).toEqual({ start: '2026-01-01', end: '2027-01-01' })
expect(windowMonths(2026, stale)[0]).toEqual({ year: 2026, month: 0 })
})
// FE-VACAY-YEARWINDOW-004b
it('clamps a start day the month cannot have, matching the server', () => {
expect(resolveYearWindow(2026, anniversary('2024-02-29'))).toEqual({ start: '2026-02-28', end: '2027-02-28' })
expect(resolveYearWindow(2026, fiscal(2, 31))).toEqual({ start: '2026-02-28', end: '2027-02-28' })
})
})
describe('windowMonths', () => {
// FE-VACAY-YEARWINDOW-005
it('lists January to December of the year for a calendar window', () => {
const months = windowMonths(2026)
expect(months).toHaveLength(12)
expect(months[0]).toEqual({ year: 2026, month: 0 })
expect(months[11]).toEqual({ year: 2026, month: 11 })
})
// FE-VACAY-YEARWINDOW-006
it('rolls over the calendar year for a fiscal window', () => {
const months = windowMonths(2026, fiscal(7))
expect(months[0]).toEqual({ year: 2026, month: 6 }) // Jul 2026
expect(months[5]).toEqual({ year: 2026, month: 11 }) // Dec 2026
expect(months[6]).toEqual({ year: 2027, month: 0 }) // Jan 2027
expect(months[11]).toEqual({ year: 2027, month: 5 }) // Jun 2027
})
// FE-VACAY-YEARWINDOW-007
it('ignores the start day — the grid always renders whole months', () => {
expect(windowMonths(2026, fiscal(4, 6))[0]).toEqual({ year: 2026, month: 3 })
})
})
describe('gridWindow / inGridWindow', () => {
// FE-VACAY-YEARWINDOW-008
it('is the window itself whenever it starts on the first of a month', () => {
expect(gridWindow(2026)).toEqual(resolveYearWindow(2026))
expect(gridWindow(2026, fiscal(7))).toEqual(resolveYearWindow(2026, fiscal(7)))
})
// FE-VACAY-YEARWINDOW-009
it('widens to whole months when the window starts later in the month', () => {
expect(gridWindow(2026, fiscal(4, 6))).toEqual({ start: '2026-04-01', end: '2027-04-01' })
})
// FE-VACAY-YEARWINDOW-010
it('accepts the days the grid shows and rejects the neighbouring periods', () => {
expect(inGridWindow('2026-12-31', 2026, fiscal(7))).toBe(true)
expect(inGridWindow('2027-01-01', 2026, fiscal(7))).toBe(true)
expect(inGridWindow('2027-06-30', 2026, fiscal(7))).toBe(true)
expect(inGridWindow('2026-06-30', 2026, fiscal(7))).toBe(false)
expect(inGridWindow('2027-07-01', 2026, fiscal(7))).toBe(false)
})
})
describe('windowCalendarYears', () => {
// FE-VACAY-YEARWINDOW-011
it('is one year for a calendar window and two for a shifted one', () => {
expect(windowCalendarYears(2026)).toEqual([2026])
expect(windowCalendarYears(2026, fiscal(7))).toEqual([2026, 2027])
})
})
describe('currentPeriodYear', () => {
// FE-VACAY-YEARWINDOW-012
it('is today’s year for a calendar user', () => {
expect(currentPeriodYear(DEFAULT_YEAR_SETTINGS, new Date(2026, 2, 15))).toBe(2026)
})
// FE-VACAY-YEARWINDOW-013
it('is the previous year while a shifted period has not started yet', () => {
expect(currentPeriodYear(fiscal(7), new Date(2026, 2, 15))).toBe(2025)
expect(currentPeriodYear(fiscal(7), new Date(2026, 7, 15))).toBe(2026)
expect(currentPeriodYear(fiscal(7), new Date(2026, 6, 1))).toBe(2026)
})
})
describe('defaultPeriodYear', () => {
// FE-VACAY-YEARWINDOW-014
it('picks the current period when the plan has it', () => {
const today = new Date(2026, 2, 15)
expect(defaultPeriodYear([2024, 2025, 2026, 2030], DEFAULT_YEAR_SETTINGS, today)).toBe(2026)
})
// FE-VACAY-YEARWINDOW-015
it('falls back to the closest year and prefers the coming one on a tie', () => {
const today = new Date(2026, 2, 15)
expect(defaultPeriodYear([2022, 2024], DEFAULT_YEAR_SETTINGS, today)).toBe(2024)
expect(defaultPeriodYear([2028, 2030], DEFAULT_YEAR_SETTINGS, today)).toBe(2028)
expect(defaultPeriodYear([2024, 2028], DEFAULT_YEAR_SETTINGS, today)).toBe(2028)
})
// FE-VACAY-YEARWINDOW-016
it('is the current period for an empty plan', () => {
expect(defaultPeriodYear([], DEFAULT_YEAR_SETTINGS, new Date(2026, 2, 15))).toBe(2026)
})
// FE-VACAY-YEARWINDOW-017
it('follows a shifted leave year rather than the calendar year', () => {
const today = new Date(2026, 2, 15)
expect(defaultPeriodYear([2025, 2026], fiscal(7), today)).toBe(2025)
expect(defaultPeriodYear([2026], fiscal(7), today)).toBe(2026)
})
})