Files
backend/test/app.e2e-spec.ts
T
2026-08-13 22:44:53 +03:00

144 lines
5.4 KiB
TypeScript

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication, ValidationPipe } from '@nestjs/common';
import cookieParser from 'cookie-parser';
import request from 'supertest';
import { App } from 'supertest/types';
import { AppModule } from './../src/app.module';
import { HttpExceptionFilter } from './../src/common/filters/http-exception.filter';
import { PrismaService } from './../src/prisma/prisma.service';
type Authentication = { user: { email: string }; accessToken: string };
type Problem = { code: string };
describe('Authentication (e2e)', () => {
let app: INestApplication<App>;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
app.setGlobalPrefix('api/v1');
app.use(cookieParser());
app.useGlobalPipes(
new ValidationPipe({ transform: true, whitelist: true }),
);
app.useGlobalFilters(new HttpExceptionFilter());
await app.init();
await app.get(PrismaService).session.deleteMany();
await app.get(PrismaService).tbankConnection.deleteMany();
await app.get(PrismaService).user.deleteMany();
});
afterEach(() => app.close());
it('registers, guards profile, rotates refresh and logs out', async () => {
const agent = request.agent(app.getHttpServer());
const registration = await agent
.post('/api/v1/auth/register')
.send({ email: ' User@Example.com ', password: 'a secure password' })
.expect(201);
const authentication = registration.body as Authentication;
expect(authentication.user.email).toBe('user@example.com');
const accessToken = authentication.accessToken;
await request(app.getHttpServer()).get('/api/v1/auth/me').expect(401);
await agent
.get('/api/v1/auth/me')
.set('Authorization', `Bearer ${accessToken}`)
.expect(200)
.expect(({ body }: { body: unknown }) =>
expect((body as { email: string }).email).toBe('user@example.com'),
);
const firstCookie = registration.headers['set-cookie'][0];
await agent.post('/api/v1/auth/refresh').expect(201);
await request(app.getHttpServer())
.post('/api/v1/auth/refresh')
.set('Cookie', firstCookie)
.expect(401)
.expect('Content-Type', /application\/problem\+json/);
await agent.post('/api/v1/auth/logout').expect(204);
await agent.post('/api/v1/auth/logout').expect(204);
});
it('rejects duplicate registration and invalid credentials', async () => {
await request(app.getHttpServer())
.post('/api/v1/auth/register')
.send({ email: 'user@example.com', password: 'a secure password' })
.expect(201);
await request(app.getHttpServer())
.post('/api/v1/auth/register')
.send({ email: 'USER@example.com', password: 'a secure password' })
.expect(409)
.expect(({ body }: { body: unknown }) =>
expect((body as Problem).code).toBe('EMAIL_ALREADY_REGISTERED'),
);
await request(app.getHttpServer())
.post('/api/v1/auth/login')
.send({ email: 'user@example.com', password: 'wrong password' })
.expect(401)
.expect(({ body }: { body: unknown }) =>
expect((body as Problem).code).toBe('INVALID_CREDENTIALS'),
);
});
it('guards T-Bank connection and never returns a token', async () => {
const registration = await request(app.getHttpServer())
.post('/api/v1/auth/register')
.send({ email: 'connection@example.com', password: 'a secure password' })
.expect(201);
const accessToken = (registration.body as Authentication).accessToken;
await request(app.getHttpServer())
.get('/api/v1/tbank-connection')
.expect(401);
await request(app.getHttpServer())
.get('/api/v1/tbank-connection')
.set('Authorization', `Bearer ${accessToken}`)
.expect(200)
.expect(({ body }: { body: unknown }) =>
expect(body).toEqual({ connected: false, connectedAt: null }),
);
});
it('guards brokerage accounts and reports a missing connection', async () => {
const registration = await request(app.getHttpServer())
.post('/api/v1/auth/register')
.send({ email: 'accounts@example.com', password: 'a secure password' })
.expect(201);
const accessToken = (registration.body as Authentication).accessToken;
await request(app.getHttpServer())
.get('/api/v1/brokerage-accounts')
.expect(401);
await request(app.getHttpServer())
.get('/api/v1/brokerage-accounts')
.set('Authorization', `Bearer ${accessToken}`)
.expect(409)
.expect(({ body }: { body: unknown }) =>
expect((body as Problem).code).toBe('TBANK_NOT_CONNECTED'),
);
});
it('guards portfolio and reports a missing connection', async () => {
const registration = await request(app.getHttpServer())
.post('/api/v1/auth/register')
.send({ email: 'portfolio@example.com', password: 'a secure password' })
.expect(201);
const accessToken = (registration.body as Authentication).accessToken;
await request(app.getHttpServer())
.get('/api/v1/brokerage-accounts/account/portfolio')
.expect(401);
await request(app.getHttpServer())
.get('/api/v1/brokerage-accounts/account/portfolio')
.set('Authorization', `Bearer ${accessToken}`)
.expect(409)
.expect(({ body }: { body: unknown }) =>
expect((body as Problem).code).toBe('TBANK_NOT_CONNECTED'),
);
});
});