/** * Arr Route Tests * * Tests Smart Arr Connect endpoints (detect, connect, credentials, test-connection) */ const request = require('supertest'); const fs = require('fs'); const path = require('path'); const os = require('os'); const testServicesFile = path.join(os.tmpdir(), `arr-services-${Date.now()}.json`); const testConfigFile = path.join(os.tmpdir(), `arr-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('Arr Routes', () => { afterAll(() => { try { fs.unlinkSync(testServicesFile); } catch (e) { /* ignore */ } try { fs.unlinkSync(testConfigFile); } catch (e) { /* ignore */ } }); describe('GET /api/arr/smart-detect', () => { test('should return detection results', async () => { const res = await request(app).get('/api/arr/smart-detect'); // Might return empty results if no Docker containers running expect(res.statusCode).toBe(200); expect(res.body.success).toBe(true); expect(res.body).toHaveProperty('services'); expect(typeof res.body.services).toBe('object'); }); }); describe('POST /api/arr/smart-connect', () => { test('should return empty results for empty request body', async () => { const res = await request(app) .post('/api/arr/smart-connect') .send({}); // With no services provided, the endpoint completes with empty steps expect(res.statusCode).toBe(200); expect(res.body).toHaveProperty('steps'); }, 15000); }); describe('POST /api/arr/test-connection', () => { test('should fail when missing url or apiKey', async () => { const res = await request(app) .post('/api/arr/test-connection') .send({ service: 'radarr' }); // Validation error returns 400 expect(res.statusCode).toBe(400); expect(res.body.success).toBe(false); expect(res.body.error).toContain('required'); }); test('should reject invalid URL format', async () => { const res = await request(app) .post('/api/arr/test-connection') .send({ url: 'not-a-url', service: 'radarr', apiKey: 'test-api-key-12345' }); expect(res.statusCode).toBe(400); }); }); describe('GET /api/arr/credentials', () => { test('should return credentials list', async () => { const res = await request(app).get('/api/arr/credentials'); expect(res.statusCode).toBe(200); expect(res.body.success).toBe(true); expect(res.body).toHaveProperty('credentials'); }); }); describe('POST /api/arr/credentials', () => { test('should reject missing service field', async () => { const res = await request(app) .post('/api/arr/credentials') .send({ apiKey: 'test-key' }); expect(res.statusCode).toBe(400); }); test('should reject missing apiKey field', async () => { const res = await request(app) .post('/api/arr/credentials') .send({ service: 'radarr' }); expect(res.statusCode).toBe(400); }); test('should store valid credentials', async () => { const res = await request(app) .post('/api/arr/credentials') .send({ service: 'radarr', apiKey: 'test-api-key-12345' }); expect(res.statusCode).toBe(200); expect(res.body.success).toBe(true); }); }); describe('DELETE /api/arr/credentials/:service', () => { test('should handle deleting non-existent credentials', async () => { const res = await request(app).delete('/api/arr/credentials/nonexistent'); // Should succeed (idempotent) or return 404 expect([200, 404]).toContain(res.statusCode); }); }); });