/** * Campaign Routes Tests * * Tests for `/api/plugins/voting/campaigns` endpoints * Uses REAL PostgreSQL database - NO mocks */ const request = require('supertest'); const express = require('express'); const campaignsRouter = require('../../routes/campaigns'); const VotingTestHelper = require('../helpers/testHelper'); describe('Campaign Routes', () => { let app; let testHelper; let testSite; let testUserId; beforeAll(async () => { // Create Express app for testing app = express(); app.use(express.json()); app.use('/api/plugins/voting', campaignsRouter); // Initialize test helper testHelper = new VotingTestHelper(); // Create test data testSite = await testHelper.createTestSite(); const testUser = await testHelper.createTestUser(testSite.id); testUserId = testUser.id; }); afterAll(async () => { // Cleanup handled by global schema manager }); describe('GET /api/plugins/voting/campaigns', () => { it('should return all campaigns for a site', async () => { // Create test campaigns const form1 = await testHelper.createTestForm(testSite.id); const form2 = await testHelper.createTestForm(testSite.id); await testHelper.createTestCampaign(testSite.id, form1.id, 'board_election'); await testHelper.createTestCampaign(testSite.id, form2.id, 'decision'); const response = await request(app) .get('/api/plugins/voting/campaigns') .query({ site_id: testSite.id }); expect(response.status).toBe(200); expect(response.body.success).toBe(true); expect(response.body.data).toBeInstanceOf(Array); expect(response.body.data.length).toBeGreaterThanOrEqual(2); // Verify campaign structure const campaign = response.body.data.find(c => c.campaign_type === 'board_election'); expect(campaign).toBeDefined(); expect(campaign.title).toBeDefined(); expect(campaign.status).toBeDefined(); }); it('should return empty array if no campaigns exist', async () => { // Create a different site with no campaigns const anotherSite = await testHelper.createTestSite(); const response = await request(app) .get('/api/plugins/voting/campaigns') .query({ site_id: anotherSite.id }); expect(response.status).toBe(200); expect(response.body.success).toBe(true); expect(response.body.data).toEqual([]); }); }); describe('GET /api/plugins/voting/campaigns/:id', () => { let testCampaign; beforeEach(async () => { // Create a test campaign const form = await testHelper.createTestForm(testSite.id); testCampaign = await testHelper.createTestCampaign(testSite.id, form.id); }); it('should return campaign details by ID', async () => { const response = await request(app) .get(`/api/plugins/voting/campaigns/${testCampaign.id}`) .query({ site_id: testSite.id }); expect(response.status).toBe(200); expect(response.body.success).toBe(true); expect(response.body.data).toBeDefined(); expect(response.body.data.id).toBe(testCampaign.id); expect(response.body.data.title).toBe(testCampaign.title); }); it('should return 404 if campaign not found', async () => { const response = await request(app) .get('/api/plugins/voting/campaigns/00000000-0000-0000-0000-000000000000'); expect(response.status).toBe(404); expect(response.body.success).toBe(false); expect(response.body.error).toBe('Campaign not found'); }); }); describe('POST /api/plugins/voting/campaigns', () => { it('should create a new campaign', async () => { const form = await testHelper.createTestForm(testSite.id); const campaignData = { site_id: testSite.id, title: 'New Board Election', description: 'Annual elections for board members', campaign_type: 'board_election', form_id: form.id, status: 'draft', overall_sharing_results: 'detailed', public_access: 'restrict', start_date: new Date().toISOString(), end_date: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(), recipient_type: 'all_owners', send_email: true, send_text: false, send_owner_app: true, created_by: testUserId }; const response = await request(app) .post('/api/plugins/voting/campaigns') .send(campaignData); expect(response.status).toBe(201); expect(response.body.success).toBe(true); expect(response.body.data).toBeDefined(); expect(response.body.data.title).toBe('New Board Election'); expect(response.body.data.campaign_type).toBe('board_election'); }); }); describe('PUT /api/plugins/voting/campaigns/:id', () => { let testCampaign; beforeEach(async () => { const form = await testHelper.createTestForm(testSite.id); testCampaign = await testHelper.createTestCampaign(testSite.id, form.id); }); it('should update campaign details', async () => { const updateData = { title: 'Updated Campaign Title', status: 'active' }; const response = await request(app) .put(`/api/plugins/voting/campaigns/${testCampaign.id}`) .send(updateData); expect(response.status).toBe(200); expect(response.body.success).toBe(true); expect(response.body.data.title).toBe('Updated Campaign Title'); expect(response.body.data.status).toBe('active'); }); it('should return 404 if campaign not found', async () => { const response = await request(app) .put('/api/plugins/voting/campaigns/00000000-0000-0000-0000-000000000000') .send({ title: 'Updated' }); expect(response.status).toBe(404); expect(response.body.success).toBe(false); }); }); describe('DELETE /api/plugins/voting/campaigns/:id', () => { let testCampaign; beforeEach(async () => { const form = await testHelper.createTestForm(testSite.id); testCampaign = await testHelper.createTestCampaign(testSite.id, form.id); }); it('should delete a campaign', async () => { const response = await request(app) .delete(`/api/plugins/voting/campaigns/${testCampaign.id}`); expect(response.status).toBe(200); expect(response.body.success).toBe(true); expect(response.body.message).toBe('Campaign deleted successfully'); // Verify deletion const getResponse = await request(app) .get(`/api/plugins/voting/campaigns/${testCampaign.id}`); expect(getResponse.status).toBe(404); }); it('should return 404 if campaign not found', async () => { const response = await request(app) .delete('/api/plugins/voting/campaigns/00000000-0000-0000-0000-000000000000'); expect(response.status).toBe(404); expect(response.body.success).toBe(false); }); }); });