test: add unit tests for lib/ (validate, auth, storage, email, rate-limit)
49 tests for all 10 Zod schemas in validate.ts, 26 tests for auth (hashPassword, verifyPassword, createSession, getSession, getCurrentUser, deleteSession), 11 for storage (magic-byte validation, saveImage, deleteImageFile), 9 for email (sendMail scenarios), and 6 for rate limiting logic.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import '../../../test/__mocks__/prisma'
|
||||
|
||||
import { checkRateLimit, recordAttempt } from '@/lib/rate-limit'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('checkRateLimit', () => {
|
||||
it('returns not limited when attempts < 10', async () => {
|
||||
vi.mocked(prisma.loginAttempt.count).mockResolvedValue(5)
|
||||
const result = await checkRateLimit('1.2.3.4')
|
||||
expect(result.limited).toBe(false)
|
||||
expect(result.remaining).toBe(5)
|
||||
})
|
||||
|
||||
it('returns limited when attempts >= 10', async () => {
|
||||
vi.mocked(prisma.loginAttempt.count).mockResolvedValue(10)
|
||||
const result = await checkRateLimit('1.2.3.4')
|
||||
expect(result.limited).toBe(true)
|
||||
expect(result.remaining).toBe(0)
|
||||
})
|
||||
|
||||
it('returns limited when attempts > 10', async () => {
|
||||
vi.mocked(prisma.loginAttempt.count).mockResolvedValue(15)
|
||||
const result = await checkRateLimit('1.2.3.4')
|
||||
expect(result.limited).toBe(true)
|
||||
})
|
||||
|
||||
it('returns remaining = 1 when attempts = 9', async () => {
|
||||
vi.mocked(prisma.loginAttempt.count).mockResolvedValue(9)
|
||||
const result = await checkRateLimit('1.2.3.4')
|
||||
expect(result.limited).toBe(false)
|
||||
expect(result.remaining).toBe(1)
|
||||
})
|
||||
|
||||
it('queries with a windowStart within the last 15 minutes', async () => {
|
||||
vi.mocked(prisma.loginAttempt.count).mockResolvedValue(0)
|
||||
const before = new Date(Date.now() - 15 * 60 * 1000 - 100)
|
||||
|
||||
await checkRateLimit('1.2.3.4')
|
||||
|
||||
const callArg = vi.mocked(prisma.loginAttempt.count).mock.calls[0][0]
|
||||
const windowStart = callArg?.where?.createdAt?.gte as Date
|
||||
expect(windowStart.getTime()).toBeGreaterThan(before.getTime())
|
||||
})
|
||||
})
|
||||
|
||||
describe('recordAttempt', () => {
|
||||
it('creates a login attempt record', async () => {
|
||||
vi.mocked(prisma.loginAttempt.create).mockResolvedValue({ id: '1', key: '1.2.3.4', createdAt: new Date() })
|
||||
vi.mocked(prisma.loginAttempt.deleteMany).mockResolvedValue({ count: 0 })
|
||||
|
||||
await recordAttempt('1.2.3.4')
|
||||
|
||||
expect(prisma.loginAttempt.create).toHaveBeenCalledWith({ data: { key: '1.2.3.4' } })
|
||||
})
|
||||
|
||||
it('cleans up old records after creating', async () => {
|
||||
vi.mocked(prisma.loginAttempt.create).mockResolvedValue({ id: '1', key: '1.2.3.4', createdAt: new Date() })
|
||||
vi.mocked(prisma.loginAttempt.deleteMany).mockResolvedValue({ count: 0 })
|
||||
|
||||
await recordAttempt('1.2.3.4')
|
||||
|
||||
expect(prisma.loginAttempt.deleteMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ where: expect.objectContaining({ createdAt: expect.anything() }) })
|
||||
)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user