66 lines
3.2 KiB
TypeScript
66 lines
3.2 KiB
TypeScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { calculateBucketUsage } from "../lib/shared/bucket-usage";
|
|
|
|
const today = "2026-02-11";
|
|
|
|
test("calculateBucketUsage matches tag subset", () => {
|
|
const bucket = { tags: ["groceries", "weekly"], necessity: "BOTH", windowDays: 30 };
|
|
const entries = [
|
|
{ amountDollars: 20, occurredAt: "2026-02-10", necessity: "NECESSARY", tags: ["groceries", "weekly", "extra"], isRecurring: false, entryType: "SPENDING" as const },
|
|
{ amountDollars: 15, occurredAt: "2026-02-10", necessity: "NECESSARY", tags: ["groceries"], isRecurring: false, entryType: "SPENDING" as const }
|
|
];
|
|
|
|
const result = calculateBucketUsage(bucket, entries, today);
|
|
assert.equal(result.totalUsage, 20);
|
|
assert.equal(result.matchedCount, 1);
|
|
});
|
|
|
|
test("calculateBucketUsage excludes recurring entries", () => {
|
|
const bucket = { tags: ["rent"], necessity: "BOTH", windowDays: 30 };
|
|
const entries = [
|
|
{ amountDollars: 500, occurredAt: "2026-02-10", necessity: "NECESSARY", tags: ["rent"], isRecurring: true, entryType: "SPENDING" as const }
|
|
];
|
|
|
|
const result = calculateBucketUsage(bucket, entries, today);
|
|
assert.equal(result.totalUsage, 0);
|
|
assert.equal(result.matchedCount, 0);
|
|
});
|
|
|
|
test("calculateBucketUsage applies windowDays filtering", () => {
|
|
const bucket = { tags: [], necessity: "BOTH", windowDays: 3 };
|
|
const entries = [
|
|
{ amountDollars: 10, occurredAt: "2026-02-11", necessity: "NECESSARY", tags: [], isRecurring: false, entryType: "SPENDING" as const },
|
|
{ amountDollars: 10, occurredAt: "2026-02-09", necessity: "NECESSARY", tags: [], isRecurring: false, entryType: "SPENDING" as const },
|
|
{ amountDollars: 10, occurredAt: "2026-02-08", necessity: "NECESSARY", tags: [], isRecurring: false, entryType: "SPENDING" as const }
|
|
];
|
|
|
|
const result = calculateBucketUsage(bucket, entries, today);
|
|
assert.equal(result.totalUsage, 20);
|
|
assert.equal(result.matchedCount, 2);
|
|
});
|
|
|
|
test("calculateBucketUsage accepts all when bucket necessity is BOTH", () => {
|
|
const bucket = { tags: [], necessity: "BOTH", windowDays: 30 };
|
|
const entries = [
|
|
{ amountDollars: 12, occurredAt: "2026-02-10", necessity: "NECESSARY", tags: [], isRecurring: false, entryType: "SPENDING" as const },
|
|
{ amountDollars: 8, occurredAt: "2026-02-10", necessity: "UNNECESSARY", tags: [], isRecurring: false, entryType: "SPENDING" as const }
|
|
];
|
|
|
|
const result = calculateBucketUsage(bucket, entries, today);
|
|
assert.equal(result.totalUsage, 20);
|
|
assert.equal(result.matchedCount, 2);
|
|
});
|
|
|
|
test("calculateBucketUsage halves BOTH entries when bucket not BOTH", () => {
|
|
const bucket = { tags: [], necessity: "NECESSARY", windowDays: 30 };
|
|
const entries = [
|
|
{ amountDollars: 10, occurredAt: "2026-02-10", necessity: "BOTH", tags: [], isRecurring: false, entryType: "SPENDING" as const },
|
|
{ amountDollars: 10, occurredAt: "2026-02-10", necessity: "UNNECESSARY", tags: [], isRecurring: false, entryType: "SPENDING" as const }
|
|
];
|
|
|
|
const result = calculateBucketUsage(bucket, entries, today);
|
|
assert.equal(result.totalUsage, 5);
|
|
assert.equal(result.matchedCount, 1);
|
|
});
|