test(09-05): add failing convertCert spec (RED)

- PEM→DER round-trip identity test (re-parses DER base64 → verify CN)
- DER→PEM round-trip identity test (re-parses PEM base64 → verify CN)
- PEM→P7B: asserts mimeType + P7B contains ≥1 cert
- malformed input: expects BadRequestException
- All 4 fail against NotImplementedException stub (RED confirmed)
This commit is contained in:
2026-07-02 07:35:51 +02:00
parent a1da5d9083
commit 37db58b816
@@ -322,3 +322,90 @@ describe('splitCerts', () => {
).rejects.toThrow(BadRequestException);
});
});
// ---------------------------------------------------------------------------
// convertCert — RED tests (CERT-04)
// ---------------------------------------------------------------------------
describe('convertCert', () => {
let service: CertManagerService;
let certPem: string;
let certDerBuffer: Buffer;
const CN = 'convert.example.com';
beforeAll(() => {
service = new CertManagerService();
// RSA-1024 self-signed cert (fast for tests)
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: CN }];
cert.setSubject(attrs);
cert.setIssuer(attrs);
cert.sign(keys.privateKey, forge.md.sha256.create());
// PEM fixture
certPem = forge.pki.certificateToPem(cert);
// DER fixture — binary encoding required (Pitfall 1)
const derBytes = forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes();
certDerBuffer = Buffer.from(derBytes, 'binary');
}, 15000);
it('PEM→DER: returns FileResponse with correct mimeType and round-trip identity', async () => {
// RED: convertCert throws NotImplementedException — this test will FAIL
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const result = await (service.convertCert({ pemText: certPem, targetFormat: 'der' } as any) as Promise<any>);
expect(result.mimeType).toBe('application/x-x509-ca-cert');
expect(result.filename).toContain('converted');
expect(result.content).toBeTruthy();
// Round-trip identity: decode base64 DER → re-parse → verify CN matches original
const derBuf = Buffer.from(result.content as string, 'base64');
const asn1 = forge.asn1.fromDer(forge.util.createBuffer(derBuf.toString('binary')));
const reparsed = forge.pki.certificateFromAsn1(asn1);
expect(reparsed.subject.getField('CN')?.value).toBe(CN);
});
it('DER→PEM: returned PEM parses to cert with same CN (round-trip identity)', async () => {
// RED: convertCert throws NotImplementedException — this test will FAIL
const result = await (service.convertCert({
file: { originalname: 'c.der', buffer: certDerBuffer },
targetFormat: 'pem',
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any) as Promise<any>);
expect(result.mimeType).toBe('application/x-pem-file');
// Decode base64 PEM content → parse → verify CN matches original
const pemStr = Buffer.from(result.content as string, 'base64').toString('utf-8');
const reparsed = forge.pki.certificateFromPem(pemStr);
expect(reparsed.subject.getField('CN')?.value).toBe(CN);
});
it('PEM→P7B: returned P7B contains the original certificate', async () => {
// RED: convertCert throws NotImplementedException — this test will FAIL
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const result = await (service.convertCert({ pemText: certPem, targetFormat: 'p7b' } as any) as Promise<any>);
expect(result.mimeType).toBe('application/x-pkcs7-certificates');
expect(result.filename).toContain('converted');
// Decode base64 P7B (PEM-wrapped PKCS7) and verify at least 1 cert enclosed
const p7bContent = Buffer.from(result.content as string, 'base64').toString('utf-8');
const p7 = forge.pkcs7.messageFromPem(p7bContent);
expect((p7.certificates as forge.pki.Certificate[]).length).toBeGreaterThanOrEqual(1);
});
it('throws BadRequestException for malformed PEM input', async () => {
// RED: convertCert throws NotImplementedException (not BadRequestException) — FAIL
await expect(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
service.convertCert({ pemText: 'garbage input not a cert', targetFormat: 'der' } as any),
).rejects.toThrow(BadRequestException);
});
});