mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-04-07 00:15:23 +02:00
test: Add proxy configuration tests for GraphApiService
This commit is contained in:
parent
1ad02baa51
commit
78b89df4ad
1 changed files with 212 additions and 0 deletions
|
|
@ -800,4 +800,216 @@ describe('GraphApiService', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Proxy Configuration', () => {
|
||||
let originalEnv;
|
||||
const { ProxyAgent } = require('undici');
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
|
||||
beforeAll(() => {
|
||||
originalEnv = { ...process.env };
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = { ...originalEnv };
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.env = originalEnv;
|
||||
});
|
||||
|
||||
describe('Graph Client Proxy Configuration', () => {
|
||||
it('should configure ProxyAgent dispatcher in Graph Client when PROXY env is set', async () => {
|
||||
process.env.PROXY = 'http://proxy.example.com:8080';
|
||||
mockTokensCache.get.mockResolvedValue(null);
|
||||
|
||||
await GraphApiService.createGraphClient('test-token', 'test-user');
|
||||
|
||||
expect(Client.init).toHaveBeenCalled();
|
||||
const initCall = Client.init.mock.calls[0][0];
|
||||
expect(initCall).toHaveProperty('fetchOptions');
|
||||
expect(initCall.fetchOptions).toHaveProperty('dispatcher');
|
||||
expect(initCall.fetchOptions.dispatcher).toBeInstanceOf(ProxyAgent);
|
||||
});
|
||||
|
||||
it('should not configure ProxyAgent dispatcher when PROXY env is not set', async () => {
|
||||
delete process.env.PROXY;
|
||||
mockTokensCache.get.mockResolvedValue(null);
|
||||
|
||||
await GraphApiService.createGraphClient('test-token', 'test-user');
|
||||
|
||||
expect(Client.init).toHaveBeenCalled();
|
||||
const initCall = Client.init.mock.calls[0][0];
|
||||
|
||||
// fetchOptions should either not exist or not have a dispatcher
|
||||
if (initCall.fetchOptions) {
|
||||
expect(initCall.fetchOptions.dispatcher).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
it('should pass correct proxy URL to ProxyAgent', async () => {
|
||||
const proxyUrl = 'http://custom-proxy.example.com:3128';
|
||||
process.env.PROXY = proxyUrl;
|
||||
mockTokensCache.get.mockResolvedValue(null);
|
||||
|
||||
await GraphApiService.createGraphClient('test-token', 'test-user');
|
||||
|
||||
const initCall = Client.init.mock.calls[0][0];
|
||||
expect(initCall.fetchOptions.dispatcher).toBeInstanceOf(ProxyAgent);
|
||||
// ProxyAgent stores the URL internally
|
||||
expect(initCall.fetchOptions.dispatcher.proxy).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('OpenID Client Proxy Configuration', () => {
|
||||
it('should configure HttpsProxyAgent for openid-client custom fetch when PROXY env is set', async () => {
|
||||
process.env.PROXY = 'http://proxy.example.com:8080';
|
||||
mockTokensCache.get.mockResolvedValue(null);
|
||||
|
||||
await GraphApiService.exchangeTokenForGraphAccess(
|
||||
mockOpenIdConfig,
|
||||
'test-token',
|
||||
'test-user',
|
||||
);
|
||||
|
||||
if (client.genericGrantRequest) {
|
||||
expect(client.genericGrantRequest).toHaveBeenCalled();
|
||||
const clientOptions = client.genericGrantRequest.mock.calls[0][3];
|
||||
|
||||
expect(clientOptions).toBeDefined();
|
||||
expect(clientOptions).toHaveProperty(Symbol.for('openid-client.custom.fetch'));
|
||||
expect(typeof clientOptions[Symbol.for('openid-client.custom.fetch')]).toBe('function');
|
||||
}
|
||||
});
|
||||
|
||||
it('should not configure custom fetch when PROXY env is not set', async () => {
|
||||
delete process.env.PROXY;
|
||||
mockTokensCache.get.mockResolvedValue(null);
|
||||
|
||||
await GraphApiService.exchangeTokenForGraphAccess(
|
||||
mockOpenIdConfig,
|
||||
'test-token',
|
||||
'test-user',
|
||||
);
|
||||
|
||||
if (client.genericGrantRequest) {
|
||||
expect(client.genericGrantRequest).toHaveBeenCalled();
|
||||
const clientOptions = client.genericGrantRequest.mock.calls[0][3];
|
||||
|
||||
// clientOptions should be empty object or not have custom fetch
|
||||
expect(clientOptions).toEqual({});
|
||||
}
|
||||
});
|
||||
|
||||
it('should use HttpsProxyAgent with correct proxy URL', async () => {
|
||||
const proxyUrl = 'http://custom-proxy.example.com:3128';
|
||||
process.env.PROXY = proxyUrl;
|
||||
mockTokensCache.get.mockResolvedValue(null);
|
||||
|
||||
await GraphApiService.exchangeTokenForGraphAccess(
|
||||
mockOpenIdConfig,
|
||||
'test-token',
|
||||
'test-user',
|
||||
);
|
||||
|
||||
if (client.genericGrantRequest) {
|
||||
const clientOptions = client.genericGrantRequest.mock.calls[0][3];
|
||||
const customFetch = clientOptions[Symbol.for('openid-client.custom.fetch')];
|
||||
|
||||
expect(customFetch).toBeDefined();
|
||||
expect(typeof customFetch).toBe('function');
|
||||
}
|
||||
});
|
||||
|
||||
it('should pass HttpsProxyAgent through custom fetch to nodeFetch', async () => {
|
||||
const nodeFetch = require('node-fetch');
|
||||
jest.spyOn(nodeFetch, 'default');
|
||||
|
||||
process.env.PROXY = 'http://proxy.example.com:8080';
|
||||
mockTokensCache.get.mockResolvedValue(null);
|
||||
|
||||
await GraphApiService.exchangeTokenForGraphAccess(
|
||||
mockOpenIdConfig,
|
||||
'test-token',
|
||||
'test-user',
|
||||
);
|
||||
|
||||
if (client.genericGrantRequest) {
|
||||
const clientOptions = client.genericGrantRequest.mock.calls[0][3];
|
||||
const customFetch = clientOptions[Symbol.for('openid-client.custom.fetch')];
|
||||
|
||||
// Test that custom fetch function properly includes agent
|
||||
if (customFetch) {
|
||||
const mockUrl = 'https://test.example.com';
|
||||
const mockOptions = { method: 'POST' };
|
||||
|
||||
// The custom fetch should be callable and should merge options with agent
|
||||
expect(() => customFetch(mockUrl, mockOptions)).not.toThrow();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Proxy Integration Tests', () => {
|
||||
it('should maintain proxy configuration throughout token exchange and graph client creation', async () => {
|
||||
process.env.PROXY = 'http://proxy.example.com:8080';
|
||||
mockTokensCache.get.mockResolvedValue(null);
|
||||
|
||||
// First, exchange token (tests openid-client proxy)
|
||||
const graphToken = await GraphApiService.exchangeTokenForGraphAccess(
|
||||
mockOpenIdConfig,
|
||||
'test-token',
|
||||
'test-user',
|
||||
);
|
||||
|
||||
expect(graphToken).toBe('mocked-graph-token');
|
||||
|
||||
if (client.genericGrantRequest) {
|
||||
const clientOptions = client.genericGrantRequest.mock.calls[0][3];
|
||||
expect(clientOptions[Symbol.for('openid-client.custom.fetch')]).toBeDefined();
|
||||
}
|
||||
|
||||
// Then, create graph client (tests Graph API proxy)
|
||||
await GraphApiService.createGraphClient('test-token', 'test-user');
|
||||
|
||||
const initCall = Client.init.mock.calls[0][0];
|
||||
expect(initCall.fetchOptions.dispatcher).toBeInstanceOf(ProxyAgent);
|
||||
});
|
||||
|
||||
it('should handle different proxy protocols', async () => {
|
||||
const proxyProtocols = [
|
||||
'http://proxy.example.com:8080',
|
||||
'https://secure-proxy.example.com:8443',
|
||||
'socks5://socks-proxy.example.com:1080',
|
||||
];
|
||||
|
||||
for (const proxyUrl of proxyProtocols) {
|
||||
process.env.PROXY = proxyUrl;
|
||||
mockTokensCache.get.mockResolvedValue(null);
|
||||
jest.clearAllMocks();
|
||||
|
||||
await GraphApiService.createGraphClient('test-token', 'test-user');
|
||||
|
||||
const initCall = Client.init.mock.calls[0][0];
|
||||
expect(initCall.fetchOptions.dispatcher).toBeInstanceOf(ProxyAgent);
|
||||
}
|
||||
});
|
||||
|
||||
it('should not fail when PROXY is set to empty string', async () => {
|
||||
process.env.PROXY = '';
|
||||
mockTokensCache.get.mockResolvedValue(null);
|
||||
|
||||
await expect(
|
||||
GraphApiService.createGraphClient('test-token', 'test-user'),
|
||||
).resolves.not.toThrow();
|
||||
|
||||
const initCall = Client.init.mock.calls[0][0];
|
||||
if (initCall.fetchOptions) {
|
||||
expect(initCall.fetchOptions.dispatcher).toBeUndefined();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue