'use strict'; /** * Integration tests – dlq controller (controllers/dlq.js) * * The dlq controller connects to RabbitMQ for most of its functionality. * Tests here focus on pure input-validation paths that call next() with an * error before any RabbitMQ or Management-API call is made, plus DB-backed * partner paths (tracker stats, archive) that only require MongoDB. */ const { connectDB, disconnectDB } = require('./jest.setup'); const { mockReq, mockRes, newId } = require('./mock_data'); let PartnerLogTracker; beforeAll(async () => { await connectDB(); PartnerLogTracker = require('../../model/partner_log_tracker'); }); afterAll(async () => { await disconnectDB(); }); const dlqCtl = require('../../controllers/dlq'); // Helper: build a req with params and/or body. function makeReq({ params = {}, body = {}, query = {} } = {}) { const req = mockReq({ body, query }); req.params = params; return req; } // --------------------------------------------------------------------------- describe('dlq controller – getDLQStats_get', () => { it('calls next() when queueName param is missing', async () => { const req = makeReq({ params: {} }); const res = mockRes(); const next = jest.fn(); await dlqCtl.getDLQStats_get(req, res, next); expect(next).toHaveBeenCalled(); expect(res.json).not.toHaveBeenCalled(); }); it('returns stats with a numeric messageCount for a non-partner queue', async () => { const req = makeReq({ params: { queueName: 'dev_jobs' } }); const res = mockRes(); const next = jest.fn(); await dlqCtl.getDLQStats_get(req, res, next); // Either RabbitMQ is reachable (messageCount >= 0) or not (-1); the // response shape is always the same. expect(res.json).toHaveBeenCalled(); expect(res._data).toHaveProperty('dlq'); expect(typeof res._data.dlq.messageCount).toBe('number'); expect(res._data.trackers).toBeUndefined(); }); it('returns stats with tracker data for a partner queue (DB is reachable)', async () => { await PartnerLogTracker.deleteMany({}); const req = makeReq({ params: { queueName: 'partner_tasks' } }); const res = mockRes(); const next = jest.fn(); await dlqCtl.getDLQStats_get(req, res, next); expect(res.json).toHaveBeenCalled(); expect(res._data).toHaveProperty('dlq'); // Partner queue: tracker stats and recent failures are always included. expect(res._data.trackers).toBeDefined(); expect(res._data.recentFailures).toBeDefined(); expect(Array.isArray(res._data.recentFailures)).toBe(true); }); }); // --------------------------------------------------------------------------- describe('dlq controller – getDLQMessages_get', () => { it('throws when queueName param is missing', async () => { const req = makeReq({ params: {} }); const res = mockRes(); const next = jest.fn(); await expect(dlqCtl.getDLQMessages_get(req, res, next)).rejects.toThrow(); }); }); // --------------------------------------------------------------------------- describe('dlq controller – processDLQ_post', () => { it('calls next() when queueName param is missing', async () => { const req = makeReq({ params: {}, body: {} }); const res = mockRes(); const next = jest.fn(); await dlqCtl.processDLQ_post(req, res, next); expect(next).toHaveBeenCalled(); }); }); // --------------------------------------------------------------------------- describe('dlq controller – retryFailedTask_post', () => { it('calls next() when queueName is not a partner queue', async () => { const req = makeReq({ params: { queueName: 'dev_jobs', id: newId().toString() } }); const res = mockRes(); const next = jest.fn(); await dlqCtl.retryFailedTask_post(req, res, next); expect(next).toHaveBeenCalled(); }); it('calls next() when tracker id does not exist in the DB', async () => { const req = makeReq({ params: { queueName: 'partner_tasks', id: newId().toString() } }); const res = mockRes(); const next = jest.fn(); await dlqCtl.retryFailedTask_post(req, res, next); expect(next).toHaveBeenCalled(); }); }); // --------------------------------------------------------------------------- describe('dlq controller – archiveFailedTask_post', () => { it('calls next() when tracker id does not exist', async () => { const req = makeReq({ params: { id: newId().toString() }, body: { reason: 'test' } }); const res = mockRes(); const next = jest.fn(); await dlqCtl.archiveFailedTask_post(req, res, next); expect(next).toHaveBeenCalled(); }); }); // --------------------------------------------------------------------------- describe('dlq controller – purgeDLQ_delete', () => { it('calls next() when confirm is not true', async () => { const req = makeReq({ params: { queueName: 'dev_jobs' }, body: { confirm: false } }); const res = mockRes(); const next = jest.fn(); await dlqCtl.purgeDLQ_delete(req, res, next); expect(next).toHaveBeenCalled(); }); it('calls next() when queueName param is missing', async () => { const req = makeReq({ params: {}, body: { confirm: true } }); const res = mockRes(); const next = jest.fn(); await dlqCtl.purgeDLQ_delete(req, res, next); expect(next).toHaveBeenCalled(); }); }); // --------------------------------------------------------------------------- describe('dlq controller – retryAllDLQ_post', () => { it('calls next() when queueName param is missing', async () => { const req = makeReq({ params: {}, body: {} }); const res = mockRes(); const next = jest.fn(); await dlqCtl.retryAllDLQ_post(req, res, next); expect(next).toHaveBeenCalled(); }); }); // --------------------------------------------------------------------------- describe('dlq controller – retryDLQByPosition_post', () => { it('calls next() when position is missing from body', async () => { const req = makeReq({ params: { queueName: 'dev_jobs' }, body: {} }); const res = mockRes(); const next = jest.fn(); await dlqCtl.retryDLQByPosition_post(req, res, next); expect(next).toHaveBeenCalled(); }); it('calls next() when position is negative', async () => { const req = makeReq({ params: { queueName: 'dev_jobs' }, body: { position: -1 } }); const res = mockRes(); const next = jest.fn(); await dlqCtl.retryDLQByPosition_post(req, res, next); expect(next).toHaveBeenCalled(); }); }); // --------------------------------------------------------------------------- describe('dlq controller – retryDLQByHeader_post', () => { it('calls next() when headerName is missing', async () => { const req = makeReq({ params: { queueName: 'dev_jobs' }, body: { headerValue: 'val' } }); const res = mockRes(); const next = jest.fn(); await dlqCtl.retryDLQByHeader_post(req, res, next); expect(next).toHaveBeenCalled(); }); it('calls next() when headerValue is missing', async () => { const req = makeReq({ params: { queueName: 'dev_jobs' }, body: { headerName: 'x-id' } }); const res = mockRes(); const next = jest.fn(); await dlqCtl.retryDLQByHeader_post(req, res, next); expect(next).toHaveBeenCalled(); }); });