← back to AbramsOS
tests/reminder-engine.test.js
69 lines
const test = require('node:test');
const assert = require('node:assert');
require('dotenv').config();
const db = require('../lib/db');
const engine = require('../lib/reminder-engine');
const TEST_USER_ID = 'user_steve';
test.before(async () => {
// Wipe any reminders the engine might recreate, but keep purchases.
await db.query(`DELETE FROM calendar_reminder WHERE user_id = $1`, [TEST_USER_ID]);
});
test.after(async () => {
await db.query(`DELETE FROM calendar_reminder WHERE user_id = $1`, [TEST_USER_ID]);
// Drop the synthetic purchase we insert below
await db.query(`DELETE FROM purchase WHERE merchant_name = 'TEST_REMINDER_FIXTURE'`);
await db.pool.end();
});
test('warranty_expiry reminder fires for purchase ~340 days old (≈25d before 1y mark)', async () => {
const purchaseDate = new Date(Date.now() - 340 * 86400e3); // 340 days ago → warranty expires ~25d from now
await db.query(
`INSERT INTO purchase (id, user_id, merchant_name, purchase_date, total_amount, currency, confidence)
VALUES ('test_pur_warranty', $1, 'TEST_REMINDER_FIXTURE', $2, 100, 'USD', 0.9)
ON CONFLICT (id) DO UPDATE SET purchase_date = EXCLUDED.purchase_date`,
[TEST_USER_ID, purchaseDate]
);
const inserted = await engine.generateForUser(TEST_USER_ID);
assert.ok(inserted >= 1, `should insert at least one reminder (got ${inserted})`);
const r = await db.query(
`SELECT reason_code FROM calendar_reminder WHERE owner_id = 'test_pur_warranty'`
);
const codes = r.rows.map(x => x.reason_code);
assert.ok(codes.includes('warranty_expiry'), `expected warranty_expiry in [${codes.join(',')}]`);
});
test('returns_window_closing fires for purchase ~25d old (≈5d before 30d mark)', async () => {
const purchaseDate = new Date(Date.now() - 25 * 86400e3);
await db.query(
`INSERT INTO purchase (id, user_id, merchant_name, purchase_date, total_amount, currency, confidence)
VALUES ('test_pur_returns', $1, 'TEST_REMINDER_FIXTURE', $2, 100, 'USD', 0.9)
ON CONFLICT (id) DO UPDATE SET purchase_date = EXCLUDED.purchase_date`,
[TEST_USER_ID, purchaseDate]
);
await engine.generateForUser(TEST_USER_ID);
const r = await db.query(
`SELECT reason_code FROM calendar_reminder WHERE owner_id = 'test_pur_returns'`
);
assert.ok(r.rows.some(x => x.reason_code === 'returns_window_closing'));
});
test('engine is idempotent (re-runs do not duplicate)', async () => {
const before = await db.query(`SELECT count(*)::int AS n FROM calendar_reminder WHERE user_id = $1`, [TEST_USER_ID]);
await engine.generateForUser(TEST_USER_ID);
await engine.generateForUser(TEST_USER_ID);
const after = await db.query(`SELECT count(*)::int AS n FROM calendar_reminder WHERE user_id = $1`, [TEST_USER_ID]);
assert.strictEqual(after.rows[0].n, before.rows[0].n, 'duplicate runs should be no-ops');
});
test('upcomingForUser returns pending reminders ordered by due_at', async () => {
const rows = await engine.upcomingForUser(TEST_USER_ID, { days: 400 });
assert.ok(rows.length >= 2, `expected ≥2 pending (got ${rows.length})`);
for (let i = 1; i < rows.length; i++) {
assert.ok(new Date(rows[i].due_at) >= new Date(rows[i-1].due_at), 'order ASC');
}
});