Files
Todo/lib/__tests__/auth-actions.test.ts
Paul Bailey 70121982a0 feat: implement user registration functionality
- Created registerUser server action with email/password validation
- Implemented password hashing with bcrypt (10 rounds)
- Added email uniqueness check to prevent duplicate registrations
- Created session after successful registration using NextAuth
- Added comprehensive validation for email format and password length (min 8 chars)
- Added email and password validation utilities to lib/validation.ts
- Removed PrismaAdapter from auth.ts (using JWT sessions only)
- Added vitest testing framework and configuration
- Created comprehensive unit tests for registration functionality
- All tests passing (6/6)

Requirements covered: 1.1, 1.2, 1.3, 1.4, 1.5
2025-12-02 00:03:23 +00:00

128 lines
3.5 KiB
TypeScript

/**
* Tests for user registration functionality
* This file tests the core registration logic without session creation
*/
import { describe, it, expect, afterEach, vi } from 'vitest'
import { prisma } from '../db'
import bcrypt from 'bcryptjs'
import { z } from 'zod'
// Mock the auth module to avoid Next.js dependencies in tests
vi.mock('@/auth', () => ({
signIn: vi.fn(),
}))
// Import after mocking
import { registerUser } from '../auth-actions'
describe('registerUser', () => {
// Clean up test users after each test
afterEach(async () => {
await prisma.user.deleteMany({
where: {
email: {
contains: 'test-',
},
},
})
})
it('should create a new user with valid credentials', async () => {
const email = `test-${Date.now()}@example.com`
const password = 'password123'
const name = 'Test User'
const result = await registerUser(email, password, name)
expect(result.success).toBe(true)
if (result.success) {
expect(result.userId).toBeDefined()
expect(typeof result.userId).toBe('string')
// Verify user was created in database
const user = await prisma.user.findUnique({
where: { email },
})
expect(user).toBeDefined()
expect(user?.email).toBe(email)
expect(user?.name).toBe(name)
expect(user?.passwordHash).toBeDefined()
expect(user?.passwordHash).not.toBe(password) // Password should be hashed
}
})
it('should reject registration with duplicate email', async () => {
const email = `test-${Date.now()}@example.com`
const password = 'password123'
// Create first user
const result1 = await registerUser(email, password)
expect(result1.success).toBe(true)
// Try to create second user with same email
const result2 = await registerUser(email, password)
expect(result2.success).toBe(false)
if (!result2.success) {
expect(result2.error).toContain('already registered')
}
})
it('should hash the password before storing', async () => {
const email = `test-${Date.now()}@example.com`
const password = 'password123'
const result = await registerUser(email, password)
expect(result.success).toBe(true)
const user = await prisma.user.findUnique({
where: { email },
})
expect(user?.passwordHash).toBeDefined()
expect(user?.passwordHash).not.toBe(password)
// Verify the hash is valid
const isValid = await bcrypt.compare(password, user!.passwordHash)
expect(isValid).toBe(true)
})
it('should reject password shorter than 8 characters', async () => {
const email = `test-${Date.now()}@example.com`
const password = 'short'
const result = await registerUser(email, password)
expect(result.success).toBe(false)
if (!result.success) {
expect(result.error).toContain('at least 8 characters')
}
})
it('should reject invalid email format', async () => {
const email = 'invalid-email'
const password = 'password123'
const result = await registerUser(email, password)
expect(result.success).toBe(false)
if (!result.success) {
expect(result.error).toContain('Invalid email')
}
})
it('should create user without name (optional field)', async () => {
const email = `test-${Date.now()}@example.com`
const password = 'password123'
const result = await registerUser(email, password)
expect(result.success).toBe(true)
const user = await prisma.user.findUnique({
where: { email },
})
expect(user).toBeDefined()
expect(user?.name).toBeNull()
})
})