| | const fs = require('fs'); |
| | const request = require('supertest'); |
| | const { MongoMemoryServer } = require('mongodb-memory-server'); |
| | const mongoose = require('mongoose'); |
| |
|
| | jest.mock('~/server/services/Config', () => ({ |
| | loadCustomConfig: jest.fn(() => Promise.resolve({})), |
| | 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', () => { |
| | |
| | jest.setTimeout(30_000); |
| |
|
| | let mongoServer; |
| | let app; |
| |
|
| | |
| | const originalReadFileSync = fs.readFileSync; |
| | beforeAll(() => { |
| | fs.readFileSync = function (filepath, options) { |
| | if (filepath.includes('index.html')) { |
| | return '<!DOCTYPE html><html><head><title>LibreChat</title></head><body><div id="root"></div></body></html>'; |
| | } |
| | return originalReadFileSync(filepath, options); |
| | }; |
| | }); |
| |
|
| | afterAll(() => { |
| | |
| | fs.readFileSync = originalReadFileSync; |
| | }); |
| |
|
| | beforeAll(async () => { |
| | |
| | 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'), |
| | '<!DOCTYPE html><html><head><title>LibreChat</title></head><body><div id="root"></div></body></html>', |
| | ); |
| |
|
| | mongoServer = await MongoMemoryServer.create(); |
| | process.env.MONGO_URI = mongoServer.getUri(); |
| | process.env.PORT = '0'; |
| | app = require('~/server'); |
| |
|
| | |
| | await healthCheckPoll(app); |
| | }); |
| |
|
| | afterAll(async () => { |
| | await mongoServer.stop(); |
| | await mongoose.disconnect(); |
| | }); |
| |
|
| | it('should return OK for /health', async () => { |
| | const response = await request(app).get('/health'); |
| | expect(response.status).toBe(200); |
| | expect(response.text).toBe('OK'); |
| | }); |
| |
|
| | it('should not cache index page', async () => { |
| | const response = await request(app).get('/'); |
| | expect(response.status).toBe(200); |
| | expect(response.headers['cache-control']).toBe('no-cache, no-store, must-revalidate'); |
| | expect(response.headers['pragma']).toBe('no-cache'); |
| | expect(response.headers['expires']).toBe('0'); |
| | }); |
| |
|
| | it('should return 500 for unknown errors via ErrorController', async () => { |
| | |
| |
|
| | |
| | const originalFindOne = mongoose.models.User.findOne; |
| | const mockError = new Error('MongoDB operation failed'); |
| | mongoose.models.User.findOne = jest.fn().mockImplementation(() => { |
| | throw mockError; |
| | }); |
| |
|
| | try { |
| | const response = await request(app).post('/api/auth/login').send({ |
| | email: 'test@example.com', |
| | password: 'password123', |
| | }); |
| |
|
| | expect(response.status).toBe(500); |
| | expect(response.text).toBe('An unknown error occurred.'); |
| | } finally { |
| | |
| | mongoose.models.User.findOne = originalFindOne; |
| | } |
| | }); |
| | }); |
| |
|
| | |
| | async function healthCheckPoll(app, retries = 0) { |
| | const maxRetries = Math.floor(10000 / 30); |
| | try { |
| | const response = await request(app).get('/health'); |
| | if (response.status === 200) { |
| | return; |
| | } |
| | } catch { |
| | |
| | } |
| |
|
| | if (retries < maxRetries) { |
| | await new Promise((resolve) => setTimeout(resolve, 30)); |
| | await healthCheckPoll(app, retries + 1); |
| | } else { |
| | throw new Error('App did not become healthy within 10 seconds.'); |
| | } |
| | } |
| |
|