import { describe, it, expect, beforeEach, afterEach } from 'vitest' import { getDb, setDbPathForTest } from '../../server/utils/db.js' import { getDeviceById, getAllDevices, createDevice, updateDevice, getUserById, getUserByIdentifier, createUser, updateUser, getPoiById, getAllPois, createPoi, updatePoi, getSessionById, createDbSession, deleteSession, } from '../../server/utils/queries.js' describe('queries', () => { let db beforeEach(async () => { setDbPathForTest(':memory:') db = await getDb() }) afterEach(() => { setDbPathForTest(null) }) describe('device queries', () => { it('getDeviceById returns null for non-existent device', async () => { const device = await getDeviceById(db, 'non-existent') expect(device).toBeNull() }) it('createDevice and getDeviceById work together', async () => { const deviceData = { name: 'Test Device', device_type: 'traffic', vendor: 'Test Vendor', lat: 40.7128, lng: -74.0060, stream_url: 'https://example.com/stream', source_type: 'mjpeg', config: null, } const created = await createDevice(db, deviceData) expect(created).toBeDefined() expect(created.name).toBe('Test Device') const retrieved = await getDeviceById(db, created.id) expect(retrieved).toBeDefined() expect(retrieved.name).toBe('Test Device') }) it('createDevice handles vendor null', async () => { const deviceData = { name: 'Test', device_type: 'feed', vendor: null, lat: 40.7128, lng: -74.0060, stream_url: '', source_type: 'mjpeg', config: null, } const created = await createDevice(db, deviceData) expect(created.vendor).toBeNull() }) it('createDevice handles all optional fields', async () => { const deviceData = { name: 'Full Device', device_type: 'traffic', vendor: 'Vendor Name', lat: 40.7128, lng: -74.0060, stream_url: 'https://example.com/stream', source_type: 'hls', config: '{"key":"value"}', } const created = await createDevice(db, deviceData) expect(created.name).toBe('Full Device') expect(created.vendor).toBe('Vendor Name') expect(created.stream_url).toBe('https://example.com/stream') expect(created.source_type).toBe('hls') expect(created.config).toBe('{"key":"value"}') }) it('getAllDevices returns all devices', async () => { await createDevice(db, { name: 'Device 1', device_type: 'feed', lat: 40.7128, lng: -74.0060, stream_url: '', source_type: 'mjpeg', config: null, }) await createDevice(db, { name: 'Device 2', device_type: 'traffic', lat: 41.7128, lng: -75.0060, stream_url: '', source_type: 'hls', config: null, }) const devices = await getAllDevices(db) expect(devices).toHaveLength(2) }) it('updateDevice updates device fields', async () => { const created = await createDevice(db, { name: 'Original', device_type: 'feed', lat: 40.7128, lng: -74.0060, stream_url: '', source_type: 'mjpeg', config: null, }) const updated = await updateDevice(db, created.id, { name: 'Updated', lat: 41.7128, }) expect(updated.name).toBe('Updated') expect(updated.lat).toBe(41.7128) }) it('updateDevice returns existing device when no updates', async () => { const created = await createDevice(db, { name: 'Test', device_type: 'feed', lat: 40.7128, lng: -74.0060, stream_url: '', source_type: 'mjpeg', config: null, }) const result = await updateDevice(db, created.id, {}) expect(result.id).toBe(created.id) }) }) describe('user queries', () => { it('getUserById returns null for non-existent user', async () => { const user = await getUserById(db, 'non-existent') expect(user).toBeNull() }) it('createUser and getUserById work together', async () => { const userData = { identifier: 'testuser', password_hash: 'hash123', role: 'admin', created_at: new Date().toISOString(), auth_provider: 'local', } const created = await createUser(db, userData) expect(created).toBeDefined() expect(created.identifier).toBe('testuser') const retrieved = await getUserById(db, created.id) expect(retrieved).toBeDefined() expect(retrieved.identifier).toBe('testuser') }) it('createUser defaults auth_provider to local', async () => { const userData = { identifier: 'testuser2', password_hash: 'hash', role: 'member', created_at: new Date().toISOString(), } const created = await createUser(db, userData) expect(created.auth_provider).toBe('local') }) it('createUser handles oidc fields', async () => { const userData = { identifier: 'oidcuser', password_hash: null, role: 'member', created_at: new Date().toISOString(), auth_provider: 'oidc', oidc_issuer: 'https://example.com', oidc_sub: 'sub123', } const created = await createUser(db, userData) expect(created.auth_provider).toBe('oidc') }) it('getUserByIdentifier finds user by identifier', async () => { await createUser(db, { identifier: 'findme', password_hash: 'hash', role: 'member', created_at: new Date().toISOString(), auth_provider: 'local', }) const user = await getUserByIdentifier(db, 'findme') expect(user).toBeDefined() expect(user.identifier).toBe('findme') }) it('updateUser updates user fields', async () => { const created = await createUser(db, { identifier: 'original', password_hash: 'hash', role: 'member', created_at: new Date().toISOString(), auth_provider: 'local', }) const updated = await updateUser(db, created.id, { role: 'admin', }) expect(updated.role).toBe('admin') }) it('updateUser returns existing user when no updates', async () => { const created = await createUser(db, { identifier: 'test', password_hash: 'hash', role: 'member', created_at: new Date().toISOString(), auth_provider: 'local', }) const result = await updateUser(db, created.id, {}) expect(result.id).toBe(created.id) }) }) describe('POI queries', () => { it('getPoiById returns null for non-existent POI', async () => { const poi = await getPoiById(db, 'non-existent') expect(poi).toBeNull() }) it('createPoi and getPoiById work together', async () => { const poiData = { lat: 40.7128, lng: -74.0060, label: 'Test POI', icon_type: 'flag', } const created = await createPoi(db, poiData) expect(created).toBeDefined() expect(created.label).toBe('Test POI') const retrieved = await getPoiById(db, created.id) expect(retrieved).toBeDefined() expect(retrieved.label).toBe('Test POI') }) it('createPoi defaults label and icon_type', async () => { const poiData = { lat: 40.7128, lng: -74.0060, } const created = await createPoi(db, poiData) expect(created.label).toBe('') expect(created.icon_type).toBe('pin') }) it('getAllPois returns all POIs', async () => { await createPoi(db, { lat: 40.7128, lng: -74.0060, label: 'POI 1' }) await createPoi(db, { lat: 41.7128, lng: -75.0060, label: 'POI 2' }) const pois = await getAllPois(db) expect(pois).toHaveLength(2) }) it('updatePoi updates POI fields', async () => { const created = await createPoi(db, { lat: 40.7128, lng: -74.0060, label: 'Original', }) const updated = await updatePoi(db, created.id, { label: 'Updated', lat: 41.7128, }) expect(updated.label).toBe('Updated') expect(updated.lat).toBe(41.7128) }) it('updatePoi returns existing POI when no updates', async () => { const created = await createPoi(db, { lat: 40.7128, lng: -74.0060, label: 'Test', }) const result = await updatePoi(db, created.id, {}) expect(result.id).toBe(created.id) }) }) describe('session queries', () => { it('getSessionById returns null for non-existent session', async () => { const session = await getSessionById(db, 'non-existent') expect(session).toBeNull() }) it('createDbSession and getSessionById work together', async () => { const sessionData = { id: 'session-1', user_id: 'user-1', created_at: new Date().toISOString(), expires_at: new Date(Date.now() + 86400000).toISOString(), } await createDbSession(db, sessionData) const retrieved = await getSessionById(db, 'session-1') expect(retrieved).toBeDefined() expect(retrieved.user_id).toBe('user-1') }) it('deleteSession removes session', async () => { await createDbSession(db, { id: 'session-1', user_id: 'user-1', created_at: new Date().toISOString(), expires_at: new Date(Date.now() + 86400000).toISOString(), }) await deleteSession(db, 'session-1') const retrieved = await getSessionById(db, 'session-1') expect(retrieved).toBeNull() }) }) })