diff --git a/api/app/clients/specs/BaseClient.test.js b/api/app/clients/specs/BaseClient.test.js
index b5ae5b80b6..b93526ef13 100644
--- a/api/app/clients/specs/BaseClient.test.js
+++ b/api/app/clients/specs/BaseClient.test.js
@@ -2,6 +2,14 @@ const { Constants } = require('librechat-data-provider');
const { initializeFakeClient } = require('./FakeClient');
jest.mock('~/db/connect');
+jest.mock('~/server/services/Config', () => ({
+ getAppConfig: jest.fn().mockResolvedValue({
+ // Default app config for tests
+ paths: { uploads: '/tmp' },
+ fileStrategy: 'local',
+ memory: { disabled: false },
+ }),
+}));
jest.mock('~/models', () => ({
User: jest.fn(),
Key: jest.fn(),
diff --git a/api/app/clients/tools/util/handleTools.test.js b/api/app/clients/tools/util/handleTools.test.js
index 1cacda8159..b01aa2f7ef 100644
--- a/api/app/clients/tools/util/handleTools.test.js
+++ b/api/app/clients/tools/util/handleTools.test.js
@@ -9,6 +9,27 @@ const mockPluginService = {
jest.mock('~/server/services/PluginService', () => mockPluginService);
+jest.mock('~/server/services/Config', () => ({
+ getAppConfig: jest.fn().mockResolvedValue({
+ // Default app config for tool tests
+ paths: { uploads: '/tmp' },
+ fileStrategy: 'local',
+ filteredTools: [],
+ includedTools: [],
+ }),
+ getCachedTools: jest.fn().mockResolvedValue({
+ // Default cached tools for tests
+ dalle: {
+ type: 'function',
+ function: {
+ name: 'dalle',
+ description: 'DALL-E image generation',
+ parameters: {},
+ },
+ },
+ }),
+}));
+
const { BaseLLM } = require('@langchain/openai');
const { Calculator } = require('@langchain/community/tools/calculator');
diff --git a/api/server/index.spec.js b/api/server/index.spec.js
index 79ca1621ac..141ce24596 100644
--- a/api/server/index.spec.js
+++ b/api/server/index.spec.js
@@ -3,9 +3,29 @@ const request = require('supertest');
const { MongoMemoryServer } = require('mongodb-memory-server');
const mongoose = require('mongoose');
-jest.mock('~/server/services/Config/loadCustomConfig', () => {
- return jest.fn(() => Promise.resolve({}));
-});
+jest.mock('~/server/services/Config', () => ({
+ loadCustomConfig: jest.fn(() => Promise.resolve({})),
+ getCustomConfig: jest.fn(() => Promise.resolve({})),
+ setAppConfig: jest.fn(),
+ getAppConfig: jest.fn().mockResolvedValue({
+ paths: {
+ uploads: '/tmp',
+ dist: '/tmp/dist',
+ fonts: '/tmp/fonts',
+ assets: '/tmp/assets',
+ },
+ fileStrategy: 'local',
+ imageOutputType: 'PNG',
+ }),
+ setCachedTools: jest.fn(),
+}));
+
+jest.mock('~/app/clients/tools', () => ({
+ createOpenAIImageTools: jest.fn(() => []),
+ createYouTubeTools: jest.fn(() => []),
+ manifestToolMap: {},
+ toolkits: [],
+}));
describe('Server Configuration', () => {
// Increase the default timeout to allow for Mongo cleanup
@@ -31,6 +51,22 @@ describe('Server Configuration', () => {
});
beforeAll(async () => {
+ // Create the required directories and files for the test
+ const fs = require('fs');
+ const path = require('path');
+
+ const dirs = ['/tmp/dist', '/tmp/fonts', '/tmp/assets'];
+ dirs.forEach((dir) => {
+ if (!fs.existsSync(dir)) {
+ fs.mkdirSync(dir, { recursive: true });
+ }
+ });
+
+ fs.writeFileSync(
+ path.join('/tmp/dist', 'index.html'),
+ '
LibreChat',
+ );
+
mongoServer = await MongoMemoryServer.create();
process.env.MONGO_URI = mongoServer.getUri();
process.env.PORT = '0'; // Use a random available port
diff --git a/api/server/services/Endpoints/azureAssistants/initialize.spec.js b/api/server/services/Endpoints/azureAssistants/initialize.spec.js
index 28e1004c9f..e894a82499 100644
--- a/api/server/services/Endpoints/azureAssistants/initialize.spec.js
+++ b/api/server/services/Endpoints/azureAssistants/initialize.spec.js
@@ -12,6 +12,15 @@ jest.mock('~/server/services/UserService', () => ({
checkUserKeyExpiry: jest.requireActual('~/server/services/UserService').checkUserKeyExpiry,
}));
+jest.mock('~/server/services/Config', () => ({
+ getAppConfig: jest.fn().mockResolvedValue({
+ azureAssistants: {
+ apiKey: 'test-key',
+ baseURL: 'https://test.url',
+ },
+ }),
+}));
+
const today = new Date();
const tenDaysFromToday = new Date(today.setDate(today.getDate() + 10));
const isoString = tenDaysFromToday.toISOString();
diff --git a/api/server/services/Endpoints/custom/initialize.spec.js b/api/server/services/Endpoints/custom/initialize.spec.js
index 373620d42a..8108ec8302 100644
--- a/api/server/services/Endpoints/custom/initialize.spec.js
+++ b/api/server/services/Endpoints/custom/initialize.spec.js
@@ -30,6 +30,12 @@ jest.mock('~/server/services/Config', () => ({
headers: { 'x-user': '{{LIBRECHAT_USER_ID}}', 'x-email': '{{LIBRECHAT_USER_EMAIL}}' },
models: { default: ['test-model'] },
}),
+ getAppConfig: jest.fn().mockResolvedValue({
+ 'test-endpoint': {
+ apiKey: 'test-key',
+ baseURL: 'https://test.com',
+ },
+ }),
}));
jest.mock('~/server/services/ModelService', () => ({
diff --git a/api/server/services/Endpoints/google/initialize.spec.js b/api/server/services/Endpoints/google/initialize.spec.js
index e5391107bd..c6218f5d12 100644
--- a/api/server/services/Endpoints/google/initialize.spec.js
+++ b/api/server/services/Endpoints/google/initialize.spec.js
@@ -8,6 +8,14 @@ jest.mock('~/server/services/UserService', () => ({
getUserKey: jest.fn().mockImplementation(() => ({})),
}));
+jest.mock('~/server/services/Config', () => ({
+ getAppConfig: jest.fn().mockResolvedValue({
+ google: {
+ apiKey: 'test-key',
+ },
+ }),
+}));
+
const app = { locals: {} };
describe('google/initializeClient', () => {
diff --git a/api/server/services/Endpoints/openAI/initialize.spec.js b/api/server/services/Endpoints/openAI/initialize.spec.js
index 16563e4b26..40a6e2973c 100644
--- a/api/server/services/Endpoints/openAI/initialize.spec.js
+++ b/api/server/services/Endpoints/openAI/initialize.spec.js
@@ -1,4 +1,13 @@
-jest.mock('~/cache/getLogStores');
+jest.mock('~/cache/getLogStores', () => ({
+ getLogStores: jest.fn().mockReturnValue({
+ get: jest.fn().mockResolvedValue({
+ openAI: { apiKey: 'test-key' },
+ }),
+ set: jest.fn(),
+ delete: jest.fn(),
+ }),
+}));
+
const { EModelEndpoint, ErrorTypes, validateAzureGroups } = require('librechat-data-provider');
const { getUserKey, getUserKeyValues } = require('~/server/services/UserService');
const initializeClient = require('./initialize');
@@ -11,6 +20,38 @@ jest.mock('~/server/services/UserService', () => ({
checkUserKeyExpiry: jest.requireActual('~/server/services/UserService').checkUserKeyExpiry,
}));
+jest.mock('~/server/services/Config', () => ({
+ getAppConfig: jest.fn().mockResolvedValue({
+ openAI: {
+ apiKey: 'test-key',
+ },
+ azureOpenAI: {
+ apiKey: 'test-azure-key',
+ modelNames: ['gpt-4-vision-preview', 'gpt-3.5-turbo', 'gpt-4'],
+ modelGroupMap: {
+ 'gpt-4-vision-preview': {
+ group: 'librechat-westus',
+ deploymentName: 'gpt-4-vision-preview',
+ version: '2024-02-15-preview',
+ },
+ },
+ groupMap: {
+ 'librechat-westus': {
+ apiKey: 'WESTUS_API_KEY',
+ instanceName: 'librechat-westus',
+ version: '2023-12-01-preview',
+ models: {
+ 'gpt-4-vision-preview': {
+ deploymentName: 'gpt-4-vision-preview',
+ version: '2024-02-15-preview',
+ },
+ },
+ },
+ },
+ },
+ }),
+}));
+
describe('initializeClient', () => {
// Set up environment variables
const originalEnvironment = process.env;
@@ -79,7 +120,7 @@ describe('initializeClient', () => {
},
];
- const { modelNames, modelGroupMap, groupMap } = validateAzureGroups(validAzureConfigs);
+ const { modelNames } = validateAzureGroups(validAzureConfigs);
beforeEach(() => {
jest.resetModules(); // Clears the cache
@@ -112,25 +153,29 @@ describe('initializeClient', () => {
test('should initialize client with Azure credentials when endpoint is azureOpenAI', async () => {
process.env.AZURE_API_KEY = 'test-azure-api-key';
(process.env.AZURE_OPENAI_API_INSTANCE_NAME = 'some-value'),
- (process.env.AZURE_OPENAI_API_DEPLOYMENT_NAME = 'some-value'),
- (process.env.AZURE_OPENAI_API_VERSION = 'some-value'),
- (process.env.AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME = 'some-value'),
- (process.env.AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME = 'some-value'),
- (process.env.OPENAI_API_KEY = 'test-openai-api-key');
+ (process.env.AZURE_OPENAI_API_DEPLOYMENT_NAME = 'some-value'),
+ (process.env.AZURE_OPENAI_API_VERSION = 'some-value'),
+ (process.env.AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME = 'some-value'),
+ (process.env.AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME = 'some-value'),
+ (process.env.OPENAI_API_KEY = 'test-openai-api-key');
process.env.DEBUG_OPENAI = 'false';
process.env.OPENAI_SUMMARIZE = 'false';
const req = {
- body: { key: null, endpoint: 'azureOpenAI' },
+ body: {
+ key: null,
+ endpoint: 'azureOpenAI',
+ model: 'gpt-4-vision-preview',
+ },
user: { id: '123' },
app,
};
const res = {};
- const endpointOption = { modelOptions: { model: 'test-model' } };
+ const endpointOption = {};
const client = await initializeClient({ req, res, endpointOption });
- expect(client.openAIApiKey).toBe('test-azure-api-key');
+ expect(client.openAIApiKey).toBe('WESTUS_API_KEY');
expect(client.client).toBeInstanceOf(OpenAIClient);
});
@@ -291,7 +336,7 @@ describe('initializeClient', () => {
let userValues = getUserKey();
try {
userValues = JSON.parse(userValues);
- } catch (e) {
+ } catch {
throw new Error(
JSON.stringify({
type: ErrorTypes.INVALID_USER_KEY,
@@ -307,6 +352,9 @@ describe('initializeClient', () => {
});
test('should initialize client correctly for Azure OpenAI with valid configuration', async () => {
+ // Set up Azure environment variables
+ process.env.WESTUS_API_KEY = 'test-westus-key';
+
const req = {
body: {
key: null,
@@ -314,15 +362,6 @@ describe('initializeClient', () => {
model: modelNames[0],
},
user: { id: '123' },
- app: {
- locals: {
- [EModelEndpoint.azureOpenAI]: {
- modelNames,
- modelGroupMap,
- groupMap,
- },
- },
- },
};
const res = {};
const endpointOption = {};