Six site improvements picked from a "what could be better" review, plus a Jest test suite covering the two areas with the trickiest money-handling history in this project (early-bird pricing tranches, donation-leg accounting): - "Add to calendar" .ics download on event pages and in confirmation emails - sitemap.xml, robots.txt, and Open Graph/Twitter metadata for public pages - Sentry error monitoring (backend + frontend), a no-op until SENTRY_DSN is set - Nightly local pg_dump backups with a Site Settings tab to browse/trigger/download - Admin audit trail for refunds, donations, manual registrations, event and settings changes, and staff-initiated cancellations - Jest tests reproducing and guarding against the 1.8.0 tranche-pricing bug and the 1.4.2 donation-balance-inflation bug Wallet passes (Google/Apple) were scoped out of this round — Apple Wallet needs a paid Apple Developer account the project doesn't have yet, and the user preferred shipping both together later rather than Google alone now. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
47 lines
2.2 KiB
JavaScript
47 lines
2.2 KiB
JavaScript
const { computeDonationRemaining } = require('../src/utils/donationUtils');
|
|
|
|
describe('computeDonationRemaining', () => {
|
|
test('a donation with no legs has its full amount remaining', () => {
|
|
expect(computeDonationRemaining(500, [])).toBe(500);
|
|
});
|
|
|
|
test('an allocation leg reduces the remaining balance', () => {
|
|
const legs = [{ amount: 200 }];
|
|
expect(computeDonationRemaining(500, legs)).toBe(300);
|
|
});
|
|
|
|
test('multiple allocation legs reduce the remaining balance cumulatively', () => {
|
|
const legs = [{ amount: 200 }, { amount: 150 }];
|
|
expect(computeDonationRemaining(500, legs)).toBe(150);
|
|
});
|
|
|
|
test('the 1.4.2 regression: refunding the donation itself (a negative-amount leg) reduces remaining balance, not inflates it', () => {
|
|
// 500 donation, never allocated, R200 of it refunded directly back to the donor
|
|
// (a leg with amount: -200). That R200 is no longer available to allocate — remaining
|
|
// must drop to 300. The pre-1.4.2 bug summed legs without Math.abs(), so
|
|
// remaining = 500 - (-200) = 700 (inflated) instead of 500 - 200 = 300 (correct).
|
|
const legs = [{ amount: -200 }];
|
|
expect(computeDonationRemaining(500, legs)).toBe(300);
|
|
});
|
|
|
|
test('an allocation and a separate direct refund both reduce the remaining balance', () => {
|
|
// 500 donation: R200 allocated to a registration, R100 separately refunded to the donor.
|
|
// Remaining = 500 - 200 - 100 = 200.
|
|
const legs = [{ amount: 200 }, { amount: -100 }];
|
|
expect(computeDonationRemaining(500, legs)).toBe(200);
|
|
});
|
|
|
|
test('unassigning an allocation removes its leg entirely rather than adding an offsetting one', () => {
|
|
// unassignDonationFromRegistration deletes the leg row outright (confirmed in
|
|
// paymentController.js), so the "leg no longer exists" case — not a negative-amount
|
|
// leg — is how an unassigned allocation becomes available again.
|
|
const legsAfterUnassign = [];
|
|
expect(computeDonationRemaining(500, legsAfterUnassign)).toBe(500);
|
|
});
|
|
|
|
test('handles a null/undefined legs array', () => {
|
|
expect(computeDonationRemaining(500, null)).toBe(500);
|
|
expect(computeDonationRemaining(500, undefined)).toBe(500);
|
|
});
|
|
});
|