Set up unit testing infrastructure

Extract slot generation from book.ts into pure utility for unit testing.
Add 8 API unit tests and 4 web component tests with coverage thresholds.

Closes #39

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit was merged in pull request #42.
This commit is contained in:
groombook-paperclip[bot]
2026-03-18 01:55:02 +00:00
committed by GitHub
parent d718821515
commit cba502e35f
10 changed files with 1046 additions and 26 deletions
+55
View File
@@ -0,0 +1,55 @@
/**
* Business hours slot generation — pure utility, no DB dependencies.
* Extracted so it can be unit tested independently of the route layer.
*/
export const BUSINESS_START_HOUR = 9; // UTC
export const BUSINESS_END_HOUR = 17; // UTC
export interface BookedSlot {
staffId: string | null;
startTime: Date;
endTime: Date;
}
/**
* Generate all available appointment start times for a given date,
* returning only slots where at least one groomer is free.
*/
export function generateAvailableSlots({
dateStr,
durationMinutes,
groomerIds,
booked,
}: {
dateStr: string;
durationMinutes: number;
groomerIds: string[];
booked: BookedSlot[];
}): string[] {
const dayStart = new Date(`${dateStr}T00:00:00Z`);
dayStart.setUTCHours(BUSINESS_START_HOUR, 0, 0, 0);
const dayEnd = new Date(`${dateStr}T00:00:00Z`);
dayEnd.setUTCHours(BUSINESS_END_HOUR, 0, 0, 0);
const durationMs = durationMinutes * 60_000;
const slots: string[] = [];
let slotStart = dayStart.getTime();
while (slotStart + durationMs <= dayEnd.getTime()) {
const slotEnd = slotStart + durationMs;
const hasGroomer = groomerIds.some(
(groomerId) =>
!booked.some(
(a) =>
a.staffId === groomerId &&
a.startTime.getTime() < slotEnd &&
a.endTime.getTime() > slotStart
)
);
if (hasGroomer) slots.push(new Date(slotStart).toISOString());
slotStart += durationMs;
}
return slots;
}