import { describe, it, expect, vi, beforeEach } from 'vitest' // Tests load the module after setting environment and mocks, so reset modules beforeEach(() => { vi.resetModules() delete process.env.LOCAL_DATABASE_URL }) describe('persistence (pool mode)', () => { it('getCodeById / insertCode / updateCode via Pool', async () => { // Mock pg Pool implementation const queryMock = vi.fn() const PoolMock = vi.fn().mockImplementation(() => ({ query: queryMock })) // Use doMock to avoid hoisting issues vi.doMock('pg', () => ({ Pool: PoolMock })) // Set env to trigger pool usage process.env.LOCAL_DATABASE_URL = 'postgres://dev:pass@localhost:5432/letschat' // Import persistence after mocks const persistence = await import('./persistence') // Setup query responses queryMock.mockResolvedValueOnce({ rows: [{ id: 'code-1', code: 'ABCDE' }] }) // getCodeById const got = await persistence.getCodeById('code-1') expect(got).toMatchObject({ id: 'code-1', code: 'ABCDE' }) queryMock.mockResolvedValueOnce({ rows: [{ id: 'code-new', code: 'NEW01' }] }) // insertCode const ins = await persistence.insertCode({ code: 'NEW01' } as any) expect(ins).toMatchObject({ id: 'code-new', code: 'NEW01' }) queryMock.mockResolvedValueOnce({ rows: [{ id: 'code-1', used_count: 5 }] }) // updateCode const upd = await persistence.updateCode('code-1', { used_count: 5 } as any) expect(upd).toMatchObject({ id: 'code-1', used_count: 5 }) }) it('updateCodesRoomId and syncLocalToSupabase', async () => { const queryMock = vi.fn() const PoolMock = vi.fn().mockImplementation(() => ({ query: queryMock })) vi.doMock('pg', () => ({ Pool: PoolMock })) // Mock supabase client const upsertMock = vi.fn().mockResolvedValue({ data: {}, error: null }) const fromMock = vi.fn().mockReturnValue({ upsert: () => ({ select: () => ({ single: upsertMock }) }) }) vi.doMock('lib/supabase/server', () => ({ createServerClient: async () => ({ from: fromMock }) })) process.env.LOCAL_DATABASE_URL = 'postgres://dev:pass@localhost:5432/letschat' process.env.SUPABASE_URL = 'http://localhost:54321' process.env.SUPABASE_SERVICE_ROLE_KEY = 'service-role-key' const persistence = await import('./persistence') // updateCodesRoomId queryMock.mockResolvedValueOnce({ rows: [{ id: 'c1', room_id: 'r1' }, { id: 'c2', room_id: 'r1' }] }) const res = await persistence.updateCodesRoomId(['c1', 'c2'], 'r1') expect(res.length).toBe(2) // syncLocalToSupabase: pool will return rooms and codes queryMock.mockResolvedValueOnce({ rows: [{ id: 'r1' }] }) // rooms queryMock.mockResolvedValueOnce({ rows: [{ id: 'c1' }, { id: 'c2' }] }) // codes queryMock.mockResolvedValueOnce({ rows: [{ id: 'm1' }] }) // room_messages const syncRes = await persistence.syncLocalToSupabase() expect(syncRes).toHaveProperty('synced') }) it('getRoomsForUser aggregates codes per room (pool)', async () => { const queryMock = vi.fn() const PoolMock = vi.fn().mockImplementation(() => ({ query: queryMock })) vi.doMock('pg', () => ({ Pool: PoolMock })) process.env.LOCAL_DATABASE_URL = 'postgres://dev:pass@localhost:5432/letschat' const persistence = await import('./persistence') queryMock.mockResolvedValueOnce({ rows: [ { id: 'r1', name: 'Room 1', description: null, status: 1, date_created: '2025-01-01', message_count: 2, code_id: 'c1', code: 'AAAAA', room_id: 'r1' }, { id: 'r1', name: 'Room 1', description: null, status: 1, date_created: '2025-01-01', message_count: 2, code_id: 'c2', code: 'BBBBB', room_id: 'r1' } ] }) const rooms = await persistence.getRoomsForUser('user-1') expect(rooms.length).toBe(1) expect(rooms[0].codes.length).toBe(2) expect(rooms[0].id).toBe('r1') }) })