test(09-01): add failing spec for cert-manager seed + helpers (RED)

- Test: seedCertManagerModule calls seedModule with slug='cert-manager',
  category='security-tools', isSystem=true
- Test: detectFormat returns pem/der/pfx/p7b based on extension + content sniff
- Test: getFingerprint returns uppercase colon-separated hex (sha1 + sha256)
- Test: parsePemChain returns array of length 2 for two concatenated PEMs
This commit is contained in:
2026-07-01 23:18:08 +02:00
parent a13a8a763f
commit a06694f915
@@ -0,0 +1,130 @@
import * as forge from 'node-forge';
import { beforeAll, describe, expect, it, vi } from 'vitest';
import { seedCertManagerModule } from './cert-manager.seed';
import { CertManagerService } from './cert-manager.service';
// ---------------------------------------------------------------------------
// Test helpers
// ---------------------------------------------------------------------------
/** Generate a self-signed X.509 cert via node-forge (RSA 1024 — fast for tests) */
function generateSelfSignedCert(): forge.pki.Certificate {
const keys = forge.pki.rsa.generateKeyPair(1024);
const cert = forge.pki.createCertificate();
cert.publicKey = keys.publicKey;
cert.serialNumber = '01';
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
const attrs = [{ name: 'commonName', value: 'test.example.com' }];
cert.setSubject(attrs);
cert.setIssuer(attrs);
cert.sign(keys.privateKey, forge.md.sha256.create());
return cert;
}
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
describe('seedCertManagerModule', () => {
it('calls moduleRegistryService.seedModule once with cert-manager slug', async () => {
const mockSeedModule = vi.fn().mockResolvedValue(undefined);
const mockModuleRegistryService = { seedModule: mockSeedModule } as any;
await seedCertManagerModule(mockModuleRegistryService);
expect(mockSeedModule).toHaveBeenCalledTimes(1);
const arg = mockSeedModule.mock.calls[0][0];
expect(arg.slug).toBe('cert-manager');
expect(arg.category).toBe('security-tools');
expect(arg.isSystem).toBe(true);
});
});
describe('CertManagerService helpers', () => {
let service: CertManagerService;
let testCert: forge.pki.Certificate;
beforeAll(() => {
service = new CertManagerService();
testCert = generateSelfSignedCert();
});
// -------------------------------------------------------------------------
// detectFormat
// -------------------------------------------------------------------------
describe('detectFormat', () => {
it('returns "pfx" for .pfx extension', () => {
const buf = Buffer.from([0x30, 0x82]); // arbitrary binary
expect(service.detectFormat('cert.pfx', buf)).toBe('pfx');
});
it('returns "p7b" for .p7b extension', () => {
const buf = Buffer.from([0x30, 0x82]);
expect(service.detectFormat('cert.p7b', buf)).toBe('p7b');
});
it('returns "der" for .der extension', () => {
const buf = Buffer.from([0x30, 0x82]);
expect(service.detectFormat('cert.der', buf)).toBe('der');
});
it('returns "pem" for .pem extension', () => {
const buf = Buffer.from('-----BEGIN CERTIFICATE-----\nfake\n-----END CERTIFICATE-----');
expect(service.detectFormat('cert.pem', buf)).toBe('pem');
});
it('returns "pem" for .cer extension with PEM content', () => {
const buf = Buffer.from('-----BEGIN CERTIFICATE-----\nfake\n-----END CERTIFICATE-----');
expect(service.detectFormat('cert.cer', buf)).toBe('pem');
});
it('returns "der" for .cer extension with binary (non-PEM) content', () => {
const buf = Buffer.from([0x30, 0x82, 0x01, 0x00]);
expect(service.detectFormat('cert.cer', buf)).toBe('der');
});
});
// -------------------------------------------------------------------------
// getFingerprint
// -------------------------------------------------------------------------
describe('getFingerprint', () => {
it('returns uppercase colon-separated hex for sha256', () => {
const fp = service.getFingerprint(testCert, 'sha256');
// e.g. "AA:BB:CC:..."
expect(fp).toMatch(/^[0-9A-F]{2}(:[0-9A-F]{2})+$/);
});
it('returns uppercase colon-separated hex for sha1', () => {
const fp = service.getFingerprint(testCert, 'sha1');
expect(fp).toMatch(/^[0-9A-F]{2}(:[0-9A-F]{2})+$/);
});
});
// -------------------------------------------------------------------------
// parsePemChain
// -------------------------------------------------------------------------
describe('parsePemChain', () => {
it('returns array of length 2 for two concatenated cert PEMs', () => {
const cert1 = generateSelfSignedCert();
const cert2 = generateSelfSignedCert();
const pem1 = forge.pki.certificateToPem(cert1);
const pem2 = forge.pki.certificateToPem(cert2);
const chain = pem1 + '\n' + pem2;
const parsed = service.parsePemChain(chain);
expect(parsed).toHaveLength(2);
});
it('returns array of length 1 for a single PEM', () => {
const pem = forge.pki.certificateToPem(testCert);
const parsed = service.parsePemChain(pem);
expect(parsed).toHaveLength(1);
});
});
});