Files
ecommerce-platform/test/integration/api/auth/login.test.ts
T
davide 6a5d5a6119 test: add integration tests for API routes (auth, Stripe webhook)
27 tests covering POST /api/auth/login (9), POST /api/auth/register (9), and
POST /api/webhooks/stripe (11). Routes are tested by importing handlers directly
as functions, no HTTP server needed. Stripe false-positive fixed: thrown error
message now differs from the hardcoded 400 response to verify sanitization.
2026-05-19 14:07:53 +02:00

120 lines
4.3 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest'
import '../../../__mocks__/prisma'
import { NextRequest } from 'next/server'
import { POST } from '@/app/api/auth/login/route'
import { prisma } from '@/lib/prisma'
import { mockUser } from '../../../fixtures/users'
vi.mock('@/lib/auth', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/lib/auth')>()
return {
...actual,
verifyPassword: vi.fn(),
createSession: vi.fn().mockResolvedValue('mock-session-token'),
setSessionCookie: vi.fn(),
}
})
import { verifyPassword, createSession, setSessionCookie } from '@/lib/auth'
function makeRequest(body: unknown, ip = '1.2.3.4') {
return new NextRequest(
new Request('http://localhost/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-forwarded-for': ip },
body: JSON.stringify(body),
})
)
}
beforeEach(() => {
vi.clearAllMocks()
vi.mocked(prisma.loginAttempt.count).mockResolvedValue(0)
vi.mocked(prisma.loginAttempt.create).mockResolvedValue({ id: '1', key: '1.2.3.4', createdAt: new Date() })
vi.mocked(prisma.loginAttempt.deleteMany).mockResolvedValue({ count: 0 })
})
describe('POST /api/auth/login', () => {
it('returns 429 when rate limit exceeded', async () => {
vi.mocked(prisma.loginAttempt.count).mockResolvedValue(10)
const res = await POST(makeRequest({ email: 'user@example.com', password: 'pass' }))
expect(res.status).toBe(429)
const data = await res.json()
expect(data.error).toMatch(/Too many/)
})
it('returns 400 for invalid email format', async () => {
const res = await POST(makeRequest({ email: 'not-an-email', password: 'pass' }))
expect(res.status).toBe(400)
})
it('returns 400 for empty password', async () => {
const res = await POST(makeRequest({ email: 'user@example.com', password: '' }))
expect(res.status).toBe(400)
})
it('returns 400 for malformed JSON body', async () => {
const req = new NextRequest(
new Request('http://localhost/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-forwarded-for': '1.2.3.4' },
body: 'not-json',
})
)
const res = await POST(req)
expect(res.status).toBe(400)
})
it('returns 401 when user not found', async () => {
vi.mocked(prisma.user.findUnique).mockResolvedValue(null)
const res = await POST(makeRequest({ email: 'notfound@example.com', password: 'SomePass1!' }))
expect(res.status).toBe(401)
const data = await res.json()
expect(data.error).toBe('Invalid email or password')
})
it('records a failed attempt when user not found', async () => {
vi.mocked(prisma.user.findUnique).mockResolvedValue(null)
await POST(makeRequest({ email: 'notfound@example.com', password: 'SomePass1!' }))
expect(prisma.loginAttempt.create).toHaveBeenCalledWith({ data: { key: '1.2.3.4' } })
})
it('returns 401 when password is wrong', async () => {
vi.mocked(prisma.user.findUnique).mockResolvedValue(mockUser as any)
vi.mocked(verifyPassword).mockResolvedValue(false)
const res = await POST(makeRequest({ email: mockUser.email, password: 'WrongPass1!' }))
expect(res.status).toBe(401)
expect((await res.json()).error).toBe('Invalid email or password')
})
it('returns 200 with user data on successful login', async () => {
vi.mocked(prisma.user.findUnique).mockResolvedValue(mockUser as any)
vi.mocked(verifyPassword).mockResolvedValue(true)
vi.mocked(prisma.session.create).mockResolvedValue({} as any)
const res = await POST(makeRequest({ email: mockUser.email, password: 'ValidPass1!' }))
expect(res.status).toBe(200)
const data = await res.json()
expect(data.user.email).toBe(mockUser.email)
expect(data.user.role).toBe(mockUser.role)
expect(data.user).not.toHaveProperty('passwordHash')
})
it('creates a session and sets cookie on successful login', async () => {
vi.mocked(prisma.user.findUnique).mockResolvedValue(mockUser as any)
vi.mocked(verifyPassword).mockResolvedValue(true)
vi.mocked(prisma.session.create).mockResolvedValue({} as any)
await POST(makeRequest({ email: mockUser.email, password: 'ValidPass1!' }))
expect(createSession).toHaveBeenCalledWith(mockUser.id)
expect(setSessionCookie).toHaveBeenCalledWith('mock-session-token')
})
})