Files

94 lines
3.0 KiB
JavaScript

import { describe, expect, it } from 'bun:test';
import { createTunnelService } from './index.js';
import {
TUNNEL_INTENT_EPHEMERAL_PUBLIC,
TUNNEL_MODE_QUICK,
TUNNEL_PROVIDER_CLOUDFLARE,
TUNNEL_PROVIDER_NGROK,
} from './types.js';
const createProvider = ({ provider, start, stop, resolvePublicUrl }) => ({
id: provider,
capabilities: {
provider,
modes: [{ key: TUNNEL_MODE_QUICK, intent: TUNNEL_INTENT_EPHEMERAL_PUBLIC }],
},
checkAvailability: async () => ({ available: true }),
start,
stop,
resolvePublicUrl: resolvePublicUrl || ((controller) => controller?.getPublicUrl?.() ?? null),
});
const createRegistry = (providers) => ({
get: (providerId) => providers[providerId] ?? null,
});
describe('createTunnelService', () => {
it('returns provider startup errors to route callers', async () => {
let controller = null;
const provider = createProvider({
provider: TUNNEL_PROVIDER_NGROK,
start: async () => {
throw new Error('ngrok authtoken is not configured');
},
});
const service = createTunnelService({
registry: createRegistry({ [TUNNEL_PROVIDER_NGROK]: provider }),
getController: () => controller,
setController: (next) => { controller = next; },
getActivePort: () => 3000,
});
try {
await service.start({ provider: TUNNEL_PROVIDER_NGROK, mode: TUNNEL_MODE_QUICK });
throw new Error('Expected service.start to fail');
} catch (error) {
expect(error.name).toBe('TunnelServiceError');
expect(error.code).toBe('startup_failed');
expect(error.message).toBe('ngrok authtoken is not configured');
}
});
it('replaces an active quick tunnel when the provider changes', async () => {
let stopped = false;
let ngrokStarted = false;
let controller = {
provider: TUNNEL_PROVIDER_CLOUDFLARE,
mode: TUNNEL_MODE_QUICK,
stop: () => { stopped = true; },
getPublicUrl: () => 'https://cloudflare.example',
};
const cloudflareProvider = createProvider({
provider: TUNNEL_PROVIDER_CLOUDFLARE,
start: async () => controller,
});
const ngrokProvider = createProvider({
provider: TUNNEL_PROVIDER_NGROK,
start: async () => {
ngrokStarted = true;
return {
mode: TUNNEL_MODE_QUICK,
getPublicUrl: () => 'https://demo.ngrok-free.app',
};
},
});
const service = createTunnelService({
registry: createRegistry({
[TUNNEL_PROVIDER_CLOUDFLARE]: cloudflareProvider,
[TUNNEL_PROVIDER_NGROK]: ngrokProvider,
}),
getController: () => controller,
setController: (next) => { controller = next; },
getActivePort: () => 3000,
});
const result = await service.start({ provider: TUNNEL_PROVIDER_NGROK, mode: TUNNEL_MODE_QUICK });
expect(stopped).toBe(true);
expect(ngrokStarted).toBe(true);
expect(result.provider).toBe(TUNNEL_PROVIDER_NGROK);
expect(result.publicUrl).toBe('https://demo.ngrok-free.app');
});
});