manicanldes-backend/test/health.spec.ts

71 lines
2.6 KiB
TypeScript

import 'reflect-metadata';
import { Test } from '@nestjs/testing';
import type { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { AppModule } from '../src/app.module';
import { DatabaseService } from '../src/database/database.service';
import { ENVIRONMENT } from '../src/config/environment.module';
import { configureApp } from '../src/configure-app';
import { parseEnvironment } from '../src/config/environment';
describe('health API', () => {
let app: INestApplication;
const database = { ping: jest.fn() };
beforeAll(async () => {
const environment = parseEnvironment({
DATABASE_URL: 'postgresql://localhost/mani',
CORS_ORIGINS: 'https://shop.example.com',
});
const module = await Test.createTestingModule({ imports: [AppModule] })
.overrideProvider(DatabaseService)
.useValue(database)
.overrideProvider(ENVIRONMENT)
.useValue(environment)
.compile();
app = module.createNestApplication();
configureApp(app, environment);
await app.init();
});
afterAll(async () => {
await app.close();
});
beforeEach(() => {
database.ping.mockReset();
});
it('reports liveness without requiring the database', async () => {
await request(app.getHttpServer())
.get('/api/v1/health/live')
.expect(200, { status: 'ok' });
expect(database.ping).not.toHaveBeenCalled();
});
it('checks the database before reporting readiness', async () => {
database.ping.mockResolvedValue(undefined);
await request(app.getHttpServer())
.get('/api/v1/health/ready')
.expect(200, { status: 'ok' });
expect(database.ping).toHaveBeenCalledTimes(1);
});
it('returns 503 without leaking database errors', async () => {
database.ping.mockRejectedValue(new Error('postgresql://secret'));
const response = await request(app.getHttpServer())
.get('/api/v1/health/ready')
.expect(503);
expect(response.text).not.toContain('secret');
});
it('sets security headers and permits only configured browser origins', async () => {
const allowed = await request(app.getHttpServer())
.get('/api/v1/health/live')
.set('Origin', 'https://shop.example.com');
expect(allowed.headers['x-content-type-options']).toBe('nosniff');
expect(allowed.headers['access-control-allow-origin']).toBe(
'https://shop.example.com',
);
const denied = await request(app.getHttpServer())
.get('/api/v1/health/live')
.set('Origin', 'https://untrusted.example.com');
expect(denied.headers['access-control-allow-origin']).toBeUndefined();
});
});