mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-18 09:20:15 +01:00
204 lines
6 KiB
JavaScript
204 lines
6 KiB
JavaScript
|
|
// Mock librechat-data-provider
|
||
|
|
jest.mock('librechat-data-provider', () => ({
|
||
|
|
...jest.requireActual('librechat-data-provider'),
|
||
|
|
extractVariableName: jest.fn(),
|
||
|
|
}));
|
||
|
|
|
||
|
|
// Mock the config logger
|
||
|
|
jest.mock('~/config', () => ({
|
||
|
|
logger: {
|
||
|
|
debug: jest.fn(),
|
||
|
|
warn: jest.fn(),
|
||
|
|
},
|
||
|
|
}));
|
||
|
|
|
||
|
|
const { checkWebSearchConfig } = require('./checks');
|
||
|
|
const { logger } = require('~/config');
|
||
|
|
const { extractVariableName } = require('librechat-data-provider');
|
||
|
|
|
||
|
|
describe('checkWebSearchConfig', () => {
|
||
|
|
let originalEnv;
|
||
|
|
|
||
|
|
beforeEach(() => {
|
||
|
|
// Clear all mocks
|
||
|
|
jest.clearAllMocks();
|
||
|
|
|
||
|
|
// Store original environment
|
||
|
|
originalEnv = process.env;
|
||
|
|
|
||
|
|
// Reset process.env
|
||
|
|
process.env = { ...originalEnv };
|
||
|
|
});
|
||
|
|
|
||
|
|
afterEach(() => {
|
||
|
|
// Restore original environment
|
||
|
|
process.env = originalEnv;
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('when webSearchConfig is undefined or null', () => {
|
||
|
|
it('should return early without logging when config is undefined', () => {
|
||
|
|
checkWebSearchConfig(undefined);
|
||
|
|
|
||
|
|
expect(logger.debug).not.toHaveBeenCalled();
|
||
|
|
expect(logger.warn).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should return early without logging when config is null', () => {
|
||
|
|
checkWebSearchConfig(null);
|
||
|
|
|
||
|
|
expect(logger.debug).not.toHaveBeenCalled();
|
||
|
|
expect(logger.warn).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('when config values are proper environment variable references', () => {
|
||
|
|
it('should log debug message for each valid environment variable with value set', () => {
|
||
|
|
const config = {
|
||
|
|
serperApiKey: '${SERPER_API_KEY}',
|
||
|
|
jinaApiKey: '${JINA_API_KEY}',
|
||
|
|
};
|
||
|
|
|
||
|
|
extractVariableName.mockReturnValueOnce('SERPER_API_KEY').mockReturnValueOnce('JINA_API_KEY');
|
||
|
|
|
||
|
|
process.env.SERPER_API_KEY = 'test-serper-key';
|
||
|
|
process.env.JINA_API_KEY = 'test-jina-key';
|
||
|
|
|
||
|
|
checkWebSearchConfig(config);
|
||
|
|
|
||
|
|
expect(extractVariableName).toHaveBeenCalledWith('${SERPER_API_KEY}');
|
||
|
|
expect(extractVariableName).toHaveBeenCalledWith('${JINA_API_KEY}');
|
||
|
|
expect(logger.debug).toHaveBeenCalledWith(
|
||
|
|
'Web search serperApiKey: Using environment variable SERPER_API_KEY with value set',
|
||
|
|
);
|
||
|
|
expect(logger.debug).toHaveBeenCalledWith(
|
||
|
|
'Web search jinaApiKey: Using environment variable JINA_API_KEY with value set',
|
||
|
|
);
|
||
|
|
expect(logger.warn).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should log debug message for environment variables not set in environment', () => {
|
||
|
|
const config = {
|
||
|
|
cohereApiKey: '${COHERE_API_KEY}',
|
||
|
|
};
|
||
|
|
|
||
|
|
extractVariableName.mockReturnValue('COHERE_API_KEY');
|
||
|
|
|
||
|
|
delete process.env.COHERE_API_KEY;
|
||
|
|
|
||
|
|
checkWebSearchConfig(config);
|
||
|
|
|
||
|
|
expect(logger.debug).toHaveBeenCalledWith(
|
||
|
|
'Web search cohereApiKey: Using environment variable COHERE_API_KEY (not set in environment, user provided value)',
|
||
|
|
);
|
||
|
|
expect(logger.warn).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('when config values are actual values instead of environment variable references', () => {
|
||
|
|
it('should warn when serperApiKey contains actual API key', () => {
|
||
|
|
const config = {
|
||
|
|
serperApiKey: 'sk-1234567890abcdef',
|
||
|
|
};
|
||
|
|
|
||
|
|
extractVariableName.mockReturnValue(null);
|
||
|
|
|
||
|
|
checkWebSearchConfig(config);
|
||
|
|
|
||
|
|
expect(logger.warn).toHaveBeenCalledWith(
|
||
|
|
expect.stringContaining(
|
||
|
|
'❗ Web search configuration error: serperApiKey contains an actual value',
|
||
|
|
),
|
||
|
|
);
|
||
|
|
expect(logger.warn).toHaveBeenCalledWith(
|
||
|
|
expect.stringContaining('Current value: "sk-1234567..."'),
|
||
|
|
);
|
||
|
|
expect(logger.debug).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should warn when firecrawlApiUrl contains actual URL', () => {
|
||
|
|
const config = {
|
||
|
|
firecrawlApiUrl: 'https://api.firecrawl.dev',
|
||
|
|
};
|
||
|
|
|
||
|
|
extractVariableName.mockReturnValue(null);
|
||
|
|
|
||
|
|
checkWebSearchConfig(config);
|
||
|
|
|
||
|
|
expect(logger.warn).toHaveBeenCalledWith(
|
||
|
|
expect.stringContaining(
|
||
|
|
'❗ Web search configuration error: firecrawlApiUrl contains an actual value',
|
||
|
|
),
|
||
|
|
);
|
||
|
|
expect(logger.warn).toHaveBeenCalledWith(
|
||
|
|
expect.stringContaining('Current value: "https://ap..."'),
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should include documentation link in warning message', () => {
|
||
|
|
const config = {
|
||
|
|
firecrawlApiKey: 'fc-actual-key',
|
||
|
|
};
|
||
|
|
|
||
|
|
extractVariableName.mockReturnValue(null);
|
||
|
|
|
||
|
|
checkWebSearchConfig(config);
|
||
|
|
|
||
|
|
expect(logger.warn).toHaveBeenCalledWith(
|
||
|
|
expect.stringContaining(
|
||
|
|
'More info: https://www.librechat.ai/docs/configuration/librechat_yaml/web_search',
|
||
|
|
),
|
||
|
|
);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('when config contains mixed value types', () => {
|
||
|
|
it('should only process string values and ignore non-string values', () => {
|
||
|
|
const config = {
|
||
|
|
serperApiKey: '${SERPER_API_KEY}',
|
||
|
|
safeSearch: 1,
|
||
|
|
scraperTimeout: 7500,
|
||
|
|
jinaApiKey: 'actual-key',
|
||
|
|
};
|
||
|
|
|
||
|
|
extractVariableName.mockReturnValueOnce('SERPER_API_KEY').mockReturnValueOnce(null);
|
||
|
|
|
||
|
|
process.env.SERPER_API_KEY = 'test-key';
|
||
|
|
|
||
|
|
checkWebSearchConfig(config);
|
||
|
|
|
||
|
|
expect(extractVariableName).toHaveBeenCalledTimes(2);
|
||
|
|
expect(logger.debug).toHaveBeenCalledTimes(1);
|
||
|
|
expect(logger.warn).toHaveBeenCalledTimes(1);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('edge cases', () => {
|
||
|
|
it('should handle config with no web search keys', () => {
|
||
|
|
const config = {
|
||
|
|
someOtherKey: 'value',
|
||
|
|
anotherKey: '${SOME_VAR}',
|
||
|
|
};
|
||
|
|
|
||
|
|
checkWebSearchConfig(config);
|
||
|
|
|
||
|
|
expect(extractVariableName).not.toHaveBeenCalled();
|
||
|
|
expect(logger.debug).not.toHaveBeenCalled();
|
||
|
|
expect(logger.warn).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should truncate long values in warning messages', () => {
|
||
|
|
const config = {
|
||
|
|
serperApiKey: 'this-is-a-very-long-api-key-that-should-be-truncated-in-the-warning-message',
|
||
|
|
};
|
||
|
|
|
||
|
|
extractVariableName.mockReturnValue(null);
|
||
|
|
|
||
|
|
checkWebSearchConfig(config);
|
||
|
|
|
||
|
|
expect(logger.warn).toHaveBeenCalledWith(
|
||
|
|
expect.stringContaining('Current value: "this-is-a-..."'),
|
||
|
|
);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|