MEGAINFRA-WEBAPP/src/lib/workforce-hours.test.ts

90 lines
No EOL
2.6 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
MS_PER_DAY,
buildWeeklyHours,
buildWeeklyTrend,
startOfIsoWeekUtc,
sumHoursInWindow,
} from "./workforce-hours";
// Wednesday, 2026-09-09 (UTC) — Monday of that week is 2026-09-07.
const NOW = new Date("2026-09-09T12:00:00.000Z");
describe("startOfIsoWeekUtc", () => {
it("anchors to Monday of the current week", () => {
expect(new Date(startOfIsoWeekUtc(NOW)).toISOString().slice(0, 10)).toBe(
"2026-09-07",
);
});
});
describe("sumHoursInWindow", () => {
const list = [
{ date: "2026-09-01", hours: 3 },
{ date: "2026-09-05", hours: 5 },
{ date: "2026-09-10", hours: 8 },
];
it("sums hours within [start, end)", () => {
const start = Date.UTC(2026, 8, 1);
const end = Date.UTC(2026, 8, 6);
expect(sumHoursInWindow(list, start, end)).toBe(8);
});
it("excludes the end boundary", () => {
const start = Date.UTC(2026, 8, 5);
const end = Date.UTC(2026, 8, 5);
expect(sumHoursInWindow(list, start, end)).toBe(0);
});
it("ignores unparseable dates instead of throwing", () => {
const bad = [{ date: "not-a-date", hours: 99 }];
expect(sumHoursInWindow(bad, 0, Date.UTC(2030, 0, 1))).toBe(0);
});
});
describe("buildWeeklyTrend", () => {
it("buckets hours into the correct week, oldest first", () => {
const timesheets = [
{ date: "2026-09-07", hours: 10 }, // this week (Mon)
{ date: "2026-08-31", hours: 4 }, // last week (Mon)
];
const trend = buildWeeklyTrend(timesheets, NOW, 2);
expect(trend).toHaveLength(2);
expect(trend[0].weekStart).toBe("2026-08-31");
expect(trend[0].hours).toBe(4);
expect(trend[1].weekStart).toBe("2026-09-07");
expect(trend[1].hours).toBe(10);
});
it("returns all-zero buckets when there are no timesheets", () => {
const trend = buildWeeklyTrend([], NOW, 3);
expect(trend.every((b) => b.hours === 0)).toBe(true);
});
});
describe("buildWeeklyHours", () => {
it("builds a per-employee weekly array, oldest first", () => {
const map = new Map([
[
"emp1",
[
{ date: "2026-09-07", hours: 6 },
{ date: "2026-08-31", hours: 2 },
],
],
]);
const result = buildWeeklyHours(map, NOW, 2);
expect(result.get("emp1")).toEqual([2, 6]);
});
it("defaults to zeros for an employee with no entries in range", () => {
const map = new Map([["emp1", []]]);
const result = buildWeeklyHours(map, NOW, 2);
expect(result.get("emp1")).toEqual([0, 0]);
});
});
it("exports the day-in-ms constant", () => {
expect(MS_PER_DAY).toBe(86_400_000);
});