Files
cloud-host/backend/src/kubernetes/helm.service.spec.ts
T
keyhan c42557a86b feat(k8s): add HelmService and rewrite deleteApplication
- New HelmService wrapping Helm CLI (install/upgrade, rollback, uninstall, history, status)
- deleteApplication: helm uninstall + explicit cleanup of kept PVCs, secrets, TLS certs
- buildHelmValues: include registry.url for pull secret
- Add scaleDeployment for lifecycle suspend/resume
- Unit tests for buildHelmValues and HelmService
2026-04-22 16:43:45 +03:30

87 lines
2.8 KiB
TypeScript

import { Test, TestingModule } from '@nestjs/testing';
import { HelmService } from './helm.service';
import * as fs from 'fs';
import * as path from 'path';
describe('HelmService', () => {
let service: HelmService;
let writeSpy: jest.SpyInstance;
beforeEach(async () => {
jest.clearAllMocks();
writeSpy = jest.spyOn(fs.promises, 'writeFile').mockResolvedValue(undefined);
const module: TestingModule = await Test.createTestingModule({
providers: [HelmService],
}).compile();
service = module.get<HelmService>(HelmService);
});
afterEach(() => {
writeSpy.mockRestore();
});
it('should be defined', () => {
expect(service).toBeDefined();
});
describe('chartPath', () => {
it('should resolve to helm/cloudhost-app relative to project root', () => {
const expectedSuffix = path.join('helm', 'cloudhost-app');
expect((service as any).chartPath).toContain(expectedSuffix);
});
});
describe('writeTempKubeconfig', () => {
it('should write kubeconfig with mode 0o600', async () => {
const result = await (service as any).writeTempKubeconfig('apiVersion: v1\nclusters: []');
expect(writeSpy).toHaveBeenCalledWith(
expect.stringContaining('cloudhost-kube-'),
'apiVersion: v1\nclusters: []',
{ mode: 0o600 },
);
expect(typeof result).toBe('string');
});
});
describe('writeTempValues', () => {
it('should write values as JSON with mode 0o600', async () => {
const values = { app: { name: 'test' } };
const result = await (service as any).writeTempValues(values);
expect(writeSpy).toHaveBeenCalledWith(
expect.stringContaining('cloudhost-vals-'),
JSON.stringify(values, null, 2),
{ mode: 0o600 },
);
expect(result).toContain('.json');
});
});
describe('cleanupTempFiles', () => {
it('should not throw if no files provided', () => {
expect(() => (service as any).cleanupTempFiles()).not.toThrow();
});
});
describe('history - parsing', () => {
it('should map app_version to appVersion', () => {
const raw = [
{ revision: 1, updated: '2024-01-01', status: 'deployed', chart: 'cloudhost-app-0.1.0', app_version: '1.0.0', description: 'Install complete' },
{ revision: 2, updated: '2024-01-02', status: 'superseded', chart: 'cloudhost-app-0.1.0', app_version: '1.0.0', description: 'Upgrade complete' },
];
const mapped = raw.map((r) => ({
revision: r.revision,
updated: r.updated,
status: r.status,
chart: r.chart,
appVersion: r.app_version,
description: r.description,
}));
expect(mapped[0].appVersion).toBe('1.0.0');
expect(mapped[1].revision).toBe(2);
expect(mapped).toHaveLength(2);
});
});
});