import { Test, TestingModule } from '@nestjs/testing'; import { ConfigService } from '@nestjs/config'; import * as path from 'path'; import { BuildService } from './build.service'; import { Application } from '../applications/entities/application.entity'; import { AppRuntime } from '../common/enums'; import { ClustersService } from '../clusters/clusters.service'; import { RegistryService } from '../kubernetes/registry.service'; import { BuildProgressStore } from './build-progress.store'; import { SourceStorageService } from '../storage/source-storage.service'; describe('BuildService', () => { let service: BuildService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ BuildService, { provide: ConfigService, useValue: { get: jest.fn((key: string) => { const map: Record = { 'build.namespace': 'cloudhost-builds', 'build.serviceAccount': 'kaniko-builder', 'registry.url': 'registry.local:5000', }; return map[key]; }), }, }, { provide: ClustersService, useValue: {} }, { provide: BuildProgressStore, useValue: { get: jest.fn(), set: jest.fn(), clear: jest.fn() }, }, { provide: RegistryService, useValue: {} }, { provide: SourceStorageService, useValue: { isObjectStorage: () => false, materializeToTempFile: jest.fn(), getSize: jest.fn(), }, }, ], }).compile(); service = module.get(BuildService); }); describe('generateDockerfile', () => { it('generates Go Dockerfile with requested runtime version', () => { const app = { runtime: AppRuntime.GO, runtimeVersion: '1.22', port: 8080, } as Application; const dockerfile = (service as any).generateDockerfile(app) as string; expect(dockerfile).toContain('FROM golang:1.22-alpine'); expect(dockerfile).toContain('EXPOSE 8080'); }); it('generates Go Dockerfile with cmd package when present in archive entries', () => { const app = { runtime: AppRuntime.GO, runtimeVersion: '1.22', port: 8080, } as Application; const dockerfile = (service as any).generateDockerfile(app, [ 'go.mod', 'cmd/server/main.go', ]) as string; expect(dockerfile).toContain('go build -a -installsuffix cgo -ldflags="-w -s" -o main ./cmd/server'); }); it('generates Node.js Dockerfile with default port', () => { const app = { runtime: AppRuntime.NODEJS, runtimeVersion: '20', } as Application; const dockerfile = (service as any).generateDockerfile(app) as string; expect(dockerfile).toContain('FROM node:20'); expect(dockerfile).toContain('EXPOSE 3000'); }); it('generates Laravel Dockerfile with artisan migrate', () => { const app = { runtime: AppRuntime.LARAVEL, phpVersion: '8.3', } as Application; const dockerfile = (service as any).generateDockerfile(app) as string; expect(dockerfile).toContain('php:8.3'); expect(dockerfile).toContain('artisan migrate'); }); it('generates WordPress Dockerfile with official image', () => { const app = { runtime: AppRuntime.WORDPRESS, runtimeVersion: '6.4', } as Application; const dockerfile = (service as any).generateDockerfile(app) as string; expect(dockerfile).toContain('wordpress:6.4'); }); it('generates Django Dockerfile with detected settings module', () => { const app = { runtime: AppRuntime.DJANGO, runtimeVersion: '3.12', } as Application; const dockerfile = (service as any).generateDockerfile(app, ['myproject/settings.py']) as string; expect(dockerfile).toContain('DJANGO_SETTINGS_MODULE=myproject.settings'); expect(dockerfile).toContain('gunicorn'); }); it('generates .NET Dockerfile that restores nested csproj', () => { const app = { runtime: AppRuntime.DOTNET, runtimeVersion: '8.0', } as Application; const dockerfile = (service as any).generateDockerfile(app, ['src/App/App.csproj']) as string; expect(dockerfile).toContain('CSPROJ="src/App/App.csproj"'); expect(dockerfile).toContain('dotnet publish "$CSPROJ"'); }); }); describe('egressProxyEnvFrom', () => { it('returns secretRef when BUILD_EGRESS_PROXY_SECRET is set', () => { const config = (service as any).configService as { get: jest.Mock }; config.get.mockImplementation((key: string) => { if (key === 'build.egressProxySecret') return 'registry-egress-proxy'; return undefined; }); expect((service as any).egressProxyEnvFrom()).toEqual([ { secretRef: { name: 'registry-egress-proxy' } }, ]); }); it('returns undefined when egress proxy is disabled', () => { const config = (service as any).configService as { get: jest.Mock }; config.get.mockImplementation((key: string) => { if (key === 'build.egressProxySecret') return ''; return undefined; }); expect((service as any).egressProxyEnvFrom()).toBeUndefined(); expect((service as any).withEgressProxy({ name: 'kaniko' })).toEqual({ name: 'kaniko' }); }); }); });