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
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
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
This commit is contained in:
@@ -82,7 +82,7 @@ jobs:
|
||||
isort --check-only .
|
||||
|
||||
- name: Run linting
|
||||
run: flake8 .
|
||||
run: flake8 . --count --max-complexity=10 --max-line-length=150
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
- name: Run linting
|
||||
run: |
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
flake8 . --count --max-complexity=10 --max-line-length=150 --statistics
|
||||
|
||||
- name: Run type checking
|
||||
run: mypy . --ignore-missing-imports
|
||||
|
||||
@@ -214,6 +214,8 @@ The modular structure allows for easy addition of new services:
|
||||
- [x] Set up CI/CD pipelines for automated testing and deployment
|
||||
- [x] Fix Maven command not found error in CI/CD pipelines (Added Maven wrapper)
|
||||
- [x] Fix Python formatting issues in CI/CD pipelines (Applied Black and isort formatting)
|
||||
- [x] Update flake8 line length limit to 150 characters for better readability
|
||||
- [x] Create JavaScript/Node.js tests for API docs service and frontend
|
||||
|
||||
## Resources
|
||||
- [Project Specifications](specs.md)
|
||||
|
||||
58
frontend/src/App.test.js
Normal file
58
frontend/src/App.test.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import React from 'react'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import App from './App'
|
||||
|
||||
// Mock the service status hook to avoid API calls during tests
|
||||
jest.mock('./hooks/useServiceStatus', () => ({
|
||||
useServiceStatus: () => ({
|
||||
isOnline: true,
|
||||
services: {
|
||||
'api-gateway': { status: 'healthy', lastCheck: new Date().toISOString() },
|
||||
'service-adapters': { status: 'healthy', lastCheck: new Date().toISOString() },
|
||||
'api-docs': { status: 'healthy', lastCheck: new Date().toISOString() }
|
||||
},
|
||||
isLoading: false,
|
||||
error: null
|
||||
})
|
||||
}))
|
||||
|
||||
// Mock the system data hook
|
||||
jest.mock('./hooks/useServiceStatus', () => ({
|
||||
useSystemData: () => ({
|
||||
systemStats: {
|
||||
cpuUsage: 45.2,
|
||||
memoryUsage: 2.1,
|
||||
diskUsage: 75.8
|
||||
},
|
||||
recentEvents: [
|
||||
{
|
||||
id: '1',
|
||||
timestamp: new Date().toISOString(),
|
||||
service: 'api-gateway',
|
||||
event_type: 'health_check',
|
||||
metadata: 'Service is healthy'
|
||||
}
|
||||
],
|
||||
isLoading: false,
|
||||
error: null
|
||||
})
|
||||
}))
|
||||
|
||||
describe('App Component', () => {
|
||||
it('renders without crashing', () => {
|
||||
render(<App />)
|
||||
expect(screen.getByText(/LabFusion/i)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders the main dashboard', () => {
|
||||
render(<App />)
|
||||
// Check for common dashboard elements
|
||||
expect(screen.getByText(/Dashboard/i)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows service status when online', () => {
|
||||
render(<App />)
|
||||
// Should show service status information
|
||||
expect(screen.getByText(/Service Status/i)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
76
frontend/src/utils/errorHandling.test.js
Normal file
76
frontend/src/utils/errorHandling.test.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import { formatError, formatServiceData, formatEventData } from './errorHandling'
|
||||
|
||||
describe('Error Handling Utils', () => {
|
||||
describe('formatError', () => {
|
||||
it('should format error objects correctly', () => {
|
||||
const error = new Error('Test error message')
|
||||
const formatted = formatError(error)
|
||||
|
||||
expect(formatted).toHaveProperty('message', 'Test error message')
|
||||
expect(formatted).toHaveProperty('type', 'Error')
|
||||
})
|
||||
|
||||
it('should handle string errors', () => {
|
||||
const error = 'Simple string error'
|
||||
const formatted = formatError(error)
|
||||
|
||||
expect(formatted).toHaveProperty('message', 'Simple string error')
|
||||
expect(formatted).toHaveProperty('type', 'string')
|
||||
})
|
||||
|
||||
it('should handle unknown error types', () => {
|
||||
const error = { someProperty: 'value' }
|
||||
const formatted = formatError(error)
|
||||
|
||||
expect(formatted).toHaveProperty('message', 'Unknown error occurred')
|
||||
expect(formatted).toHaveProperty('type', 'unknown')
|
||||
})
|
||||
})
|
||||
|
||||
describe('formatServiceData', () => {
|
||||
it('should format service data correctly', () => {
|
||||
const rawData = {
|
||||
'api-gateway': {
|
||||
status: 'healthy',
|
||||
lastCheck: '2024-01-01T00:00:00.000Z'
|
||||
}
|
||||
}
|
||||
|
||||
const formatted = formatServiceData(rawData)
|
||||
|
||||
expect(formatted).toHaveProperty('api-gateway')
|
||||
expect(formatted['api-gateway']).toHaveProperty('status', 'healthy')
|
||||
expect(formatted['api-gateway']).toHaveProperty('lastCheck')
|
||||
})
|
||||
|
||||
it('should handle empty data', () => {
|
||||
const formatted = formatServiceData({})
|
||||
expect(formatted).toEqual({})
|
||||
})
|
||||
})
|
||||
|
||||
describe('formatEventData', () => {
|
||||
it('should format event data correctly', () => {
|
||||
const rawEvents = [
|
||||
{
|
||||
id: '1',
|
||||
timestamp: '2024-01-01T00:00:00.000Z',
|
||||
service: 'api-gateway',
|
||||
event_type: 'health_check'
|
||||
}
|
||||
]
|
||||
|
||||
const formatted = formatEventData(rawEvents)
|
||||
|
||||
expect(Array.isArray(formatted)).toBe(true)
|
||||
expect(formatted[0]).toHaveProperty('id', '1')
|
||||
expect(formatted[0]).toHaveProperty('service', 'api-gateway')
|
||||
})
|
||||
|
||||
it('should handle empty events array', () => {
|
||||
const formatted = formatEventData([])
|
||||
expect(Array.isArray(formatted)).toBe(true)
|
||||
expect(formatted).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
172
services/api-docs/__tests__/server.test.js
Normal file
172
services/api-docs/__tests__/server.test.js
Normal file
@@ -0,0 +1,172 @@
|
||||
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')
|
||||
})
|
||||
})
|
||||
})
|
||||
13
services/api-docs/jest.config.js
Normal file
13
services/api-docs/jest.config.js
Normal file
@@ -0,0 +1,13 @@
|
||||
module.exports = {
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/__tests__/**/*.test.js', '**/?(*.)+(spec|test).js'],
|
||||
collectCoverageFrom: [
|
||||
'server.js',
|
||||
'!node_modules/**',
|
||||
'!coverage/**'
|
||||
],
|
||||
coverageDirectory: 'coverage',
|
||||
coverageReporters: ['text', 'lcov', 'html'],
|
||||
testTimeout: 10000,
|
||||
setupFilesAfterEnv: ['<rootDir>/jest.setup.js']
|
||||
}
|
||||
18
services/api-docs/jest.setup.js
Normal file
18
services/api-docs/jest.setup.js
Normal file
@@ -0,0 +1,18 @@
|
||||
// Jest setup file
|
||||
// This file runs before each test file
|
||||
|
||||
// Mock console methods to reduce noise in tests
|
||||
global.console = {
|
||||
...console,
|
||||
log: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
error: jest.fn()
|
||||
}
|
||||
|
||||
// Set test environment variables
|
||||
process.env.NODE_ENV = 'test'
|
||||
process.env.PORT = '8083'
|
||||
process.env.API_GATEWAY_URL = 'http://localhost:8080'
|
||||
process.env.SERVICE_ADAPTERS_URL = 'http://localhost:8000'
|
||||
process.env.METRICS_COLLECTOR_URL = 'http://localhost:8081'
|
||||
process.env.NOTIFICATION_SERVICE_URL = 'http://localhost:8082'
|
||||
64
services/api-docs/package-lock.json
generated
64
services/api-docs/package-lock.json
generated
@@ -13,7 +13,7 @@
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.2",
|
||||
"express": "^4.21.2",
|
||||
"swagger-jsdoc": "^7.0.0-rc.6",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
"swagger-ui-express": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -55,9 +55,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@apidevtools/swagger-parser": {
|
||||
"version": "10.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.2.tgz",
|
||||
"integrity": "sha512-JFxcEyp8RlNHgBCE98nwuTkZT6eNFPc1aosWV6wPcQph72TSEEu1k3baJD4/x1qznU+JiDdz8F5pTwabZh+Dhg==",
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz",
|
||||
"integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@apidevtools/json-schema-ref-parser": "^9.0.6",
|
||||
@@ -65,7 +65,7 @@
|
||||
"@apidevtools/swagger-methods": "^3.0.2",
|
||||
"@jsdevtools/ono": "^7.1.3",
|
||||
"call-me-maybe": "^1.0.1",
|
||||
"z-schema": "^4.2.3"
|
||||
"z-schema": "^5.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"openapi-types": ">=7"
|
||||
@@ -2332,11 +2332,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz",
|
||||
"integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==",
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/component-emitter": {
|
||||
"version": "1.3.1",
|
||||
@@ -7333,28 +7335,32 @@
|
||||
}
|
||||
},
|
||||
"node_modules/swagger-jsdoc": {
|
||||
"version": "7.0.0-rc.6",
|
||||
"resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-7.0.0-rc.6.tgz",
|
||||
"integrity": "sha512-LIvIPQxipRaOzIij+HrWOcCWTINE6OeJuqmXCfDkofVcstPVABHRkaAc3D7vrX9s7L0ccH0sH0amwHgN6+SXPg==",
|
||||
"version": "6.2.8",
|
||||
"resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz",
|
||||
"integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "6.2.0",
|
||||
"doctrine": "3.0.0",
|
||||
"glob": "7.1.6",
|
||||
"lodash.mergewith": "4.6.2",
|
||||
"swagger-parser": "10.0.2",
|
||||
"lodash.mergewith": "^4.6.2",
|
||||
"swagger-parser": "^10.0.3",
|
||||
"yaml": "2.0.0-1"
|
||||
},
|
||||
"bin": {
|
||||
"swagger-jsdoc": "bin/swagger-jsdoc.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/swagger-parser": {
|
||||
"version": "10.0.2",
|
||||
"resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.2.tgz",
|
||||
"integrity": "sha512-9jHkHM+QXyLGFLk1DkXBwV+4HyNm0Za3b8/zk/+mjr8jgOSiqm3FOTHBSDsBjtn9scdL+8eWcHdupp2NLM8tDw==",
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz",
|
||||
"integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-parser": "10.0.2"
|
||||
"@apidevtools/swagger-parser": "10.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
@@ -7965,23 +7971,33 @@
|
||||
}
|
||||
},
|
||||
"node_modules/z-schema": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/z-schema/-/z-schema-4.2.4.tgz",
|
||||
"integrity": "sha512-YvBeW5RGNeNzKOUJs3rTL4+9rpcvHXt5I051FJbOcitV8bl40pEfcG0Q+dWSwS0/BIYrMZ/9HHoqLllMkFhD0w==",
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz",
|
||||
"integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash.get": "^4.4.2",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"validator": "^13.6.0"
|
||||
"validator": "^13.7.0"
|
||||
},
|
||||
"bin": {
|
||||
"z-schema": "bin/z-schema"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"commander": "^2.7.1"
|
||||
"commander": "^9.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/z-schema/node_modules/commander": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
|
||||
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": "^12.20.0 || >=14"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.2",
|
||||
"express": "^4.21.2",
|
||||
"swagger-jsdoc": "^7.0.0-rc.6",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
"swagger-ui-express": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -324,8 +324,13 @@ app.get('/', swaggerUi.setup(null, {
|
||||
customSiteTitle: 'LabFusion API Documentation'
|
||||
}))
|
||||
|
||||
// Start server
|
||||
// Export app for testing
|
||||
module.exports = app
|
||||
|
||||
// Start server only if not in test environment
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
app.listen(PORT, () => {
|
||||
console.log(`LabFusion API Docs server running on port ${PORT}`)
|
||||
console.log(`Access the documentation at: http://localhost:${PORT}`)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user