94 lines
3.0 KiB
JavaScript
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');
|
|
});
|
|
});
|