jest.mock('../../src/database', () => { const tx = { __tx: true }; const prisma = { $transaction: jest.fn(async (fn: (tx: unknown) => Promise) => fn(tx)), }; return { prisma }; }); import { prisma } from '../../src/database'; import { transaction, withTransaction } from '../../src/core/db'; describe('core/db transaction helpers', () => { beforeEach(() => { (prisma.$transaction as jest.Mock).mockClear(); }); test('transaction() executes callback via prisma.$transaction', async () => { const result = await transaction(async (_tx) => { return 123; }); expect(result).toBe(123); expect(prisma.$transaction).toHaveBeenCalledTimes(1); }); test('transaction() propagates error (rollback is handled by Prisma)', async () => { await expect( transaction(async () => { throw new Error('boom'); }), ).rejects.toThrow('boom'); expect(prisma.$transaction).toHaveBeenCalledTimes(1); }); test('withTransaction() starts a new transaction for root client', async () => { const rootClient = prisma as unknown as { $transaction: (fn: any) => Promise }; const result = await withTransaction(rootClient as any, async (_tx) => 'ok'); expect(result).toBe('ok'); expect(prisma.$transaction).toHaveBeenCalledTimes(1); }); test('withTransaction() reuses existing tx client (does not nest)', async () => { const txClient = {} as any; // does not have $transaction const result = await withTransaction(txClient, async (_tx) => 'ok'); expect(result).toBe('ok'); expect(prisma.$transaction).toHaveBeenCalledTimes(0); }); });