import { beforeEach, afterEach, describe, expect, it } from 'vitest'; import { setupTestDb } from '../../tests/helpers.js'; import type { Database } from './db/types.js'; import { createLocalUser, deleteUser, listUsers, setLocalPasswordForUser, updateUser, upsertUserFromAuth, upsertUserProfile } from './users.js'; let database: Database; beforeEach(() => { database = setupTestDb(); }); afterEach(() => { database.close(); }); describe('upsertUserFromAuth', () => { it('creates a new user with profile data', () => { const created = upsertUserFromAuth({ id: 'u1', username: 'jdoe', fullName: 'Jane Doe', email: 'jane@example.com', authSource: 'OIDC - Synology' }); expect(created.id).toBe('u1'); expect(created.username).toBe('jdoe'); expect(created.full_name).toBe('Jane Doe'); expect(created.email).toBe('jane@example.com'); expect(created.auth_source).toBe('OIDC - Synology'); expect(listUsers()).toHaveLength(1); }); it('updates existing users with new auth data', () => { upsertUserFromAuth({ id: 'u1', username: 'jdoe', fullName: 'Jane Doe', email: 'jane@example.com', authSource: 'OIDC - Synology' }); const updated = upsertUserFromAuth({ id: 'u1', username: 'janed', email: 'jane.doe@example.com' }); expect(updated.username).toBe('janed'); expect(updated.email).toBe('jane.doe@example.com'); }); }); describe('upsertUserProfile', () => { it('creates a user from profile details', () => { const created = upsertUserProfile('u2', 'Sam Sample', 'sam@example.com'); expect(created.id).toBe('u2'); expect(created.full_name).toBe('Sam Sample'); expect(created.email).toBe('sam@example.com'); }); }); describe('updateUser', () => { it('updates user fields and syncs self profile when present', () => { upsertUserFromAuth({ id: 'u3', username: 'sarah', fullName: 'Sarah Lee', email: 'sarah@example.com' }); database.run( `INSERT INTO people (id, user_id, first_name, last_name, email, is_self) VALUES (?, ?, ?, ?, ?, 1)`, ['p1', 'u3', 'Sarah', 'Lee', 'sarah@example.com'] ); updateUser({ id: 'u3', username: 'slee', fullName: 'Sarah Smith', email: 'ss@example.com' }); const user = listUsers().find((item) => item.id === 'u3'); expect(user?.username).toBe('slee'); expect(user?.full_name).toBe('Sarah Smith'); expect(user?.email).toBe('ss@example.com'); const profile = database.get<{ first_name: string; last_name: string; email: string | null }>( 'SELECT first_name, last_name, email FROM people WHERE user_id = ? AND is_self = 1', ['u3'] ); expect(profile?.first_name).toBe('Sarah'); expect(profile?.last_name).toBe('Smith'); expect(profile?.email).toBe('ss@example.com'); }); }); describe('deleteUser', () => { it('removes the user record', () => { upsertUserFromAuth({ id: 'u4', username: 'delete-me', fullName: 'Delete Me' }); deleteUser('u4'); expect(listUsers().find((item) => item.id === 'u4')).toBeUndefined(); }); }); describe('createLocalUser', () => { it('creates a local user with credentials', async () => { const created = await createLocalUser({ username: 'local-user', fullName: 'Local User', email: 'local@example.com', password: 'averysecurepassword' }); expect(created.username).toBe('local-user'); expect(created.auth_source).toBe('Local'); const row = database.get<{ user_id: string; password_hash: string }>( 'SELECT user_id, password_hash FROM local_credentials WHERE user_id = ?', [created.id] ); expect(row?.user_id).toBe(created.id); expect(row?.password_hash).toBeTruthy(); }); it('rejects duplicate usernames', async () => { await createLocalUser({ username: 'dup-user', fullName: 'Dup User', password: 'averysecurepassword' }); await expect( createLocalUser({ username: 'dup-user', fullName: 'Dup User Two', password: 'averysecurepassword' }) ).rejects.toThrow('Username already exists'); }); }); describe('setLocalPasswordForUser', () => { it('sets local credentials for an existing user', async () => { upsertUserFromAuth({ id: 'u5', username: 'sarah', fullName: 'Sarah Lee' }); await setLocalPasswordForUser('u5', 'averysecurepassword'); const row = database.get<{ user_id: string; password_hash: string }>( 'SELECT user_id, password_hash FROM local_credentials WHERE user_id = ?', ['u5'] ); expect(row?.user_id).toBe('u5'); expect(row?.password_hash).toBeTruthy(); }); });