116 lines
3.6 KiB
TypeScript
116 lines
3.6 KiB
TypeScript
import { APP_GUARD } from '@nestjs/core';
|
||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||
import { MODULE_METADATA } from '@nestjs/common/constants';
|
||
import { Test } from '@nestjs/testing';
|
||
import {
|
||
getOptionsToken,
|
||
ThrottlerGuard,
|
||
ThrottlerModule,
|
||
} from '@nestjs/throttler';
|
||
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard';
|
||
import { AppModule } from 'src/app.module';
|
||
|
||
type DynamicModuleLike = {
|
||
module?: unknown;
|
||
global?: boolean;
|
||
providers?: Array<{
|
||
provide?: unknown;
|
||
useClass?: unknown;
|
||
useValue?: unknown;
|
||
}>;
|
||
};
|
||
|
||
type AppImportEntry = DynamicModuleLike | Promise<DynamicModuleLike>;
|
||
|
||
describe('AppModule конфигурация', () => {
|
||
afterEach(() => {
|
||
delete process.env.ALLOWED_ORIGINS;
|
||
delete process.env.JWT_SECRET;
|
||
});
|
||
|
||
it('должен регистрировать ThrottlerModule с лимитом 5/60000ms', () => {
|
||
const imports = (Reflect.getMetadata(MODULE_METADATA.IMPORTS, AppModule) ??
|
||
[]) as DynamicModuleLike[];
|
||
const throttlerDynamicModule = imports.find(
|
||
(entry) => entry.module === ThrottlerModule,
|
||
);
|
||
|
||
expect(throttlerDynamicModule).toBeDefined();
|
||
const throttlerOptionsProvider = throttlerDynamicModule?.providers?.find(
|
||
(provider) => provider.provide === getOptionsToken(),
|
||
);
|
||
expect(throttlerOptionsProvider).toBeDefined();
|
||
expect(throttlerOptionsProvider?.useValue).toEqual(
|
||
expect.arrayContaining([
|
||
expect.objectContaining({
|
||
limit: 5,
|
||
ttl: 60000,
|
||
}),
|
||
]),
|
||
);
|
||
});
|
||
|
||
it('должен регистрировать ThrottlerGuard и JwtAuthGuard как глобальные guards', () => {
|
||
const providers = (Reflect.getMetadata(
|
||
MODULE_METADATA.PROVIDERS,
|
||
AppModule,
|
||
) ?? []) as DynamicModuleLike['providers'];
|
||
|
||
expect(providers).toEqual(
|
||
expect.arrayContaining([
|
||
expect.objectContaining({
|
||
provide: APP_GUARD,
|
||
useClass: ThrottlerGuard,
|
||
}),
|
||
expect.objectContaining({
|
||
provide: APP_GUARD,
|
||
useClass: JwtAuthGuard,
|
||
}),
|
||
]),
|
||
);
|
||
});
|
||
|
||
it('должен подключать ConfigModule как глобальный', async () => {
|
||
const imports = (Reflect.getMetadata(MODULE_METADATA.IMPORTS, AppModule) ??
|
||
[]) as AppImportEntry[];
|
||
const resolvedImports = await Promise.all(
|
||
imports.map((entry) =>
|
||
entry instanceof Promise ? entry : Promise.resolve(entry),
|
||
),
|
||
);
|
||
const configDynamicModule = resolvedImports.find(
|
||
(entry) => entry.module === ConfigModule,
|
||
);
|
||
|
||
expect(configDynamicModule).toBeDefined();
|
||
expect(configDynamicModule?.global).toBe(true);
|
||
});
|
||
|
||
it('должен делать ConfigService доступным и читать ALLOWED_ORIGINS из env', async () => {
|
||
process.env.ALLOWED_ORIGINS = 'http://test.local:8080,http://localhost';
|
||
|
||
const moduleRef = await Test.createTestingModule({
|
||
imports: [
|
||
ConfigModule.forRoot({
|
||
isGlobal: true,
|
||
ignoreEnvFile: true,
|
||
}),
|
||
],
|
||
}).compile();
|
||
|
||
const configService = moduleRef.get<ConfigService>(ConfigService);
|
||
expect(configService).toBeDefined();
|
||
expect(configService.get<string>('ALLOWED_ORIGINS')).toBe(
|
||
'http://test.local:8080,http://localhost',
|
||
);
|
||
});
|
||
|
||
it('должен использовать достаточно длинный JWT_SECRET в тестовых env', () => {
|
||
process.env.JWT_SECRET = 'test-secret-key-for-jwt-signing-1234567890';
|
||
|
||
const jwtSecret = process.env.JWT_SECRET;
|
||
expect(jwtSecret).toBeDefined();
|
||
expect(jwtSecret?.length).toBeGreaterThanOrEqual(32);
|
||
});
|
||
});
|