test: Add proxy configuration tests for GraphApiService

This commit is contained in:
David Rodríguez 2026-01-14 16:07:04 +00:00
parent 1ad02baa51
commit 78b89df4ad

View file

@ -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();
}
});
});
});
});