Files
Nexus/packages/engine/src/__tests__/calculator.test.ts
T

127 lines
3.9 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, expect, it } from "vitest";
import {
calculateAllocation,
calculateTotalCost,
countWorkingDays,
isWorkday,
} from "../allocation/calculator.js";
const stdAvailability = {
monday: 8,
tuesday: 8,
wednesday: 8,
thursday: 8,
friday: 8,
};
describe("isWorkday", () => {
it("returns true for Monday", () => {
expect(isWorkday(new Date("2025-01-06"), stdAvailability)).toBe(true); // Monday
});
it("returns false for Saturday", () => {
expect(isWorkday(new Date("2025-01-04"), stdAvailability)).toBe(false); // Saturday
});
it("returns false for Sunday", () => {
expect(isWorkday(new Date("2025-01-05"), stdAvailability)).toBe(false); // Sunday
});
});
describe("countWorkingDays", () => {
it("counts 5 days in a Mon-Fri week", () => {
const start = new Date("2025-01-06"); // Monday
const end = new Date("2025-01-10"); // Friday
expect(countWorkingDays(start, end, stdAvailability)).toBe(5);
});
it("counts 10 days over two Mon-Fri weeks", () => {
const start = new Date("2025-01-06"); // Monday
const end = new Date("2025-01-17"); // Friday
expect(countWorkingDays(start, end, stdAvailability)).toBe(10);
});
it("counts 0 for a weekend-only range", () => {
const start = new Date("2025-01-04"); // Saturday
const end = new Date("2025-01-05"); // Sunday
expect(countWorkingDays(start, end, stdAvailability)).toBe(0);
});
it("counts same day as 1 if it's a workday", () => {
const day = new Date("2025-01-06"); // Monday
expect(countWorkingDays(day, day, stdAvailability)).toBe(1);
});
});
describe("calculateAllocation", () => {
it("calculates cost for a full week at 8h/day and 100 EUR/h (10000 cents)", () => {
const result = calculateAllocation({
lcrCents: 10000, // 100 EUR/h
hoursPerDay: 8,
startDate: new Date("2025-01-06"), // Monday
endDate: new Date("2025-01-10"), // Friday
availability: stdAvailability,
});
expect(result.workingDays).toBe(5);
expect(result.totalHours).toBe(40);
// 5 days × 8h × 10000 cents/h = 400000 cents = 4000 EUR
expect(result.totalCostCents).toBe(400000);
expect(result.dailyCostCents).toBe(80000);
expect(result.dailyBreakdown).toHaveLength(5);
});
it("skips weekend days in breakdown", () => {
const result = calculateAllocation({
lcrCents: 10000,
hoursPerDay: 8,
startDate: new Date("2025-01-04"), // Saturday
endDate: new Date("2025-01-12"), // Sunday
availability: stdAvailability,
});
expect(result.workingDays).toBe(5);
const weekendDays = result.dailyBreakdown.filter((d) => !d.isWorkday);
expect(weekendDays).toHaveLength(4); // 2 weekends
});
it("caps hours at available hours if requested > available", () => {
const limitedAvailability = { ...stdAvailability, monday: 4 };
const result = calculateAllocation({
lcrCents: 10000,
hoursPerDay: 8, // Requested more than available
startDate: new Date("2025-01-06"), // Monday only
endDate: new Date("2025-01-06"),
availability: limitedAvailability,
});
expect(result.totalHours).toBe(4); // Capped at availability
expect(result.totalCostCents).toBe(40000); // 4h × 10000 cents
});
it("returns zero for date range with no working days", () => {
const result = calculateAllocation({
lcrCents: 10000,
hoursPerDay: 8,
startDate: new Date("2025-01-04"), // Saturday
endDate: new Date("2025-01-05"), // Sunday
availability: stdAvailability,
});
expect(result.workingDays).toBe(0);
expect(result.totalHours).toBe(0);
expect(result.totalCostCents).toBe(0);
});
});
describe("calculateTotalCost", () => {
it("calculates correctly", () => {
// 10000 cents/h × 8h × 5 days = 400000 cents
expect(calculateTotalCost(10000, 8, 5)).toBe(400000);
});
it("returns 0 for 0 working days", () => {
expect(calculateTotalCost(10000, 8, 0)).toBe(0);
});
});