53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { authenticateUser, createUser, hashPassword, verifyPassword } from '@/lib/auth';
|
|
|
|
const { query } = vi.hoisted(() => ({ query: vi.fn() }));
|
|
|
|
vi.mock('@/lib/db', () => ({
|
|
db: {
|
|
query,
|
|
},
|
|
}));
|
|
|
|
describe('auth helpers', () => {
|
|
beforeEach(() => {
|
|
query.mockReset();
|
|
});
|
|
|
|
it('hashes passwords before storing a user', async () => {
|
|
query.mockResolvedValueOnce({ rows: [{ id: 1, username: 'alice', role: 'user' }] });
|
|
|
|
const user = await createUser('alice', 's3cret', 'user');
|
|
|
|
expect(user).toEqual({ id: 1, username: 'alice', role: 'user' });
|
|
expect(query).toHaveBeenCalledTimes(1);
|
|
|
|
const [, params] = query.mock.calls[0];
|
|
expect(params[0]).toBe('alice');
|
|
expect(params[1]).not.toBe('s3cret');
|
|
expect(await verifyPassword('s3cret', params[1] as string)).toBe(true);
|
|
});
|
|
|
|
it('authenticates a user with the stored password hash', async () => {
|
|
const passwordHash = await hashPassword('secret-password');
|
|
query.mockResolvedValueOnce({
|
|
rows: [{ id: 2, username: 'bob', password_hash: passwordHash, role: 'admin' }],
|
|
});
|
|
|
|
await expect(authenticateUser('bob', 'secret-password')).resolves.toEqual({
|
|
id: 2,
|
|
username: 'bob',
|
|
role: 'admin',
|
|
});
|
|
});
|
|
|
|
it('rejects an invalid password', async () => {
|
|
const passwordHash = await hashPassword('secret-password');
|
|
query.mockResolvedValueOnce({
|
|
rows: [{ id: 2, username: 'bob', password_hash: passwordHash, role: 'admin' }],
|
|
});
|
|
|
|
await expect(authenticateUser('bob', 'wrong-password')).resolves.toBeNull();
|
|
});
|
|
});
|