import { INestApplication } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { SwaggerModule } from '@nestjs/swagger'; import { AppController } from '../../app.controller'; import { AppService } from '../../app.service'; import { AuthController } from '../../modules/auth/auth.controller'; import { AuthService } from '../../modules/auth/auth.service'; import { PrivilegesService } from '../../modules/privileges/privileges.service'; import { UsersService } from '../../modules/users/users.service'; import { createOpenApiDocument, isSwaggerEnabled, setupSwagger, } from './setup-swagger'; describe('isSwaggerEnabled', () => { it('is disabled in production by default', () => { expect(isSwaggerEnabled({ NODE_ENV: 'production' })).toBe(false); }); it('is enabled in production when SWAGGER_ENABLED=true', () => { expect( isSwaggerEnabled({ NODE_ENV: 'production', SWAGGER_ENABLED: 'true', }), ).toBe(true); }); it('is enabled when not production', () => { expect(isSwaggerEnabled({ NODE_ENV: 'development' })).toBe(true); }); it('is disabled when SWAGGER_ENABLED=false', () => { expect( isSwaggerEnabled({ NODE_ENV: 'development', SWAGGER_ENABLED: 'false', }), ).toBe(false); }); }); describe('createOpenApiDocument', () => { let app: INestApplication; beforeAll(async () => { const moduleRef: TestingModule = await Test.createTestingModule({ controllers: [AppController, AuthController], providers: [ AppService, { provide: AuthService, useValue: { register: jest.fn(), login: jest.fn(), refresh: jest.fn(), revoke: jest.fn(), }, }, { provide: UsersService, useValue: { findById: jest.fn() }, }, { provide: PrivilegesService, useValue: { findPrivilegeSummary: jest.fn(), getPermissionsMap: jest.fn(), }, }, ], }).compile(); app = moduleRef.createNestApplication(); await app.init(); }); afterAll(async () => { await app.close(); }); it('includes auth and app paths with bearer scheme', () => { const document = createOpenApiDocument(app); expect(document.info.title).toBe('Tracking API'); expect(document.paths['/auth/login']).toBeDefined(); expect(document.paths['/auth/me']).toBeDefined(); expect(document.paths['/']).toBeDefined(); expect(document.components?.securitySchemes?.['access-token']).toEqual( expect.objectContaining({ type: 'http', scheme: 'bearer' }), ); }); it('requires bearer on /auth/me but not on public auth posts', () => { const document = createOpenApiDocument(app); expect(document.paths['/auth/me']?.get?.security).toEqual([ { 'access-token': [] }, ]); expect(document.paths['/auth/login']?.post?.security).toBeUndefined(); expect(document.paths['/auth/register']?.post?.security).toBeUndefined(); }); }); describe('setupSwagger', () => { let app: INestApplication; let setupSpy: jest.SpyInstance; beforeAll(async () => { const moduleRef: TestingModule = await Test.createTestingModule({ controllers: [AppController], providers: [AppService], }).compile(); app = moduleRef.createNestApplication(); await app.init(); }); afterAll(async () => { await app.close(); }); beforeEach(() => { setupSpy = jest .spyOn(SwaggerModule, 'setup') .mockImplementation(() => undefined); }); afterEach(() => { setupSpy.mockRestore(); }); it('skips mounting when swagger is disabled', () => { setupSwagger(app, { NODE_ENV: 'production', }); expect(setupSpy).not.toHaveBeenCalled(); }); it('mounts at /docs when swagger is enabled', () => { setupSwagger(app, { NODE_ENV: 'test', }); expect(setupSpy).toHaveBeenCalledWith( 'docs', app, expect.any(Object), expect.objectContaining({ jsonDocumentUrl: 'docs-json' }), ); }); });