feat: add logging
This commit is contained in:
+49
-9
@@ -1,11 +1,12 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { INestApplication, ValidationPipe } from '@nestjs/common';
|
||||
import cookieParser from 'cookie-parser';
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
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 { StructuredLogger } from './../src/common/logging/structured-logger.service';
|
||||
import { configureApp } from './../src/main';
|
||||
import { PrismaService } from './../src/prisma/prisma.service';
|
||||
import { AuthService } from './../src/auth/auth.service';
|
||||
|
||||
type Authentication = { user: { email: string }; accessToken: string };
|
||||
type Problem = { code: string };
|
||||
@@ -19,12 +20,7 @@ describe('Authentication (e2e)', () => {
|
||||
}).compile();
|
||||
|
||||
app = moduleFixture.createNestApplication();
|
||||
app.setGlobalPrefix('api/v1');
|
||||
app.use(cookieParser());
|
||||
app.useGlobalPipes(
|
||||
new ValidationPipe({ transform: true, whitelist: true }),
|
||||
);
|
||||
app.useGlobalFilters(new HttpExceptionFilter());
|
||||
configureApp(app);
|
||||
await app.init();
|
||||
await app.get(PrismaService).session.deleteMany();
|
||||
await app.get(PrismaService).tbankConnection.deleteMany();
|
||||
@@ -140,4 +136,48 @@ describe('Authentication (e2e)', () => {
|
||||
expect((body as Problem).code).toBe('TBANK_NOT_CONNECTED'),
|
||||
);
|
||||
});
|
||||
|
||||
it('exposes a server request ID and logs one completion event', async () => {
|
||||
const logger = app.get(StructuredLogger);
|
||||
const event = jest.spyOn(logger, 'event');
|
||||
const response = await request(app.getHttpServer())
|
||||
.get('/api/v1/auth/me')
|
||||
.set('Origin', 'http://localhost:5173')
|
||||
.expect(401);
|
||||
|
||||
expect(response.headers['x-request-id']).toMatch(/^[0-9a-f-]{36}$/i);
|
||||
expect(response.headers['access-control-expose-headers']).toContain(
|
||||
'X-Request-ID',
|
||||
);
|
||||
expect(event).toHaveBeenCalledTimes(1);
|
||||
expect(event).toHaveBeenCalledWith(
|
||||
'warn',
|
||||
'http.request.completed',
|
||||
expect.objectContaining({ status: 401, code: 'UNAUTHORIZED' }),
|
||||
);
|
||||
});
|
||||
|
||||
it('records the public code and stack for an unhandled error', async () => {
|
||||
const logger = app.get(StructuredLogger);
|
||||
const event = jest.spyOn(logger, 'event');
|
||||
jest
|
||||
.spyOn(app.get(AuthService), 'login')
|
||||
.mockRejectedValue(new Error('password: secret'));
|
||||
|
||||
await request(app.getHttpServer())
|
||||
.post('/api/v1/auth/login')
|
||||
.send({ email: 'user@example.com', password: 'a secure password' })
|
||||
.expect(500)
|
||||
.expect(({ body }: { body: unknown }) =>
|
||||
expect(body).toEqual({ status: 500, code: 'INTERNAL_SERVER_ERROR' }),
|
||||
);
|
||||
|
||||
expect(event).toHaveBeenCalledWith(
|
||||
'error',
|
||||
'http.request.completed',
|
||||
expect.objectContaining({
|
||||
code: 'INTERNAL_SERVER_ERROR',
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user