duly / test/agent.test.mjs · raw
import test from 'node:test';import assert from 'node:assert/strict';import { decide, reminderText } from '../worker/src/agent.js';const DAY = 86_400_000;const now = 1_800_000_000_000;const rules = { days: 3, bps: 500, hours: 72 };const inv = (o = {}) => ({ status: 'overdue', number: 4, due_at_ms: String(now - 5 * DAY), discount_bps: 0, discount_until_ms: '0', due_now: '100000000', ...o });test('acts on an invoice overdue past the merchant\'s threshold', () => {  assert.deepEqual(decide(inv(), rules, now, 200), { bps: 200, until: now + 72 * 3_600_000 });});test('the on-chain cap beats a looser off-chain rule', () => {  assert.equal(decide(inv(), rules, now, 200).bps, 200);  assert.equal(decide(inv(), { ...rules, bps: 100 }, now, 200).bps, 100);  assert.equal(decide(inv(), rules, now, 0).bps, 0);});test('leaves invoices alone when it should', () => {  for (const status of ['open', 'paid', 'cancelled', 'refunded', 'partially_refunded']) {    assert.equal(decide(inv({ status }), rules, now, 200), null, status);  }  assert.equal(decide(inv({ due_at_ms: String(now - 2 * DAY) }), rules, now, 200), null);});test('does not stack a second offer on a live one', () => {  assert.equal(decide(inv({ discount_bps: 200, discount_until_ms: String(now + DAY) }), rules, now, 200), null);  assert.ok(decide(inv({ discount_bps: 200, discount_until_ms: String(now - DAY) }), rules, now, 200));});test('a reminder states the amount and only mentions an offer that was made', () => {  const made = reminderText(inv(), { bps: 200, until: now }, 'https://x/i/1-4');  assert.match(made, /\$100\.00/);  assert.match(made, /2% off/);  assert.doesNotMatch(reminderText(inv(), { bps: 0, until: now }, 'https://x/i/1-4'), /off if/);});test('every sponsored or agent call carries the gas the contract demands for a payout', async () => {  const { readFileSync } = await import('node:fs');  const { SWEEP_TGAS } = await import('../worker/src/agent.js');  const { METHODS } = await import('../worker/src/policy.js');  const src = readFileSync(new URL('../contract/src/lib.rs', import.meta.url), 'utf8');  const tgas = (name) => BigInt(src.match(new RegExp(`const ${name}: Gas = Gas::from_tgas\\((\\d+)\\)`))[1]);  const overhead = tgas('GAS_CALLBACK') + tgas('GAS_OVERHEAD');  assert.ok(SWEEP_TGAS >= tgas('GAS_FT_TRANSFER') + overhead, 'agent_sweep');  const needed = (tgas('GAS_FT_TRANSFER_CALL') + overhead) * 1_000_000_000_000n;  assert.ok(METHODS.withdraw.gas >= needed, 'withdraw through Intents');  assert.ok(METHODS.refund.gas >= needed, 'refund through Intents');});