Integrate Oudelaa backend features, security, tests, and deployment updates

هذا الالتزام موجود في:
boutmoun123
2026-07-26 16:58:53 +03:00
الأصل 1b24ca4294
التزام 2fd5322ef7
178 ملفات معدلة مع 19068 إضافات و2592 حذوفات

230
src/main.spec.ts Normal file
عرض الملف

@@ -0,0 +1,230 @@
import { ConfigService } from '@nestjs/config';
import { NestFactory } from '@nestjs/core';
import { SwaggerModule } from '@nestjs/swagger';
import * as express from 'express';
import { existsSync, mkdirSync } from 'fs';
import { networkInterfaces } from 'os';
import { AppLoggerService } from './infrastructure/logging/app-logger.service';
import { RedisService } from './infrastructure/redis/redis.service';
import { configureHttpServer } from './infrastructure/reliability/http-server.config';
import { RedisIoAdapter } from './infrastructure/socket/redis-io.adapter';
import { bootstrap, getLocalIpv4Addresses, getStaticMediaHeaders, isPrivateIpv4Host } from './main';
jest.mock('./app.module', () => ({ AppModule: class AppModule {} }));
jest.mock('@nestjs/core', () => ({ NestFactory: { create: jest.fn() } }));
jest.mock('@nestjs/swagger', () => {
class DocumentBuilder {
setTitle() { return this; }
setDescription() { return this; }
setVersion() { return this; }
addBearerAuth() { return this; }
build() { return { openapi: '3.0.0' }; }
}
return {
DocumentBuilder,
SwaggerModule: { createDocument: jest.fn(() => ({ paths: {} })), setup: jest.fn() },
};
});
jest.mock('compression', () => jest.fn(() => 'compression-middleware'));
jest.mock('express', () => ({
json: jest.fn(() => 'json-middleware'),
urlencoded: jest.fn(() => 'urlencoded-middleware'),
static: jest.fn(() => 'static-middleware'),
}));
jest.mock('fs', () => ({
...jest.requireActual<typeof import('fs')>('fs'),
existsSync: jest.fn(),
mkdirSync: jest.fn(),
}));
jest.mock('os', () => ({
...jest.requireActual<typeof import('os')>('os'),
networkInterfaces: jest.fn(),
}));
jest.mock('./infrastructure/reliability/http-server.config', () => ({ configureHttpServer: jest.fn() }));
jest.mock('./infrastructure/socket/redis-io.adapter', () => ({
RedisIoAdapter: jest.fn().mockImplementation(() => ({
connectToRedis: jest.fn().mockResolvedValue(undefined),
})),
}));
describe('main bootstrap', () => {
const build = (overrides: Record<string, unknown> = {}) => {
const values: Record<string, unknown> = {
'cors.origins': ['https://app.example.com'],
nodeEnv: 'production',
'security.bodyLimit': '2mb',
'performance.compressionEnabled': true,
'performance.compressionThresholdBytes': 2048,
'storage.provider': 'local',
'storage.basePath': '/uploads/',
publicBaseUrl: 'http://localhost:4000/',
'email.enabled': true,
'email.smtpHost': 'smtp.example.com',
'email.smtpUser': 'smtp-user',
'email.fromEmail': 'noreply@example.com',
globalPrefix: 'api/v1',
responseEnvelopeEnabled: true,
'redis.enabled': true,
'redis.socketAdapterEnabled': true,
'swagger.enabled': true,
'swagger.path': 'docs',
'swagger.title': 'Oudelaa API',
'swagger.description': 'API',
'swagger.version': '1.0.0',
port: 4000,
host: '0.0.0.0',
...overrides,
};
const config = {
get: jest.fn((key: string, defaultValue?: unknown) =>
Object.prototype.hasOwnProperty.call(values, key) ? values[key] : defaultValue,
),
};
const logger = {
log: jest.fn(),
warn: jest.fn(),
logHttp: jest.fn(),
};
const redis = {};
const httpServer = { keepAliveTimeout: 0, headersTimeout: 0, requestTimeout: 0 };
const app = {
get: jest.fn((token: unknown) => {
if (token === ConfigService) return config;
if (token === AppLoggerService) return logger;
if (token === RedisService) return redis;
return undefined;
}),
useLogger: jest.fn(),
enableShutdownHooks: jest.fn(),
use: jest.fn(),
enableCors: jest.fn(),
setGlobalPrefix: jest.fn(),
useGlobalPipes: jest.fn(),
useGlobalInterceptors: jest.fn(),
useWebSocketAdapter: jest.fn(),
listen: jest.fn().mockResolvedValue(undefined),
getHttpServer: jest.fn(() => httpServer),
};
(NestFactory.create as jest.Mock).mockResolvedValue(app);
return { app, config, logger, redis, httpServer };
};
beforeEach(() => {
jest.clearAllMocks();
(existsSync as jest.Mock).mockReturnValue(false);
(networkInterfaces as jest.Mock).mockReturnValue({
Ethernet: [
{ family: 'IPv4', internal: false, address: '192.168.1.20' },
{ family: 'IPv6', internal: false, address: '::1' },
null,
],
Loopback: [{ family: 'IPv4', internal: true, address: '127.0.0.1' }],
});
});
it('classifies local addresses and static-media response headers', () => {
expect(getLocalIpv4Addresses()).toEqual(['192.168.1.20']);
expect(isPrivateIpv4Host('10.0.0.1')).toBe(true);
expect(isPrivateIpv4Host('192.168.1.1')).toBe(true);
expect(isPrivateIpv4Host('172.16.0.1')).toBe(true);
expect(isPrivateIpv4Host('172.31.0.1')).toBe(true);
expect(isPrivateIpv4Host('172.15.0.1')).toBe(false);
expect(getStaticMediaHeaders('.mp3', '/audio/song.mp3')).toEqual(
expect.objectContaining({ contentType: 'audio/mpeg', acceptRanges: true }),
);
expect(getStaticMediaHeaders('.gif')).toEqual(expect.objectContaining({ contentType: 'image/gif' }));
expect(getStaticMediaHeaders('.m3u8')).toEqual(
expect.objectContaining({ contentType: 'application/vnd.apple.mpegurl', acceptRanges: true }),
);
expect(getStaticMediaHeaders('.m4s')).toEqual(expect.objectContaining({ contentType: 'video/iso.segment' }));
expect(getStaticMediaHeaders('.ts')).toEqual(expect.objectContaining({ contentType: 'video/mp2t' }));
expect(getStaticMediaHeaders('.unknown')).toEqual({});
});
it('boots the production stack with security, local media, Redis sockets, and Swagger', async () => {
const { app, logger, httpServer } = build();
await bootstrap();
expect(NestFactory.create).toHaveBeenCalledWith(expect.any(Function), {
bufferLogs: true,
bodyParser: false,
});
expect(mkdirSync).toHaveBeenCalledWith(expect.stringMatching(/uploads$/), { recursive: true });
expect(app.enableCors).toHaveBeenCalledWith(expect.objectContaining({ credentials: true }));
expect(app.setGlobalPrefix).toHaveBeenCalledWith('api/v1');
expect(app.useGlobalPipes).toHaveBeenCalled();
expect(app.useGlobalInterceptors).toHaveBeenCalled();
expect(app.listen).toHaveBeenCalledWith(4000, '0.0.0.0');
expect(configureHttpServer).toHaveBeenCalledWith(httpServer, expect.anything());
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining('Mobile devices on the LAN'), 'Bootstrap');
expect(RedisIoAdapter).toHaveBeenCalled();
const adapter = (RedisIoAdapter as unknown as jest.Mock).mock.results[0].value;
expect(adapter.connectToRedis).toHaveBeenCalled();
expect(app.useWebSocketAdapter).toHaveBeenCalledWith(adapter);
expect(SwaggerModule.createDocument).toHaveBeenCalled();
expect(SwaggerModule.setup).toHaveBeenCalledWith('docs', app, expect.anything());
const middleware = app.use.mock.calls
.filter((call) => typeof call[0] === 'function')
.map((call) => call[0]);
expect(middleware).toHaveLength(2);
const setHeader = jest.fn();
const next = jest.fn();
middleware[0]({}, { setHeader } as any, next);
expect(setHeader).toHaveBeenCalledWith('Strict-Transport-Security', expect.any(String));
let finish: (() => void) | undefined;
const request = { headers: { 'x-request-id': 'invalid id' }, method: 'GET', originalUrl: '/health' } as any;
const response = {
statusCode: 200,
setHeader,
on: jest.fn((_event: string, listener: () => void) => { finish = listener; }),
} as any;
middleware[1](request, response, next);
finish?.();
expect(request.headers['x-request-id']).toEqual(expect.any(String));
expect(logger.logHttp).toHaveBeenCalledWith(expect.objectContaining({ method: 'GET', statusCode: 200 }));
const suppliedIdRequest = {
headers: { 'x-request-id': 'mobile-client:request-1' },
method: 'GET',
originalUrl: '/health',
} as any;
middleware[1](suppliedIdRequest, response, next);
expect(suppliedIdRequest.headers['x-request-id']).toBe('mobile-client:request-1');
const staticOptions = (express.static as unknown as jest.Mock).mock.calls[0][1];
const staticHeader = jest.fn();
staticOptions.setHeaders({ setHeader: staticHeader }, '/uploads/stream.m3u8');
expect(staticHeader).toHaveBeenCalledWith('Content-Type', 'application/vnd.apple.mpegurl');
expect(staticHeader).toHaveBeenCalledWith('Accept-Ranges', 'bytes');
});
it('boots without optional integrations and warns about a mismatched private public URL', async () => {
const { app, logger } = build({
'cors.origins': [],
nodeEnv: 'development',
'performance.compressionEnabled': false,
'storage.provider': 's3',
publicBaseUrl: 'http://192.168.1.99:4000',
responseEnvelopeEnabled: false,
'redis.enabled': false,
'redis.socketAdapterEnabled': false,
'swagger.enabled': false,
'email.enabled': false,
'email.smtpHost': '',
'email.smtpUser': '',
'email.fromEmail': '',
});
await bootstrap();
expect(mkdirSync).not.toHaveBeenCalled();
expect(app.enableCors).toHaveBeenCalledWith(expect.objectContaining({ origin: true, credentials: true }));
expect(app.useGlobalInterceptors).not.toHaveBeenCalled();
expect(app.useWebSocketAdapter).not.toHaveBeenCalled();
expect(SwaggerModule.setup).not.toHaveBeenCalled();
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining('not assigned to the current machine'), 'Bootstrap');
});
});