- 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
128 lines
3.5 KiB
TypeScript
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()
|
|
})
|
|
})
|