cd78f72f33
Complete rename of all technical identifiers across the codebase: Package names (11 packages): - @planarchy/* → @capakraken/* in all package.json, tsconfig, imports Import statements: 277 files, 548 occurrences replaced Database & Docker: - PostgreSQL user/db: planarchy → capakraken - Docker volumes: planarchy_pgdata → capakraken_pgdata - Connection strings updated in docker-compose, .env, CI CI/CD: - GitHub Actions workflow: all filter commands updated - Test database credentials updated Infrastructure: - Redis channel: planarchy:sse → capakraken:sse - Logger service name: planarchy-api → capakraken-api - Anonymization seed updated - Start/stop/restart scripts updated Test data: - Seed emails: @planarchy.dev → @capakraken.dev - E2E test credentials: all 11 spec files updated - Email defaults: @planarchy.app → @capakraken.app - localStorage keys: planarchy_* → capakraken_* Documentation: 30+ .md files updated Verification: - pnpm install: workspace resolution works - TypeScript: only pre-existing TS2589 (no new errors) - Engine: 310/310 tests pass - Staffing: 37/37 tests pass Co-Authored-By: claude-flow <ruv@ruv.net>
138 lines
4.6 KiB
TypeScript
138 lines
4.6 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { isRecurringDay, getRecurringHoursForDay } from "../allocation/recurrence.js";
|
|
import { RecurrenceFrequency } from "@capakraken/shared";
|
|
import type { RecurrencePattern } from "@capakraken/shared";
|
|
|
|
const monday = new Date("2026-03-09"); // Monday
|
|
const tuesday = new Date("2026-03-10"); // Tuesday
|
|
const wednesday = new Date("2026-03-11"); // Wednesday
|
|
const friday = new Date("2026-03-13"); // Friday
|
|
const nextMonday = new Date("2026-03-16"); // Monday (next week)
|
|
const twoWeeksMonday = new Date("2026-03-23"); // Monday (two weeks after)
|
|
|
|
const allocationStart = new Date("2026-03-09"); // Monday
|
|
|
|
describe("isRecurringDay", () => {
|
|
describe("WEEKLY", () => {
|
|
const pattern: RecurrencePattern = {
|
|
frequency: RecurrenceFrequency.WEEKLY,
|
|
weekdays: [1, 3, 5], // Mon, Wed, Fri
|
|
};
|
|
|
|
it("returns true for days matching weekday list", () => {
|
|
expect(isRecurringDay(monday, pattern, allocationStart)).toBe(true);
|
|
expect(isRecurringDay(wednesday, pattern, allocationStart)).toBe(true);
|
|
expect(isRecurringDay(friday, pattern, allocationStart)).toBe(true);
|
|
});
|
|
|
|
it("returns false for days not in weekday list", () => {
|
|
expect(isRecurringDay(tuesday, pattern, allocationStart)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("BIWEEKLY", () => {
|
|
const pattern: RecurrencePattern = {
|
|
frequency: RecurrenceFrequency.BIWEEKLY,
|
|
weekdays: [1], // Monday only
|
|
interval: 2,
|
|
};
|
|
|
|
it("returns true on the allocation start week (week 0)", () => {
|
|
expect(isRecurringDay(monday, pattern, allocationStart)).toBe(true);
|
|
});
|
|
|
|
it("returns false on the next week (week 1, odd)", () => {
|
|
expect(isRecurringDay(nextMonday, pattern, allocationStart)).toBe(false);
|
|
});
|
|
|
|
it("returns true two weeks after start (week 2, even)", () => {
|
|
expect(isRecurringDay(twoWeeksMonday, pattern, allocationStart)).toBe(true);
|
|
});
|
|
|
|
it("returns false for non-matching weekdays even in active weeks", () => {
|
|
expect(isRecurringDay(tuesday, pattern, allocationStart)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("MONTHLY", () => {
|
|
const pattern: RecurrencePattern = {
|
|
frequency: RecurrenceFrequency.MONTHLY,
|
|
monthDay: 15,
|
|
};
|
|
|
|
it("returns true on the specified day of month", () => {
|
|
expect(isRecurringDay(new Date("2026-03-15"), pattern, allocationStart)).toBe(true);
|
|
});
|
|
|
|
it("returns false on other days", () => {
|
|
expect(isRecurringDay(new Date("2026-03-14"), pattern, allocationStart)).toBe(false);
|
|
});
|
|
|
|
it("returns false when monthDay is undefined", () => {
|
|
const noDay: RecurrencePattern = {
|
|
frequency: RecurrenceFrequency.MONTHLY,
|
|
};
|
|
expect(isRecurringDay(new Date("2026-03-15"), noDay, allocationStart)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("CUSTOM", () => {
|
|
const pattern: RecurrencePattern = {
|
|
frequency: RecurrenceFrequency.CUSTOM,
|
|
};
|
|
|
|
it("always returns true", () => {
|
|
expect(isRecurringDay(monday, pattern, allocationStart)).toBe(true);
|
|
expect(isRecurringDay(tuesday, pattern, allocationStart)).toBe(true);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("getRecurringHoursForDay", () => {
|
|
const weeklyPattern: RecurrencePattern = {
|
|
frequency: RecurrenceFrequency.WEEKLY,
|
|
weekdays: [1, 3, 5], // Mon, Wed, Fri
|
|
};
|
|
|
|
it("returns default hours on recurring days", () => {
|
|
expect(getRecurringHoursForDay(monday, weeklyPattern, 8, allocationStart)).toBe(8);
|
|
});
|
|
|
|
it("returns 0 on non-recurring days", () => {
|
|
expect(getRecurringHoursForDay(tuesday, weeklyPattern, 8, allocationStart)).toBe(0);
|
|
});
|
|
|
|
it("uses pattern.hoursPerDay when set", () => {
|
|
const patternWithHours: RecurrencePattern = {
|
|
...weeklyPattern,
|
|
hoursPerDay: 4,
|
|
};
|
|
expect(getRecurringHoursForDay(monday, patternWithHours, 8, allocationStart)).toBe(4);
|
|
});
|
|
|
|
it("returns 0 before pattern startDate", () => {
|
|
const patternWithStart: RecurrencePattern = {
|
|
...weeklyPattern,
|
|
startDate: new Date("2026-03-16"),
|
|
};
|
|
expect(getRecurringHoursForDay(monday, patternWithStart, 8, allocationStart)).toBe(0);
|
|
});
|
|
|
|
it("returns 0 after pattern endDate", () => {
|
|
const patternWithEnd: RecurrencePattern = {
|
|
...weeklyPattern,
|
|
endDate: new Date("2026-03-08"),
|
|
};
|
|
expect(getRecurringHoursForDay(monday, patternWithEnd, 8, allocationStart)).toBe(0);
|
|
});
|
|
|
|
it("returns hours within pattern date bounds", () => {
|
|
const bounded: RecurrencePattern = {
|
|
...weeklyPattern,
|
|
startDate: new Date("2026-03-01"),
|
|
endDate: new Date("2026-03-31"),
|
|
};
|
|
expect(getRecurringHoursForDay(monday, bounded, 8, allocationStart)).toBe(8);
|
|
});
|
|
});
|