Files
crumbs-original/src/lib/server/auth.test.ts
T
Frederic CabassutandClaude Opus 4.6 4f4cc69b9f fix: replace hardcoded test passwords with runtime-generated UUIDs
Generate random passwords in global-setup and share via temp file so
all Playwright workers use the same credentials. Screenshot scripts
use module-level crypto.randomUUID() since they run single-process.
Unit test auth passwords also use randomUUID().

Eliminates security scanner alerts for passwords committed to git.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 10:29:45 +01:00

128 lines
3.8 KiB
TypeScript

import { describe, it, expect, beforeEach } from 'vitest';
import { createTestDb } from './db/test-helpers.js';
import { users, sessions } from './db/schema.js';
import { eq } from 'drizzle-orm';
import * as argon2 from 'argon2';
import { randomBytes, randomUUID } from 'crypto';
import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
import type * as schema from './db/schema.js';
let db: BetterSQLite3Database<typeof schema>;
beforeEach(() => {
const testDb = createTestDb();
db = testDb.db;
});
describe('Auth - Password Hashing', () => {
it('should hash and verify a password correctly', async () => {
const password = randomUUID();
const hash = await argon2.hash(password);
expect(hash).not.toBe(password);
expect(await argon2.verify(hash, password)).toBe(true);
expect(await argon2.verify(hash, randomUUID())).toBe(false);
});
it('should produce different hashes for the same password', async () => {
const password = randomUUID();
const hash1 = await argon2.hash(password);
const hash2 = await argon2.hash(password);
expect(hash1).not.toBe(hash2);
expect(await argon2.verify(hash1, password)).toBe(true);
expect(await argon2.verify(hash2, password)).toBe(true);
});
});
describe('Auth - User Setup', () => {
it('should create a user with hashed password', async () => {
const password = randomUUID();
const hash = await argon2.hash(password);
await db.insert(users).values({
email: 'admin@test.com',
displayName: 'Admin',
role: 'admin',
passwordHash: hash,
createdAt: new Date()
});
const user = await db.select().from(users).get();
expect(user).toBeDefined();
expect(user!.email).toBe('admin@test.com');
expect(user!.role).toBe('admin');
expect(user!.passwordHash).not.toBe(password);
expect(await argon2.verify(user!.passwordHash!, password)).toBe(true);
});
it('should only allow one admin setup', async () => {
await db.insert(users).values({
email: 'admin@test.com',
role: 'admin',
passwordHash: 'hash1',
createdAt: new Date()
});
const allUsers = await db.select().from(users);
expect(allUsers).toHaveLength(1);
});
});
describe('Auth - Sessions', () => {
it('should create and validate a session', async () => {
const [user] = await db
.insert(users)
.values({ email: 'test@test.com', passwordHash: 'hash', createdAt: new Date() })
.returning();
const token = randomBytes(32).toString('hex');
await db.insert(sessions).values({
id: token,
userId: user.id,
expiresAt: new Date(Date.now() + 86400000)
});
const session = await db.select().from(sessions).where(eq(sessions.id, token)).get();
expect(session).toBeDefined();
expect(session!.userId).toBe(user.id);
expect(session!.expiresAt.getTime()).toBeGreaterThan(Date.now());
});
it('should detect expired sessions', async () => {
const [user] = await db
.insert(users)
.values({ email: 'test@test.com', passwordHash: 'hash', createdAt: new Date() })
.returning();
const token = randomBytes(32).toString('hex');
await db.insert(sessions).values({
id: token,
userId: user.id,
expiresAt: new Date(Date.now() - 1000) // Expired
});
const session = await db.select().from(sessions).where(eq(sessions.id, token)).get();
expect(session).toBeDefined();
expect(session!.expiresAt.getTime()).toBeLessThan(Date.now());
});
it('should delete a session', async () => {
const [user] = await db
.insert(users)
.values({ email: 'test@test.com', passwordHash: 'hash', createdAt: new Date() })
.returning();
const token = randomBytes(32).toString('hex');
await db.insert(sessions).values({
id: token,
userId: user.id,
expiresAt: new Date(Date.now() + 86400000)
});
await db.delete(sessions).where(eq(sessions.id, token));
const session = await db.select().from(sessions).where(eq(sessions.id, token)).get();
expect(session).toBeUndefined();
});
});