Files
optima/tests/unit/algoColdThreshold.test.ts
T

130 lines
4.1 KiB
TypeScript

/**
* Tests for src/modules/algorithms/algo.coldThreshold.ts
*
* Pure function — no mocking needed.
*/
import { describe, test, expect } from "bun:test";
import {
checkColdStatus,
COLD_THRESHOLDS,
} from "../../src/modules/algorithms/algo.coldThreshold";
describe("COLD_THRESHOLDS", () => {
test("defines thresholds for QuoteSent (43) and ConfirmedQuote (57)", () => {
expect(COLD_THRESHOLDS[43]).toBeDefined();
expect(COLD_THRESHOLDS[43].days).toBe(14);
expect(COLD_THRESHOLDS[57]).toBeDefined();
expect(COLD_THRESHOLDS[57].days).toBe(30);
});
test("ms values match day values", () => {
expect(COLD_THRESHOLDS[43].ms).toBe(14 * 24 * 60 * 60 * 1000);
expect(COLD_THRESHOLDS[57].ms).toBe(30 * 24 * 60 * 60 * 1000);
});
});
describe("checkColdStatus", () => {
test("returns not cold when statusCwId is null", () => {
const result = checkColdStatus({
statusCwId: null,
lastActivityDate: new Date(),
});
expect(result.cold).toBe(false);
expect(result.triggeredBy).toBeNull();
});
test("returns not cold for non-eligible status", () => {
const result = checkColdStatus({
statusCwId: 24, // New — not in threshold table
lastActivityDate: new Date("2020-01-01"),
now: new Date("2026-06-01"),
});
expect(result.cold).toBe(false);
});
test("returns not cold when lastActivityDate is null", () => {
const result = checkColdStatus({
statusCwId: 43, // QuoteSent
lastActivityDate: null,
});
expect(result.cold).toBe(false);
});
test("returns not cold when within threshold (QuoteSent, 13 days)", () => {
const now = new Date("2026-03-14T00:00:00Z");
const lastActivity = new Date("2026-03-01T00:00:00Z"); // 13 days ago
const result = checkColdStatus({
statusCwId: 43,
lastActivityDate: lastActivity,
now,
});
expect(result.cold).toBe(false);
});
test("returns cold when QuoteSent exceeds 14 days", () => {
const now = new Date("2026-03-16T00:00:00Z");
const lastActivity = new Date("2026-03-01T00:00:00Z"); // 15 days ago
const result = checkColdStatus({
statusCwId: 43,
lastActivityDate: lastActivity,
now,
});
expect(result.cold).toBe(true);
expect(result.triggeredBy).not.toBeNull();
expect(result.triggeredBy!.statusCwId).toBe(43);
expect(result.triggeredBy!.statusName).toBe("QuoteSent");
expect(result.triggeredBy!.thresholdDays).toBe(14);
expect(result.triggeredBy!.staleDays).toBe(15);
});
test("returns cold when ConfirmedQuote exceeds 30 days", () => {
const now = new Date("2026-04-01T00:00:00Z");
const lastActivity = new Date("2026-02-28T00:00:00Z"); // 32 days
const result = checkColdStatus({
statusCwId: 57,
lastActivityDate: lastActivity,
now,
});
expect(result.cold).toBe(true);
expect(result.triggeredBy!.statusName).toBe("ConfirmedQuote");
expect(result.triggeredBy!.thresholdDays).toBe(30);
expect(result.triggeredBy!.staleDays).toBeGreaterThanOrEqual(30);
});
test("returns not cold when ConfirmedQuote within 30 days", () => {
const now = new Date("2026-03-20T00:00:00Z");
const lastActivity = new Date("2026-03-01T00:00:00Z"); // 19 days
const result = checkColdStatus({
statusCwId: 57,
lastActivityDate: lastActivity,
now,
});
expect(result.cold).toBe(false);
});
test("exactly at threshold is cold (>= threshold)", () => {
const now = new Date("2026-03-15T00:00:00Z");
const lastActivity = new Date("2026-03-01T00:00:00Z"); // exactly 14 days
const result = checkColdStatus({
statusCwId: 43,
lastActivityDate: lastActivity,
now,
});
expect(result.cold).toBe(true);
expect(result.triggeredBy!.staleDays).toBe(14);
});
test("now override works as expected", () => {
const fixed = new Date("2026-06-01T00:00:00Z");
const lastActivity = new Date("2026-05-01T00:00:00Z"); // 31 days
const result = checkColdStatus({
statusCwId: 57,
lastActivityDate: lastActivity,
now: fixed,
});
expect(result.cold).toBe(true);
expect(result.triggeredBy!.staleDays).toBe(31);
});
});