122 lines
4.1 KiB
TypeScript
122 lines
4.1 KiB
TypeScript
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
|
import { SmartProxy } from '../ts/index.js';
|
|
|
|
// Test that certificate provisioning is deferred until after ports are listening
|
|
tap.test('should defer certificate provisioning until ports are ready', async (tapTest) => {
|
|
// Track when operations happen
|
|
let portsListening = false;
|
|
let certProvisioningStarted = false;
|
|
let operationOrder: string[] = [];
|
|
|
|
// Create proxy with certificate route but without real ACME
|
|
const proxy = new SmartProxy({
|
|
routes: [{
|
|
name: 'test-route',
|
|
match: {
|
|
ports: 8443,
|
|
domains: ['test.local']
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
target: { host: 'localhost', port: 8181 },
|
|
tls: {
|
|
mode: 'terminate',
|
|
certificate: 'auto',
|
|
acme: {
|
|
email: 'test@local.dev',
|
|
useProduction: false
|
|
}
|
|
}
|
|
}
|
|
}]
|
|
});
|
|
|
|
// Override the certificate manager creation to avoid real ACME
|
|
const originalCreateCertManager = proxy['createCertificateManager'];
|
|
proxy['createCertificateManager'] = async function(...args: any[]) {
|
|
console.log('Creating mock cert manager');
|
|
operationOrder.push('create-cert-manager');
|
|
const mockCertManager = {
|
|
certStore: null,
|
|
smartAcme: null,
|
|
httpProxy: null,
|
|
renewalTimer: null,
|
|
pendingChallenges: new Map(),
|
|
challengeRoute: null,
|
|
certStatus: new Map(),
|
|
globalAcmeDefaults: null,
|
|
updateRoutesCallback: undefined,
|
|
challengeRouteActive: false,
|
|
isProvisioning: false,
|
|
acmeStateManager: null,
|
|
initialize: async () => {
|
|
operationOrder.push('cert-manager-init');
|
|
console.log('Mock cert manager initialized');
|
|
},
|
|
provisionAllCertificates: async () => {
|
|
operationOrder.push('cert-provisioning');
|
|
certProvisioningStarted = true;
|
|
// Check that ports are listening when provisioning starts
|
|
if (!portsListening) {
|
|
throw new Error('Certificate provisioning started before ports ready!');
|
|
}
|
|
console.log('Mock certificate provisioning (ports are ready)');
|
|
},
|
|
stop: async () => {},
|
|
setHttpProxy: () => {},
|
|
setGlobalAcmeDefaults: () => {},
|
|
setAcmeStateManager: () => {},
|
|
setUpdateRoutesCallback: () => {},
|
|
getAcmeOptions: () => ({}),
|
|
getState: () => ({ challengeRouteActive: false }),
|
|
getCertStatus: () => new Map(),
|
|
checkAndRenewCertificates: async () => {},
|
|
addChallengeRoute: async () => {},
|
|
removeChallengeRoute: async () => {},
|
|
getCertificate: async () => null,
|
|
isValidCertificate: () => false,
|
|
waitForProvisioning: async () => {}
|
|
} as any;
|
|
|
|
// Call initialize immediately as the real createCertificateManager does
|
|
await mockCertManager.initialize();
|
|
|
|
return mockCertManager;
|
|
};
|
|
|
|
// Track port manager operations
|
|
const originalAddPorts = proxy['portManager'].addPorts;
|
|
proxy['portManager'].addPorts = async function(ports: number[]) {
|
|
operationOrder.push('ports-starting');
|
|
const result = await originalAddPorts.call(this, ports);
|
|
operationOrder.push('ports-ready');
|
|
portsListening = true;
|
|
console.log('Ports are now listening');
|
|
return result;
|
|
};
|
|
|
|
// Start the proxy
|
|
await proxy.start();
|
|
|
|
// Log the operation order for debugging
|
|
console.log('Operation order:', operationOrder);
|
|
|
|
// Verify operations happened in the correct order
|
|
expect(operationOrder).toContain('create-cert-manager');
|
|
expect(operationOrder).toContain('cert-manager-init');
|
|
expect(operationOrder).toContain('ports-starting');
|
|
expect(operationOrder).toContain('ports-ready');
|
|
expect(operationOrder).toContain('cert-provisioning');
|
|
|
|
// Verify ports were ready before certificate provisioning
|
|
const portsReadyIndex = operationOrder.indexOf('ports-ready');
|
|
const certProvisioningIndex = operationOrder.indexOf('cert-provisioning');
|
|
|
|
expect(portsReadyIndex).toBeLessThan(certProvisioningIndex);
|
|
expect(certProvisioningStarted).toEqual(true);
|
|
expect(portsListening).toEqual(true);
|
|
|
|
await proxy.stop();
|
|
});
|
|
|
|
tap.start(); |