152 lines
4.9 KiB
JavaScript
152 lines
4.9 KiB
JavaScript
/**
|
|
* 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 db module to avoid requiring DATABASE_URL in CI
|
|
jest.mock('../db', () => ({
|
|
query: jest.fn(() => Promise.resolve({ rows: [] })),
|
|
}));
|
|
|
|
// 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);
|
|
});
|
|
});
|
|
});
|