splitwise / tests /integration /ledger.test.ts
assafvayner's picture
assafvayner HF Staff
test(ledger): prove compaction crash safety with fault injection and against the real bucket
8d2f1b6
Raw History Blame Contribute Delete
1.75 kB
import { afterAll, describe, expect, it } from 'vitest';
import type { ExpenseBody } from '../../src/lib/domain/types';
import { ulid } from '../../src/lib/domain/ulid';
import { Ledger } from '../../src/lib/server/ledger/ledger';
import { HfBucketStore } from '../../src/lib/server/storage/hf-bucket-store';
import { PrefixedStore } from '../../src/lib/server/storage/prefixed-store';
import { realBucket } from './env';
const creds = realBucket();
const body = (description: string): ExpenseBody => ({
description, amountCents: 300, currency: 'USD', date: '2026-08-01', paidBy: 'u_a',
split: { mode: 'equal', participants: ['u_a', 'u_b', 'u_c'] }, shares: { u_a: 100, u_b: 100, u_c: 100 }
});
describe.skipIf(!creds)(
'Ledger against the real bucket',
() => {
const store = creds
? new PrefixedStore(new HfBucketStore(creds.bucket, creds.token), `test/${ulid()}`)
: (undefined as unknown as PrefixedStore);
afterAll(() => store.wipe(), 60_000);
it('writes events, compacts twice (append path), and reloads identically', async () => {
const ledger = await Ledger.load(store);
await ledger.createExpense('u_a', body('one'));
await ledger.createExpense('u_a', body('two'));
expect(await ledger.compact()).toMatchObject({ appended: 2, deleted: 2 });
await ledger.createExpense('u_a', body('three'));
expect(await ledger.compact()).toMatchObject({ appended: 1, deleted: 1, backedUp: true });
expect(await store.list('events/')).toEqual([]);
const reloaded = await Ledger.load(store);
expect(reloaded.listExpenses().map((e) => e.description).sort()).toEqual(['one', 'three', 'two']);
expect(reloaded.stats()).toEqual({ pendingEvents: 0, ledgerEvents: 3, ledgerExists: true });
});
},
120_000
);