Files
labFusion/services/api-docs/__tests__/server.test.js
glenn schrooyen 8c87c84208
Some checks failed
API Docs (Node.js Express) / test (16) (push) Failing after 5m42s
API Docs (Node.js Express) / test (20) (push) Has been cancelled
API Docs (Node.js Express) / build (push) Has been cancelled
API Docs (Node.js Express) / security (push) Has been cancelled
API Docs (Node.js Express) / test (18) (push) Has been cancelled
LabFusion CI/CD Pipeline / api-gateway (push) Has been cancelled
LabFusion CI/CD Pipeline / service-adapters (push) Has been cancelled
LabFusion CI/CD Pipeline / api-docs (push) Has been cancelled
LabFusion CI/CD Pipeline / frontend (push) Has been cancelled
LabFusion CI/CD Pipeline / integration-tests (push) Has been cancelled
LabFusion CI/CD Pipeline / security-scan (push) Has been cancelled
Docker Build and Push / build-and-push (push) Has been cancelled
Docker Build and Push / security-scan (push) Has been cancelled
Docker Build and Push / deploy-staging (push) Has been cancelled
Docker Build and Push / deploy-production (push) Has been cancelled
Frontend (React) / test (16) (push) Has been cancelled
Frontend (React) / test (18) (push) Has been cancelled
Frontend (React) / test (20) (push) Has been cancelled
Frontend (React) / build (push) Has been cancelled
Frontend (React) / lighthouse (push) Has been cancelled
Frontend (React) / security (push) Has been cancelled
Integration Tests / performance-tests (push) Has been cancelled
Service Adapters (Python FastAPI) / security (push) Has been cancelled
Service Adapters (Python FastAPI) / test (3.1) (push) Has been cancelled
Service Adapters (Python FastAPI) / test (3.11) (push) Has been cancelled
Service Adapters (Python FastAPI) / test (3.12) (push) Has been cancelled
Service Adapters (Python FastAPI) / test (3.9) (push) Has been cancelled
Service Adapters (Python FastAPI) / build (push) Has been cancelled
Integration Tests / integration-tests (push) Has been cancelled
Update CI workflows for Python linting by increasing flake8 line length limit to 150 characters for better readability; adjust service-adapters.yml and ci.yml accordingly; update progress documentation
2025-09-12 22:42:47 +02:00

173 lines
5.4 KiB
JavaScript

const request = require('supertest')
const app = require('../server')
// Mock axios to avoid actual HTTP requests during tests
jest.mock('axios')
const axios = require('axios')
describe('API Docs Service', () => {
let server
beforeAll(() => {
// Start the server for testing
server = app.listen(0) // Use random available port
})
afterAll((done) => {
// Close the server after tests
server.close(done)
})
describe('GET /health', () => {
it('should return health status', async () => {
const response = await request(app)
.get('/health')
.expect(200)
expect(response.body).toHaveProperty('status', 'healthy')
expect(response.body).toHaveProperty('timestamp')
expect(new Date(response.body.timestamp)).toBeInstanceOf(Date)
})
})
describe('GET /services', () => {
beforeEach(() => {
// Reset axios mocks
jest.clearAllMocks()
})
it('should return service status for all services', async () => {
// Mock successful health checks for active services
axios.get.mockImplementation((url) => {
if (url.includes('/health')) {
return Promise.resolve({
headers: { 'x-response-time': '50ms' }
})
}
return Promise.reject(new Error('Not found'))
})
const response = await request(app)
.get('/services')
.expect(200)
expect(response.body).toHaveProperty('api-gateway')
expect(response.body).toHaveProperty('service-adapters')
expect(response.body).toHaveProperty('metrics-collector')
expect(response.body).toHaveProperty('notification-service')
// Check structure of service status
Object.values(response.body).forEach(service => {
expect(service).toHaveProperty('name')
expect(service).toHaveProperty('url')
expect(service).toHaveProperty('status')
})
})
it('should handle service health check failures', async () => {
// Mock all health checks to fail
axios.get.mockRejectedValue(new Error('Connection refused'))
const response = await request(app)
.get('/services')
.expect(200)
// All services should show as unhealthy or planned
Object.values(response.body).forEach(service => {
expect(['unhealthy', 'planned']).toContain(service.status)
if (service.status === 'unhealthy') {
expect(service).toHaveProperty('error')
}
})
})
})
describe('GET /openapi.json', () => {
beforeEach(() => {
jest.clearAllMocks()
})
it('should return unified OpenAPI specification', async () => {
// Mock service spec responses
axios.get.mockImplementation((url) => {
if (url.includes('/v3/api-docs')) {
return Promise.resolve({
data: {
openapi: '3.0.0',
info: { title: 'API Gateway', version: '1.0.0' },
paths: { '/test': { get: { summary: 'Test endpoint' } } },
components: { schemas: {} }
}
})
}
if (url.includes('/openapi.json')) {
return Promise.resolve({
data: {
openapi: '3.0.0',
info: { title: 'Service Adapters', version: '1.0.0' },
paths: { '/health': { get: { summary: 'Health check' } } },
components: { schemas: {} }
}
})
}
return Promise.reject(new Error('Not found'))
})
const response = await request(app)
.get('/openapi.json')
.expect(200)
expect(response.body).toHaveProperty('openapi', '3.0.0')
expect(response.body).toHaveProperty('info')
expect(response.body).toHaveProperty('paths')
expect(response.body).toHaveProperty('components')
expect(response.body).toHaveProperty('tags')
// Check that paths are prefixed with service names
expect(response.body.paths).toHaveProperty('/api-gateway/test')
expect(response.body.paths).toHaveProperty('/service-adapters/health')
})
it('should handle service spec fetch failures gracefully', async () => {
// Mock all service spec requests to fail
axios.get.mockRejectedValue(new Error('Service unavailable'))
const response = await request(app)
.get('/openapi.json')
.expect(200)
expect(response.body).toHaveProperty('openapi', '3.0.0')
expect(response.body).toHaveProperty('info')
expect(response.body).toHaveProperty('paths')
expect(response.body).toHaveProperty('components')
expect(response.body).toHaveProperty('tags')
// Should still have tags for all services
expect(response.body.tags).toHaveLength(4)
})
})
describe('GET /api-docs.json', () => {
it('should return API docs service specification', async () => {
const response = await request(app)
.get('/api-docs.json')
.expect(200)
expect(response.body).toHaveProperty('openapi', '3.0.0')
expect(response.body).toHaveProperty('info')
expect(response.body.info).toHaveProperty('title', 'LabFusion API Docs Service')
})
})
describe('GET /', () => {
it('should serve Swagger UI', async () => {
const response = await request(app)
.get('/')
.expect(200)
expect(response.text).toContain('swagger-ui')
expect(response.text).toContain('LabFusion API Documentation')
})
})
})