import { AllocationStatus } from "@capakraken/shared"; import { describe, expect, it } from "vitest"; import { findCapacityWindows, analyzeUtilization } from "../capacity-analyzer.js"; import type { CapacityAnalysisInput } from "../capacity-analyzer.js"; const standardAvailability = { sunday: 0, monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8, saturday: 0, }; /** * Performance regression test. * 50 resources × 20 allocations × 365 days must complete in under 500 ms. */ describe("capacity-analyzer performance", () => { it("analyzeUtilization: 50 resources × 20 allocations × 365 days < 500 ms", () => { const analysisStart = new Date("2026-01-01"); const analysisEnd = new Date("2026-12-31"); const periodMs = analysisEnd.getTime() - analysisStart.getTime(); const resources: CapacityAnalysisInput[] = Array.from({ length: 50 }, (_, ri) => { const allocations = Array.from({ length: 20 }, (_, ai) => { // Distribute allocations pseudo-randomly across the year const offset = Math.floor(((ri * 20 + ai) / 1000) * periodMs); const start = new Date(analysisStart.getTime() + offset); const end = new Date(start.getTime() + 30 * 24 * 60 * 60 * 1000); // 30-day blocks return { startDate: start > analysisEnd ? analysisStart : start, endDate: end > analysisEnd ? analysisEnd : end, hoursPerDay: 4, status: AllocationStatus.CONFIRMED, projectName: `Project-${ri}-${ai}`, isChargeable: ai % 2 === 0, }; }); return { resource: { id: `res-${ri}`, displayName: `Resource ${ri}`, chargeabilityTarget: 80, availability: standardAvailability, }, allocations, analysisStart, analysisEnd, }; }); const t0 = performance.now(); for (const input of resources) { analyzeUtilization(input); } const elapsed = performance.now() - t0; expect(elapsed).toBeLessThan(500); }); it("findCapacityWindows: 50 resources × 20 allocations × 365 days < 500 ms", () => { const searchStart = new Date("2026-01-01"); const searchEnd = new Date("2026-12-31"); const periodMs = searchEnd.getTime() - searchStart.getTime(); const simpleResource = { id: "res-perf", displayName: "Perf Resource", availability: standardAvailability, }; const t0 = performance.now(); for (let ri = 0; ri < 50; ri++) { const allocations = Array.from({ length: 20 }, (_, ai) => { const offset = Math.floor(((ri * 20 + ai) / 1000) * periodMs); const start = new Date(searchStart.getTime() + offset); const end = new Date(start.getTime() + 30 * 24 * 60 * 60 * 1000); return { startDate: start > searchEnd ? searchStart : start, endDate: end > searchEnd ? searchEnd : end, hoursPerDay: 4, status: AllocationStatus.CONFIRMED, }; }); findCapacityWindows(simpleResource, allocations, searchStart, searchEnd); } const elapsed = performance.now() - t0; expect(elapsed).toBeLessThan(500); }); });