| 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.'); |
| } |
| } |
|
|