import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { SqliteAdapter } from './sqlite.js'; describe('SqliteAdapter', () => { let adapter: SqliteAdapter; beforeEach(async () => { adapter = new SqliteAdapter({ type: 'sqlite', path: ':memory:' }); await adapter.migrate(); }); afterEach(async () => { await adapter.close(); }); describe('CRUD', () => { it('creates and reads a record', async () => { const created = await adapter.create('users', { name: 'Alice', email: 'alice@test.com' }); expect(created.id).toBeDefined(); expect(created.name).toBe('Alice'); const read = await adapter.read('users', created.id); expect(read).not.toBeNull(); expect(read!.name).toBe('Alice'); expect(read!.email).toBe('alice@test.com'); }); it('returns null for non-existent record', async () => { const result = await adapter.read('users', 'does-not-exist'); expect(result).toBeNull(); }); it('updates a record', async () => { const created = await adapter.create('users', { name: 'Alice' }); const updated = await adapter.update('users', created.id, { name: 'Bob' }); expect(updated).toBe(true); const read = await adapter.read('users', created.id); expect(read!.name).toBe('Bob'); }); it('update returns false for non-existent record', async () => { const result = await adapter.update('users', 'does-not-exist', { name: 'X' }); expect(result).toBe(false); }); it('deletes a record', async () => { const created = await adapter.create('users', { name: 'Alice' }); const deleted = await adapter.delete('users', created.id); expect(deleted).toBe(true); const read = await adapter.read('users', created.id); expect(read).toBeNull(); }); it('delete returns false for non-existent record', async () => { const result = await adapter.delete('users', 'does-not-exist'); expect(result).toBe(false); }); }); describe('find', () => { it('finds records with filter', async () => { await adapter.create('users', { name: 'Alice', role: 'admin' }); await adapter.create('users', { name: 'Bob', role: 'user' }); await adapter.create('users', { name: 'Charlie', role: 'admin' }); const admins = await adapter.find('users', { role: 'admin' }); expect(admins).toHaveLength(2); expect(admins.map((u) => u.name).sort()).toEqual(['Alice', 'Charlie']); }); it('finds all records without filter', async () => { await adapter.create('users', { name: 'Alice' }); await adapter.create('users', { name: 'Bob' }); const all = await adapter.find('users'); expect(all).toHaveLength(2); }); it('supports limit and offset', async () => { for (let i = 0; i < 5; i++) { await adapter.create('users', { name: `User${i}`, idx: i }); } const page = await adapter.find('users', undefined, { limit: 2, offset: 1, orderBy: 'created_at', }); expect(page).toHaveLength(2); }); it('findOne returns first match', async () => { await adapter.create('users', { name: 'Alice', role: 'admin' }); await adapter.create('users', { name: 'Bob', role: 'user' }); const found = await adapter.findOne('users', { role: 'user' }); expect(found).not.toBeNull(); expect(found!.name).toBe('Bob'); }); it('findOne returns null when no match', async () => { const result = await adapter.findOne('users', { role: 'nonexistent' }); expect(result).toBeNull(); }); }); describe('count', () => { it('counts all records', async () => { await adapter.create('users', { name: 'Alice' }); await adapter.create('users', { name: 'Bob' }); const total = await adapter.count('users'); expect(total).toBe(2); }); it('counts with filter', async () => { await adapter.create('users', { name: 'Alice', role: 'admin' }); await adapter.create('users', { name: 'Bob', role: 'user' }); await adapter.create('users', { name: 'Charlie', role: 'admin' }); const adminCount = await adapter.count('users', { role: 'admin' }); expect(adminCount).toBe(2); }); it('returns 0 for empty collection', async () => { const count = await adapter.count('users'); expect(count).toBe(0); }); }); describe('transaction', () => { it('commits on success', async () => { await adapter.transaction(async (tx) => { await tx.create('users', { name: 'Alice' }); await tx.create('users', { name: 'Bob' }); }); const count = await adapter.count('users'); expect(count).toBe(2); }); it('rolls back on error', async () => { await expect( adapter.transaction(async (tx) => { await tx.create('users', { name: 'Alice' }); throw new Error('rollback test'); }), ).rejects.toThrow('rollback test'); const count = await adapter.count('users'); expect(count).toBe(0); }); }); describe('migrate', () => { it('creates all tables', async () => { // migrate() was already called in beforeEach — verify tables exist const collections = [ 'users', 'sessions', 'accounts', 'projects', 'missions', 'tasks', 'agents', 'conversations', 'messages', 'preferences', 'insights', 'skills', 'events', 'routing_rules', 'provider_credentials', 'agent_logs', 'teams', 'team_members', 'mission_tasks', 'tickets', 'summarization_jobs', 'appreciations', 'verifications', ]; for (const collection of collections) { // Should not throw const count = await adapter.count(collection); expect(count).toBe(0); } }); it('is idempotent', async () => { await adapter.migrate(); await adapter.migrate(); // Should not throw const count = await adapter.count('users'); expect(count).toBe(0); }); }); });