import { INestApplication } from '@nestjs/common'; import * as bcrypt from 'bcryptjs'; import request from 'supertest'; import { App } from 'supertest/types'; import { PrismaService } from '../src/prisma/prisma.service'; import { createTestApp } from './utils/create-test-app'; const LOGIN_THROTTLE_LIMIT = 10; describe('Auth login throttling (e2e)', () => { let app: INestApplication; let prisma: PrismaService; const email = `auth-throttle-e2e-${Date.now()}@example.com`; const password = 'SuperSecret123!'; let userId: string; beforeAll(async () => { app = await createTestApp(); prisma = app.get(PrismaService); const passwordHash = await bcrypt.hash(password, 12); const user = await prisma.user.create({ data: { email, passwordHash, name: 'Throttle E2E User', role: 'STAFF' }, }); userId = user.id; }); afterAll(async () => { await prisma.refreshToken.deleteMany({ where: { userId } }); await prisma.auditLog.deleteMany({ where: { userId } }); await prisma.user.delete({ where: { id: userId } }); await app.close(); }); it('rejects login attempts beyond the per-minute limit with 429', async () => { for (let attempt = 0; attempt < LOGIN_THROTTLE_LIMIT; attempt += 1) { await request(app.getHttpServer()) .post('/api/v1/auth/login') .send({ email, password: 'wrong-password' }) .expect(401); } await request(app.getHttpServer()) .post('/api/v1/auth/login') .send({ email, password: 'wrong-password' }) .expect(429); }); });