/** * Config Route Tests * * Tests DashCaddy configuration endpoints (get, save, delete) */ const request = require('supertest'); const fs = require('fs'); const path = require('path'); const os = require('os'); const testServicesFile = path.join(os.tmpdir(), `config-services-${Date.now()}.json`); const testConfigFile = path.join(os.tmpdir(), `config-config-${Date.now()}.json`); process.env.SERVICES_FILE = testServicesFile; process.env.CONFIG_FILE = testConfigFile; process.env.ENABLE_HEALTH_CHECKER = 'false'; process.env.NODE_ENV = 'test'; fs.writeFileSync(testServicesFile, '[]', 'utf8'); fs.writeFileSync(testConfigFile, '{}', 'utf8'); const app = require('../server'); describe('Config Routes', () => { afterAll(() => { try { fs.unlinkSync(testServicesFile); } catch (e) { /* ignore */ } try { fs.unlinkSync(testConfigFile); } catch (e) { /* ignore */ } }); // Reset config file before each test to avoid leaking state beforeEach(() => { fs.writeFileSync(testConfigFile, '{}', 'utf8'); }); describe('GET /api/config', () => { test('should return 200 with config object', async () => { const res = await request(app).get('/api/config'); expect(res.statusCode).toBe(200); expect(typeof res.body).toBe('object'); }); }); describe('POST /api/config', () => { test('should return 200 with success:true for valid config', async () => { const validConfig = { tld: 'sami', theme: 'dark', timezone: 'America/New_York' }; const res = await request(app) .post('/api/config') .send(validConfig); expect(res.statusCode).toBe(200); expect(res.body.success).toBe(true); // Verify config was persisted const savedConfig = JSON.parse(fs.readFileSync(testConfigFile, 'utf8')); expect(savedConfig.tld).toBe('sami'); expect(savedConfig.theme).toBe('dark'); }); test('should return 400 for invalid config body', async () => { // Send a non-object body (string) which fails the typeof check const res = await request(app) .post('/api/config') .set('Content-Type', 'application/json') .send('"not an object"'); expect(res.statusCode).toBe(400); }); test('should return 400 for config with invalid field values', async () => { const invalidConfig = { tld: 123, // tld must be a string dns: 'not-an-object' // dns must be an object }; const res = await request(app) .post('/api/config') .send(invalidConfig); expect(res.statusCode).toBe(400); }); }); describe('DELETE /api/config', () => { test('should return 200 and reset config', async () => { // First save a config await request(app) .post('/api/config') .send({ tld: 'sami', theme: 'dark' }); // Then delete it const res = await request(app).delete('/api/config'); expect(res.statusCode).toBe(200); expect(res.body.success).toBe(true); // Config file should no longer exist expect(fs.existsSync(testConfigFile)).toBe(false); }); test('should return 200 even when config does not exist', async () => { // Remove the config file first try { fs.unlinkSync(testConfigFile); } catch (e) { /* ignore */ } const res = await request(app).delete('/api/config'); expect(res.statusCode).toBe(200); expect(res.body.success).toBe(true); }); }); });