csa / test /unit-proxy-agent.mjs
ricebug's picture
Upload 76 files
ca8ab2d verified
/**
* test/unit-proxy-agent.mjs
*
* ๅ•ๅ…ƒๆต‹่ฏ•๏ผšproxy-agent ไปฃ็†ๆจกๅ—
* ่ฟ่กŒๆ–นๅผ๏ผšnode test/unit-proxy-agent.mjs
*
* ๆต‹่ฏ•้€ป่พ‘ๅ‡ไธบ็บฏๅ†…่”ๅฎž็Žฐ๏ผŒไธไพ่ต– dist ็ผ–่ฏ‘ไบง็‰ฉใ€‚
* ้ชŒ่ฏ๏ผš
* 1. ๆ— ไปฃ็†ๆ—ถ getProxyFetchOptions ่ฟ”ๅ›ž็ฉบๅฏน่ฑก
* 2. ๆœ‰ไปฃ็†ๆ—ถ่ฟ”ๅ›žๅซ dispatcher ็š„ๅฏน่ฑก
* 3. ProxyAgent ็ผ“ๅญ˜๏ผˆๅ•ไพ‹๏ผ‰
* 4. ๅ„็งไปฃ็† URL ๆ ผๅผๆ”ฏๆŒ
*/
// โ”€โ”€โ”€ ๆต‹่ฏ•ๆก†ๆžถ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
let passed = 0;
let failed = 0;
function test(name, fn) {
try {
fn();
console.log(` โœ… ${name}`);
passed++;
} catch (e) {
console.error(` โŒ ${name}`);
console.error(` ${e.message}`);
failed++;
}
}
function assert(condition, msg) {
if (!condition) throw new Error(msg || 'Assertion failed');
}
function assertEqual(a, b, msg) {
const as = JSON.stringify(a), bs = JSON.stringify(b);
if (as !== bs) throw new Error(msg || `Expected ${bs}, got ${as}`);
}
// โ”€โ”€โ”€ ๅ†…่” mock ๅฎž็Žฐ๏ผˆๆจกๆ‹Ÿ proxy-agent.ts ๆ ธๅฟƒ้€ป่พ‘๏ผŒไธไพ่ต– dist๏ผ‰โ”€โ”€โ”€โ”€โ”€โ”€
// ๆจกๆ‹Ÿ config
let mockConfig = {};
function getConfig() {
return mockConfig;
}
// ๆจกๆ‹Ÿ ProxyAgent๏ผˆ่ฝป้‡็บง๏ผ‰
class MockProxyAgent {
constructor(url) {
this.url = url;
this.type = 'ProxyAgent';
}
}
// ๅ†…่”ไธŽ src/proxy-agent.ts ๅŒ้€ป่พ‘็š„ๅฎž็Žฐ
let cachedAgent = undefined;
function resetCache() {
cachedAgent = undefined;
}
function getProxyDispatcher() {
const config = getConfig();
const proxyUrl = config.proxy;
if (!proxyUrl) return undefined;
if (!cachedAgent) {
cachedAgent = new MockProxyAgent(proxyUrl);
}
return cachedAgent;
}
function getProxyFetchOptions() {
const dispatcher = getProxyDispatcher();
return dispatcher ? { dispatcher } : {};
}
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
// 1. ๆ— ไปฃ็†้…็ฝฎ โ†’ ่ฟ”ๅ›ž็ฉบๅฏน่ฑก
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
console.log('\n๐Ÿ“ฆ [1] ๆ— ไปฃ็†้…็ฝฎ\n');
test('proxy ๆœช่ฎพ็ฝฎๆ—ถ่ฟ”ๅ›ž็ฉบๅฏน่ฑก', () => {
resetCache();
mockConfig = {};
const opts = getProxyFetchOptions();
assertEqual(Object.keys(opts).length, 0, 'ๅบ”่ฟ”ๅ›ž็ฉบๅฏน่ฑก');
});
test('proxy ไธบ undefined ๆ—ถ่ฟ”ๅ›ž็ฉบๅฏน่ฑก', () => {
resetCache();
mockConfig = { proxy: undefined };
const opts = getProxyFetchOptions();
assertEqual(Object.keys(opts).length, 0);
});
test('proxy ไธบ็ฉบๅญ—็ฌฆไธฒๆ—ถ่ฟ”ๅ›ž็ฉบๅฏน่ฑก', () => {
resetCache();
mockConfig = { proxy: '' };
const opts = getProxyFetchOptions();
assertEqual(Object.keys(opts).length, 0, '็ฉบๅญ—็ฌฆไธฒไธๅบ”ๅˆ›ๅปบไปฃ็†');
});
test('getProxyDispatcher ๆ— ไปฃ็†ๆ—ถ่ฟ”ๅ›ž undefined', () => {
resetCache();
mockConfig = {};
const d = getProxyDispatcher();
assertEqual(d, undefined);
});
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
// 2. ๆœ‰ไปฃ็†้…็ฝฎ โ†’ ่ฟ”ๅ›žๅซ dispatcher ็š„ๅฏน่ฑก
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
console.log('\n๐Ÿ“ฆ [2] ๆœ‰ไปฃ็†้…็ฝฎ\n');
test('่ฎพ็ฝฎ proxy ๅŽ่ฟ”ๅ›žๅซ dispatcher ็š„ๅฏน่ฑก', () => {
resetCache();
mockConfig = { proxy: 'http://127.0.0.1:7890' };
const opts = getProxyFetchOptions();
assert(opts.dispatcher !== undefined, 'ๅบ”ๅŒ…ๅซ dispatcher');
assert(opts.dispatcher instanceof MockProxyAgent, 'ๅบ”ไธบ ProxyAgent ๅฎžไพ‹');
});
test('dispatcher ๅŒ…ๅซๆญฃ็กฎ็š„ไปฃ็† URL', () => {
resetCache();
mockConfig = { proxy: 'http://127.0.0.1:7890' };
const d = getProxyDispatcher();
assertEqual(d.url, 'http://127.0.0.1:7890');
});
test('ๅธฆ่ฎค่ฏ็š„ไปฃ็† URL', () => {
resetCache();
mockConfig = { proxy: 'http://user:pass@proxy.corp.com:8080' };
const d = getProxyDispatcher();
assertEqual(d.url, 'http://user:pass@proxy.corp.com:8080');
});
test('HTTPS ไปฃ็† URL', () => {
resetCache();
mockConfig = { proxy: 'https://secure-proxy.corp.com:443' };
const d = getProxyDispatcher();
assertEqual(d.url, 'https://secure-proxy.corp.com:443');
});
test('ๅธฆ็‰นๆฎŠๅญ—็ฌฆๅฏ†็ ็š„ไปฃ็† URL', () => {
resetCache();
const url = 'http://admin:p%40ssw0rd@proxy:8080';
mockConfig = { proxy: url };
const d = getProxyDispatcher();
assertEqual(d.url, url, 'ๅบ”ๅŽŸๆ ทไฟ็•™ URL ็ผ–็ ็š„็‰นๆฎŠๅญ—็ฌฆ');
});
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
// 3. ็ผ“ๅญ˜๏ผˆๅ•ไพ‹๏ผ‰่กŒไธบ
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
console.log('\n๐Ÿ“ฆ [3] ็ผ“ๅญ˜ๅ•ไพ‹่กŒไธบ\n');
test('ๅคšๆฌก่ฐƒ็”จ่ฟ”ๅ›žๅŒไธ€ ProxyAgent ๅฎžไพ‹', () => {
resetCache();
mockConfig = { proxy: 'http://127.0.0.1:7890' };
const d1 = getProxyDispatcher();
const d2 = getProxyDispatcher();
assert(d1 === d2, 'ๅบ”่ฟ”ๅ›žๅŒไธ€ไธช็ผ“ๅญ˜ๅฎžไพ‹');
});
test('getProxyFetchOptions ๅคšๆฌก่ฐƒ็”จๅค็”จๅŒไธ€ dispatcher', () => {
resetCache();
mockConfig = { proxy: 'http://127.0.0.1:7890' };
const opts1 = getProxyFetchOptions();
const opts2 = getProxyFetchOptions();
assert(opts1.dispatcher === opts2.dispatcher, 'dispatcher ๅบ”ไธบๅŒไธ€ๅฎžไพ‹');
});
test('้‡็ฝฎ็ผ“ๅญ˜ๅŽๅˆ›ๅปบๆ–ฐๅฎžไพ‹', () => {
resetCache();
mockConfig = { proxy: 'http://127.0.0.1:7890' };
const d1 = getProxyDispatcher();
resetCache();
mockConfig = { proxy: 'http://10.0.0.1:3128' };
const d2 = getProxyDispatcher();
assert(d1 !== d2, '้‡็ฝฎๅŽๅบ”ๅˆ›ๅปบๆ–ฐๅฎžไพ‹');
assertEqual(d2.url, 'http://10.0.0.1:3128');
});
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
// 4. fetch options ๅฑ•ๅผ€่ฏญไน‰้ชŒ่ฏ
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
console.log('\n๐Ÿ“ฆ [4] fetch options ๅฑ•ๅผ€่ฏญไน‰\n');
test('ๆ— ไปฃ็†ๆ—ถๅฑ•ๅผ€ไธๅฝฑๅ“ๅŽŸๅง‹ options', () => {
resetCache();
mockConfig = {};
const original = { method: 'POST', headers: { 'Content-Type': 'application/json' } };
const merged = { ...original, ...getProxyFetchOptions() };
assertEqual(merged.method, 'POST');
assertEqual(merged.headers['Content-Type'], 'application/json');
assert(merged.dispatcher === undefined, 'ไธๅบ”ๆทปๅŠ  dispatcher');
});
test('ๆœ‰ไปฃ็†ๆ—ถๅฑ•ๅผ€ๆ’ๅ…ฅ dispatcher ไธ”ไธ่ฆ†็›–ๅ…ถไป–ๅญ—ๆฎต', () => {
resetCache();
mockConfig = { proxy: 'http://127.0.0.1:7890' };
const original = { method: 'POST', body: '{}', signal: 'test-signal' };
const merged = { ...original, ...getProxyFetchOptions() };
assertEqual(merged.method, 'POST');
assertEqual(merged.body, '{}');
assertEqual(merged.signal, 'test-signal');
assert(merged.dispatcher instanceof MockProxyAgent, 'ๅบ”ๅŒ…ๅซ dispatcher');
});
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
// 5. config.ts ้›†ๆˆ้ชŒ่ฏ๏ผˆ็Žฏๅขƒๅ˜้‡ไผ˜ๅ…ˆ็บง๏ผ‰
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
console.log('\n๐Ÿ“ฆ [5] config ็Žฏๅขƒๅ˜้‡้›†ๆˆ้ชŒ่ฏ\n');
test('PROXY ็Žฏๅขƒๅ˜้‡ๅบ”่ฆ†็›– config.yaml๏ผˆ้€ป่พ‘้ชŒ่ฏ๏ผ‰', () => {
// ๆจกๆ‹Ÿ config.ts ็š„่ฆ†็›–้€ป่พ‘๏ผšenv > yaml
let config = { proxy: 'http://yaml-proxy:1234' };
const envProxy = 'http://env-proxy:5678';
// ๆจกๆ‹Ÿ config.ts ็ฌฌ 49 ่กŒ้€ป่พ‘
if (envProxy) config.proxy = envProxy;
assertEqual(config.proxy, 'http://env-proxy:5678', 'PROXY ็Žฏๅขƒๅ˜้‡ๅบ”่ฆ†็›– yaml ้…็ฝฎ');
});
test('PROXY ็Žฏๅขƒๅ˜้‡ๆœช่ฎพ็ฝฎๆ—ถไฟๆŒ yaml ๅ€ผ๏ผˆ้€ป่พ‘้ชŒ่ฏ๏ผ‰', () => {
let config = { proxy: 'http://yaml-proxy:1234' };
const envProxy = undefined;
if (envProxy) config.proxy = envProxy;
assertEqual(config.proxy, 'http://yaml-proxy:1234', 'ๅบ”ไฟๆŒ yaml ้…็ฝฎไธๅ˜');
});
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
// ๆฑ‡ๆ€ป
// โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
console.log('\n' + 'โ•'.repeat(55));
console.log(` ็ป“ๆžœ: ${passed} ้€š่ฟ‡ / ${failed} ๅคฑ่ดฅ / ${passed + failed} ๆ€ป่ฎก`);
console.log('โ•'.repeat(55) + '\n');
if (failed > 0) process.exit(1);