This commit is contained in:
136
test/unit/cotSsl.spec.js
Normal file
136
test/unit/cotSsl.spec.js
Normal file
@@ -0,0 +1,136 @@
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
||||
import { existsSync, writeFileSync, mkdirSync, unlinkSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import { tmpdir } from 'node:os'
|
||||
import {
|
||||
TRUSTSTORE_PASSWORD,
|
||||
DEFAULT_COT_PORT,
|
||||
getCotPort,
|
||||
COT_TLS_REQUIRED_MESSAGE,
|
||||
getCotSslPaths,
|
||||
buildP12FromCertPath,
|
||||
} from '../../server/utils/cotSsl.js'
|
||||
import { withTemporaryEnv } from '../helpers/env.js'
|
||||
|
||||
describe('cotSsl', () => {
|
||||
let testCertDir
|
||||
let testCertPath
|
||||
let testKeyPath
|
||||
|
||||
beforeEach(() => {
|
||||
testCertDir = join(tmpdir(), `kestrelos-test-${Date.now()}`)
|
||||
mkdirSync(testCertDir, { recursive: true })
|
||||
testCertPath = join(testCertDir, 'cert.pem')
|
||||
testKeyPath = join(testCertDir, 'key.pem')
|
||||
writeFileSync(testCertPath, '-----BEGIN CERTIFICATE-----\nTEST\n-----END CERTIFICATE-----\n')
|
||||
writeFileSync(testKeyPath, '-----BEGIN PRIVATE KEY-----\nTEST\n-----END PRIVATE KEY-----\n')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
try {
|
||||
if (existsSync(testCertPath)) unlinkSync(testCertPath)
|
||||
if (existsSync(testKeyPath)) unlinkSync(testKeyPath)
|
||||
}
|
||||
catch {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
})
|
||||
|
||||
describe('constants', () => {
|
||||
it.each([
|
||||
['TRUSTSTORE_PASSWORD', TRUSTSTORE_PASSWORD, 'kestrelos'],
|
||||
['DEFAULT_COT_PORT', DEFAULT_COT_PORT, 8089],
|
||||
])('exports %s', (name, value, expected) => {
|
||||
expect(value).toBe(expected)
|
||||
})
|
||||
|
||||
it('exports COT_TLS_REQUIRED_MESSAGE', () => {
|
||||
expect(COT_TLS_REQUIRED_MESSAGE).toContain('SSL')
|
||||
})
|
||||
})
|
||||
|
||||
describe('getCotPort', () => {
|
||||
it.each([
|
||||
[{ COT_PORT: undefined }, DEFAULT_COT_PORT],
|
||||
[{ COT_PORT: '9999' }, 9999],
|
||||
[{ COT_PORT: '8080' }, 8080],
|
||||
])('returns correct port for env: %j', (env, expected) => {
|
||||
withTemporaryEnv(env, () => {
|
||||
expect(getCotPort()).toBe(expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getCotSslPaths', () => {
|
||||
it('returns paths from env vars when available, otherwise checks default locations', () => {
|
||||
withTemporaryEnv({ COT_SSL_CERT: undefined, COT_SSL_KEY: undefined }, () => {
|
||||
const result = getCotSslPaths()
|
||||
if (result !== null) {
|
||||
expect(result).toMatchObject({
|
||||
certPath: expect.any(String),
|
||||
keyPath: expect.any(String),
|
||||
})
|
||||
}
|
||||
else {
|
||||
expect(result).toBeNull()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('returns paths from COT_SSL_CERT and COT_SSL_KEY env vars', () => {
|
||||
withTemporaryEnv({ COT_SSL_CERT: testCertPath, COT_SSL_KEY: testKeyPath }, () => {
|
||||
expect(getCotSslPaths()).toEqual({ certPath: testCertPath, keyPath: testKeyPath })
|
||||
})
|
||||
})
|
||||
|
||||
it('returns paths from config parameter when env vars not set', () => {
|
||||
withTemporaryEnv({ COT_SSL_CERT: undefined, COT_SSL_KEY: undefined }, () => {
|
||||
const config = { cotSslCert: testCertPath, cotSslKey: testKeyPath }
|
||||
expect(getCotSslPaths(config)).toEqual({ certPath: testCertPath, keyPath: testKeyPath })
|
||||
})
|
||||
})
|
||||
|
||||
it('prefers env vars over config parameter', () => {
|
||||
withTemporaryEnv({ COT_SSL_CERT: testCertPath, COT_SSL_KEY: testKeyPath }, () => {
|
||||
const config = { cotSslCert: '/other/cert.pem', cotSslKey: '/other/key.pem' }
|
||||
expect(getCotSslPaths(config)).toEqual({ certPath: testCertPath, keyPath: testKeyPath })
|
||||
})
|
||||
})
|
||||
|
||||
it('returns paths from config even if files do not exist', () => {
|
||||
withTemporaryEnv({ COT_SSL_CERT: undefined, COT_SSL_KEY: undefined }, () => {
|
||||
const result = getCotSslPaths({ cotSslCert: '/nonexistent/cert.pem', cotSslKey: '/nonexistent/key.pem' })
|
||||
expect(result).toEqual({ certPath: '/nonexistent/cert.pem', keyPath: '/nonexistent/key.pem' })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('buildP12FromCertPath', () => {
|
||||
it('throws error when cert file does not exist', () => {
|
||||
expect(() => {
|
||||
buildP12FromCertPath('/nonexistent/cert.pem', 'password')
|
||||
}).toThrow()
|
||||
})
|
||||
|
||||
it('throws error when openssl command fails', () => {
|
||||
const invalidCertPath = join(testCertDir, 'invalid.pem')
|
||||
writeFileSync(invalidCertPath, 'invalid cert content')
|
||||
expect(() => {
|
||||
buildP12FromCertPath(invalidCertPath, 'password')
|
||||
}).toThrow()
|
||||
})
|
||||
|
||||
it('cleans up temp file on error', () => {
|
||||
const invalidCertPath = join(testCertDir, 'invalid.pem')
|
||||
writeFileSync(invalidCertPath, 'invalid cert content')
|
||||
try {
|
||||
buildP12FromCertPath(invalidCertPath, 'password')
|
||||
}
|
||||
catch {
|
||||
// Expected to throw
|
||||
}
|
||||
// Function should clean up on error - test passes if no exception during cleanup
|
||||
expect(true).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user