/** * Example-Based Tests: Route Removal and Remaining Routes * * Feature: jira-api-compliance-cleanup * * Property 2: Search route is absent from router (Example) * After the route removal, a POST request to /api/jira/search SHALL return HTTP 404. * Validates: Requirements 1.1, 1.2 * * Property 3: Existing routes remain functional after search route removal (Example) * The routes GET /lookup/:issueKey, POST /sync-all, POST /:id/sync, and * POST /create-in-jira SHALL continue to respond with non-404 status codes. * Validates: Requirements 1.3, 1.4, 1.5, 1.6 */ const http = require('http'); const express = require('express'); // Mock the auth middleware so routes don't require real sessions/cookies. jest.mock('../middleware/auth', () => ({ requireAuth: () => (req, res, next) => { req.user = { id: 1, username: 'test', group: 'Admin' }; next(); }, requireGroup: () => (req, res, next) => next(), })); // Mock the audit log helper to be a no-op. jest.mock('../helpers/auditLog', () => jest.fn()); // Mock the jiraApi helper — mark it as not configured so routes return 503 // (which is fine; we only care that they are NOT 404). jest.mock('../helpers/jiraApi', () => ({ isConfigured: false, getRateLimitStatus: jest.fn(() => ({ burst: { remaining: 60, limit: 60 }, daily: { remaining: 1440, limit: 1440 }, })), })); const createJiraTicketsRouter = require('../routes/jiraTickets'); // Minimal db mock — callback-style methods that return empty results. function createMockDb() { return { get: jest.fn((_sql, _params, cb) => cb(null, null)), all: jest.fn((_sql, _params, cb) => cb(null, [])), run: jest.fn(function (_sql, _params, cb) { if (typeof cb === 'function') cb.call({ lastID: 1, changes: 0 }, null); }), }; } /** * Helper: send an HTTP request to the test server and return { statusCode }. */ function request(server, method, path, body) { return new Promise((resolve, reject) => { const addr = server.address(); const options = { hostname: '127.0.0.1', port: addr.port, path, method, headers: { 'Content-Type': 'application/json' }, }; const req = http.request(options, (res) => { // Consume the response body so the socket closes cleanly. const chunks = []; res.on('data', (chunk) => chunks.push(chunk)); res.on('end', () => { resolve({ statusCode: res.statusCode }); }); }); req.on('error', reject); if (body) { req.write(JSON.stringify(body)); } req.end(); }); } describe('Feature: jira-api-compliance-cleanup — route removal tests', () => { let app; let server; beforeAll((done) => { const db = createMockDb(); app = express(); app.use(express.json()); app.use('/api/jira-tickets', createJiraTicketsRouter(db)); // Listen on a random available port. server = app.listen(0, '127.0.0.1', done); }); afterAll((done) => { server.close(done); }); // --------------------------------------------------------------------------- // Property 2: POST /api/jira-tickets/search returns 404 // Validates: Requirements 1.1, 1.2 // --------------------------------------------------------------------------- describe('Property 2: Search route is absent', () => { it('POST /api/jira-tickets/search returns HTTP 404', async () => { const res = await request(server, 'POST', '/api/jira-tickets/search', { jql: 'project = TEST', }); expect(res.statusCode).toBe(404); }); }); // --------------------------------------------------------------------------- // Property 3: Remaining routes respond with non-404 status codes // Validates: Requirements 1.3, 1.4, 1.5, 1.6 // --------------------------------------------------------------------------- describe('Property 3: Existing routes remain functional', () => { it('GET /api/jira-tickets/lookup/:issueKey returns non-404', async () => { const res = await request(server, 'GET', '/api/jira-tickets/lookup/TEST-1'); expect(res.statusCode).not.toBe(404); }); it('POST /api/jira-tickets/sync-all returns non-404', async () => { const res = await request(server, 'POST', '/api/jira-tickets/sync-all'); expect(res.statusCode).not.toBe(404); }); it('POST /api/jira-tickets/:id/sync returns non-404', async () => { const res = await request(server, 'POST', '/api/jira-tickets/1/sync'); expect(res.statusCode).not.toBe(404); }); it('POST /api/jira-tickets/create-in-jira returns non-404', async () => { const res = await request(server, 'POST', '/api/jira-tickets/create-in-jira', { cve_id: 'CVE-2024-12345', vendor: 'TestVendor', summary: 'Test summary', }); expect(res.statusCode).not.toBe(404); }); }); });