LibreChat/api/app/clients/tools/structured/specs/GeminiImageGen-proxy.spec.js

126 lines
3.6 KiB
JavaScript
Raw Normal View History

const { ProxyAgent } = require('undici');
/**
* These tests verify the proxy wrapper behavior for GeminiImageGen.
* Instead of loading the full module (which has many dependencies),
* we directly test the wrapper logic that would be applied.
*/
describe('GeminiImageGen Proxy Configuration', () => {
let originalEnv;
let originalFetch;
beforeAll(() => {
originalEnv = { ...process.env };
originalFetch = globalThis.fetch;
});
beforeEach(() => {
process.env = { ...originalEnv };
globalThis.fetch = originalFetch;
});
afterEach(() => {
process.env = originalEnv;
globalThis.fetch = originalFetch;
});
/**
* Simulates the proxy wrapper that GeminiImageGen applies at module load.
* This is the same logic from GeminiImageGen.js lines 30-42.
*/
function applyProxyWrapper() {
if (process.env.PROXY) {
const _originalFetch = globalThis.fetch;
const proxyAgent = new ProxyAgent(process.env.PROXY);
globalThis.fetch = function (url, options = {}) {
const urlString = url.toString();
if (urlString.includes('googleapis.com')) {
options = { ...options, dispatcher: proxyAgent };
}
return _originalFetch.call(this, url, options);
};
}
}
it('should wrap globalThis.fetch when PROXY env is set', () => {
process.env.PROXY = 'http://proxy.example.com:8080';
const fetchBeforeWrap = globalThis.fetch;
applyProxyWrapper();
expect(globalThis.fetch).not.toBe(fetchBeforeWrap);
});
it('should not wrap globalThis.fetch when PROXY env is not set', () => {
delete process.env.PROXY;
const fetchBeforeWrap = globalThis.fetch;
applyProxyWrapper();
expect(globalThis.fetch).toBe(fetchBeforeWrap);
});
it('should add dispatcher to googleapis.com URLs', async () => {
process.env.PROXY = 'http://proxy.example.com:8080';
let capturedOptions = null;
const mockFetch = jest.fn((url, options) => {
capturedOptions = options;
return Promise.resolve({ ok: true });
});
globalThis.fetch = mockFetch;
applyProxyWrapper();
await globalThis.fetch('https://generativelanguage.googleapis.com/v1/models', {});
expect(capturedOptions).toBeDefined();
expect(capturedOptions.dispatcher).toBeInstanceOf(ProxyAgent);
});
it('should not add dispatcher to non-googleapis.com URLs', async () => {
process.env.PROXY = 'http://proxy.example.com:8080';
let capturedOptions = null;
const mockFetch = jest.fn((url, options) => {
capturedOptions = options;
return Promise.resolve({ ok: true });
});
globalThis.fetch = mockFetch;
applyProxyWrapper();
await globalThis.fetch('https://api.openai.com/v1/images', {});
expect(capturedOptions).toBeDefined();
expect(capturedOptions.dispatcher).toBeUndefined();
});
it('should preserve existing options when adding dispatcher', async () => {
process.env.PROXY = 'http://proxy.example.com:8080';
let capturedOptions = null;
const mockFetch = jest.fn((url, options) => {
capturedOptions = options;
return Promise.resolve({ ok: true });
});
globalThis.fetch = mockFetch;
applyProxyWrapper();
const customHeaders = { 'X-Custom-Header': 'test' };
await globalThis.fetch('https://aiplatform.googleapis.com/v1/models', {
headers: customHeaders,
method: 'POST',
});
expect(capturedOptions).toBeDefined();
expect(capturedOptions.dispatcher).toBeInstanceOf(ProxyAgent);
expect(capturedOptions.headers).toEqual(customHeaders);
expect(capturedOptions.method).toBe('POST');
});
});