120 lines
3.5 KiB
TypeScript
120 lines
3.5 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import {
|
|
assertHolidayCalendarEntryDateAvailable,
|
|
assertHolidayCalendarScopeConsistency,
|
|
clampHolidayCalendarDate,
|
|
normalizeHolidayCalendarScopeInput,
|
|
normalizeHolidayCalendarStateCode,
|
|
resolveHolidayCalendarUpdateScope,
|
|
} from "../router/holiday-calendar-write-support.js";
|
|
|
|
describe("holiday calendar write support", () => {
|
|
it("normalizes state codes and optional scope fields", () => {
|
|
expect(normalizeHolidayCalendarStateCode(" by ")).toBe("BY");
|
|
expect(normalizeHolidayCalendarStateCode(undefined)).toBeNull();
|
|
expect(normalizeHolidayCalendarScopeInput({
|
|
stateCode: " ny ",
|
|
metroCityId: undefined,
|
|
})).toEqual({
|
|
stateCode: "NY",
|
|
metroCityId: null,
|
|
});
|
|
});
|
|
|
|
it("reuses existing scope values for partial updates", () => {
|
|
expect(resolveHolidayCalendarUpdateScope({
|
|
existing: {
|
|
stateCode: "BY",
|
|
metroCityId: "city_1",
|
|
},
|
|
data: {
|
|
stateCode: undefined,
|
|
metroCityId: null,
|
|
},
|
|
})).toEqual({
|
|
stateCode: "BY",
|
|
metroCityId: null,
|
|
});
|
|
});
|
|
|
|
it("clamps dates to UTC midnight", () => {
|
|
expect(clampHolidayCalendarDate(new Date("2026-12-24T18:45:00.000Z")).toISOString())
|
|
.toBe("2026-12-24T00:00:00.000Z");
|
|
});
|
|
|
|
it("rejects invalid state and city scope combinations before hitting uniqueness checks", async () => {
|
|
const db = {
|
|
metroCity: { findUnique: vi.fn() },
|
|
holidayCalendar: { findFirst: vi.fn() },
|
|
} as never;
|
|
|
|
await expect(assertHolidayCalendarScopeConsistency(db, {
|
|
scopeType: "STATE",
|
|
countryId: "country_de",
|
|
stateCode: null,
|
|
metroCityId: null,
|
|
})).rejects.toMatchObject({
|
|
code: "BAD_REQUEST",
|
|
message: "State calendars require a state code",
|
|
});
|
|
|
|
await expect(assertHolidayCalendarScopeConsistency(db, {
|
|
scopeType: "CITY",
|
|
countryId: "country_de",
|
|
stateCode: null,
|
|
metroCityId: null,
|
|
})).rejects.toMatchObject({
|
|
code: "BAD_REQUEST",
|
|
message: "City calendars require a metro city",
|
|
});
|
|
|
|
expect(db.holidayCalendar.findFirst).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("rejects city scopes whose metro city belongs to a different country", async () => {
|
|
const db = {
|
|
metroCity: {
|
|
findUnique: vi.fn().mockResolvedValue({
|
|
id: "city_augsburg",
|
|
countryId: "country_us",
|
|
}),
|
|
},
|
|
holidayCalendar: { findFirst: vi.fn() },
|
|
} as never;
|
|
|
|
await expect(assertHolidayCalendarScopeConsistency(db, {
|
|
scopeType: "CITY",
|
|
countryId: "country_de",
|
|
stateCode: null,
|
|
metroCityId: "city_augsburg",
|
|
})).rejects.toMatchObject({
|
|
code: "BAD_REQUEST",
|
|
message: "Metro city must belong to the selected country",
|
|
});
|
|
});
|
|
|
|
it("rejects duplicate holiday entry dates using the clamped date", async () => {
|
|
const db = {
|
|
holidayCalendarEntry: {
|
|
findFirst: vi.fn().mockResolvedValue({ id: "entry_existing" }),
|
|
},
|
|
} as never;
|
|
|
|
await expect(assertHolidayCalendarEntryDateAvailable(db, {
|
|
holidayCalendarId: "cal_1",
|
|
date: new Date("2026-12-24T18:45:00.000Z"),
|
|
})).rejects.toMatchObject({
|
|
code: "CONFLICT",
|
|
message: "A holiday entry for this calendar and date already exists",
|
|
});
|
|
|
|
expect(db.holidayCalendarEntry.findFirst).toHaveBeenCalledWith({
|
|
where: {
|
|
holidayCalendarId: "cal_1",
|
|
date: new Date("2026-12-24T00:00:00.000Z"),
|
|
},
|
|
select: { id: true },
|
|
});
|
|
});
|
|
});
|