mirror change from https://github.com/binhkid2/FullStack-Blog-Nestjs-Nextjs-Postgres
This commit is contained in:
141
backend/test/auth.e2e-spec.ts
Normal file
141
backend/test/auth.e2e-spec.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { INestApplication, ValidationPipe } from '@nestjs/common';
|
||||
import * as request from 'supertest';
|
||||
import * as cookieParser from 'cookie-parser';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { User } from '../src/users/entities/user.entity';
|
||||
|
||||
describe('Auth (e2e)', () => {
|
||||
let app: INestApplication;
|
||||
let userRepo: Repository<User>;
|
||||
|
||||
beforeAll(async () => {
|
||||
const moduleFixture: TestingModule = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleFixture.createNestApplication();
|
||||
app.use(cookieParser());
|
||||
app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));
|
||||
await app.init();
|
||||
|
||||
userRepo = moduleFixture.get<Repository<User>>(getRepositoryToken(User));
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
const testEmail = `test-${Date.now()}@example.com`;
|
||||
const testPassword = 'Test1234!';
|
||||
|
||||
describe('POST /auth/register', () => {
|
||||
it('should register a new user and return tokens', async () => {
|
||||
const res = await request(app.getHttpServer())
|
||||
.post('/auth/register')
|
||||
.send({ email: testEmail, password: testPassword, name: 'Test User' })
|
||||
.expect(201);
|
||||
|
||||
expect(res.body.success).toBe(true);
|
||||
expect(res.body.accessToken).toBeDefined();
|
||||
expect(res.body.user.email).toBe(testEmail);
|
||||
expect(res.body.user.passwordHash).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should reject duplicate email', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/auth/register')
|
||||
.send({ email: testEmail, password: testPassword })
|
||||
.expect(409);
|
||||
});
|
||||
|
||||
it('should reject short password', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/auth/register')
|
||||
.send({ email: 'new@example.com', password: '123' })
|
||||
.expect(400);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /auth/login', () => {
|
||||
it('should login with correct credentials', async () => {
|
||||
const res = await request(app.getHttpServer())
|
||||
.post('/auth/login')
|
||||
.send({ email: testEmail, password: testPassword })
|
||||
.expect(201);
|
||||
|
||||
expect(res.body.success).toBe(true);
|
||||
expect(res.body.accessToken).toBeDefined();
|
||||
|
||||
// Cookies should be set
|
||||
const cookies = res.headers['set-cookie'] as string[];
|
||||
expect(cookies).toBeDefined();
|
||||
const hasAccessCookie = cookies.some((c) => c.startsWith('accessToken='));
|
||||
expect(hasAccessCookie).toBe(true);
|
||||
});
|
||||
|
||||
it('should reject wrong password', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/auth/login')
|
||||
.send({ email: testEmail, password: 'wrongpassword' })
|
||||
.expect(401);
|
||||
});
|
||||
|
||||
it('should reject non-existent email', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/auth/login')
|
||||
.send({ email: 'nonexistent@example.com', password: testPassword })
|
||||
.expect(401);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /auth/refresh', () => {
|
||||
it('should rotate refresh token', async () => {
|
||||
// First login to get refresh token
|
||||
const loginRes = await request(app.getHttpServer())
|
||||
.post('/auth/login')
|
||||
.send({ email: testEmail, password: testPassword });
|
||||
|
||||
const cookies = loginRes.headers['set-cookie'] as string[];
|
||||
const refreshCookie = cookies.find((c) => c.startsWith('refreshToken='));
|
||||
expect(refreshCookie).toBeDefined();
|
||||
|
||||
// Use refresh token
|
||||
const refreshRes = await request(app.getHttpServer())
|
||||
.post('/auth/refresh')
|
||||
.set('Cookie', cookies)
|
||||
.expect(201);
|
||||
|
||||
expect(refreshRes.body.success).toBe(true);
|
||||
expect(refreshRes.body.accessToken).toBeDefined();
|
||||
});
|
||||
|
||||
it('should reject missing refresh token', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/auth/refresh')
|
||||
.expect(401);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /auth/magic-link', () => {
|
||||
it('should accept magic link request for existing email', async () => {
|
||||
const res = await request(app.getHttpServer())
|
||||
.post('/auth/magic-link')
|
||||
.send({ email: testEmail })
|
||||
.expect(201);
|
||||
|
||||
expect(res.body.success).toBe(true);
|
||||
});
|
||||
|
||||
it('should accept magic link request for non-existing email (no enumeration)', async () => {
|
||||
const res = await request(app.getHttpServer())
|
||||
.post('/auth/magic-link')
|
||||
.send({ email: 'nobody@nowhere.com' })
|
||||
.expect(201);
|
||||
|
||||
expect(res.body.success).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user