import { describe, it, expect, vi, beforeEach } from 'vitest'; // Mock postgresClient BEFORE importing the module under test. const queryMock = vi.fn(); vi.mock('./postgres-client', () => ({ postgresClient: { query: (...args: unknown[]) => queryMock(...args), }, })); // eslint-disable-next-line import/first -- imported after vi.mock hoisting import { writeAuditEvent } from './phishing-audit'; describe('writeAuditEvent', () => { beforeEach(() => { queryMock.mockReset(); }); it('issues one parameterized INSERT into audit_events and returns the RETURNING id when no client is passed', async () => { queryMock.mockResolvedValueOnce({ rows: [{ id: 'audit-1' }] }); const id = await writeAuditEvent({ campaignId: 'campaign-1', actor: 'operator@example.com', eventType: 'remediation_approved', payload: { actionType: 'block_sender' }, }); expect(id).toBe('audit-1'); expect(queryMock).toHaveBeenCalledTimes(1); const [sql, params] = queryMock.mock.calls[0]; expect(sql).toContain('INSERT INTO audit_events'); expect(sql).toContain('RETURNING id::text AS id'); expect(params).toEqual([ 'campaign-1', 'operator@example.com', 'remediation_approved', JSON.stringify({ actionType: 'block_sender' }), ]); }); it('routes the query through an explicit client instead of postgresClient when one is supplied', async () => { const clientQueryMock = vi.fn().mockResolvedValueOnce({ rows: [{ id: 'audit-2' }] }); const fakeClient = { query: clientQueryMock }; const id = await writeAuditEvent( { campaignId: 'campaign-2', actor: null, eventType: 'remediation_completed', payload: { actionId: 'action-1' }, }, fakeClient ); expect(id).toBe('audit-2'); expect(clientQueryMock).toHaveBeenCalledTimes(1); expect(queryMock).not.toHaveBeenCalled(); }); });