90 lines
3.0 KiB
TypeScript
90 lines
3.0 KiB
TypeScript
import { PacProxyAgent } from 'pac-proxy-agent';
|
|
import { SocksProxyAgent } from 'socks-proxy-agent';
|
|
import { ProxyAgent } from 'undici';
|
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const loadProxy = async (env: Record<string, string>) => {
|
|
vi.resetModules();
|
|
for (const [key, value] of Object.entries(env)) {
|
|
vi.stubEnv(key, value);
|
|
}
|
|
return (await import('@/utils/proxy')).default;
|
|
};
|
|
|
|
describe('proxy', () => {
|
|
afterEach(() => {
|
|
vi.clearAllTimers();
|
|
vi.useRealTimers();
|
|
vi.unstubAllEnvs();
|
|
});
|
|
|
|
it('uses PAC proxy when PAC_URI is set', async () => {
|
|
const proxy = await loadProxy({
|
|
PAC_URI: 'http://example.com/proxy.pac',
|
|
PROXY_URIS: '',
|
|
PROXY_URI: '',
|
|
});
|
|
|
|
expect(proxy.agent).toBeInstanceOf(PacProxyAgent);
|
|
expect(proxy.dispatcher).toBeNull();
|
|
expect(proxy.proxyUri).toBe('http://example.com/proxy.pac');
|
|
|
|
const current = proxy.getCurrentProxy();
|
|
expect(current?.uri).toBe('http://example.com/proxy.pac');
|
|
});
|
|
|
|
it('handles multi-proxy selection and updates after failures', async () => {
|
|
const proxy = await loadProxy({
|
|
PROXY_URIS: 'http://proxy1.local:8080,http://proxy2.local:8081',
|
|
PAC_URI: '',
|
|
PROXY_URI: '',
|
|
});
|
|
|
|
expect(proxy.multiProxy).toBeDefined();
|
|
const current = proxy.getCurrentProxy();
|
|
expect(current).not.toBeNull();
|
|
expect(proxy.getDispatcherForProxy(current!)).toBeInstanceOf(ProxyAgent);
|
|
expect(proxy.getAgentForProxy({ uri: 'socks5://proxy.local:1080' } as any)).toBeInstanceOf(SocksProxyAgent);
|
|
|
|
proxy.markProxyFailed(current!.uri);
|
|
const next = proxy.getCurrentProxy();
|
|
expect(next).not.toBeNull();
|
|
});
|
|
|
|
it('clears proxy when multi-proxy has no valid entries', async () => {
|
|
const proxy = await loadProxy({
|
|
PROXY_URIS: 'http://inv lid.test',
|
|
PAC_URI: '',
|
|
PROXY_URI: '',
|
|
});
|
|
|
|
expect(proxy.getCurrentProxy()).toBeNull();
|
|
proxy.markProxyFailed('http://inv lid.test');
|
|
expect(proxy.agent).toBeNull();
|
|
expect(proxy.dispatcher).toBeNull();
|
|
expect(proxy.proxyUri).toBeUndefined();
|
|
});
|
|
|
|
it('creates a socks proxy agent for single proxy settings', async () => {
|
|
const proxy = await loadProxy({
|
|
PROXY_URI: 'socks5://proxy.local:1080',
|
|
PROXY_URIS: '',
|
|
PAC_URI: '',
|
|
});
|
|
|
|
expect(proxy.agent).toBeInstanceOf(SocksProxyAgent);
|
|
expect(proxy.dispatcher).toBeInstanceOf(ProxyAgent);
|
|
expect(proxy.getCurrentProxy()?.uri).toBe('socks5://proxy.local:1080');
|
|
});
|
|
|
|
it('returns null agent for unsupported proxy protocol', async () => {
|
|
const proxy = await loadProxy({
|
|
PROXY_URI: '',
|
|
PROXY_URIS: '',
|
|
PAC_URI: '',
|
|
});
|
|
|
|
expect(proxy.getAgentForProxy({ uri: 'ftp://proxy.local:21' } as any)).toBeNull();
|
|
});
|
|
});
|