generated from finos-labs/project-blueprint
-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Features/#689 CLI Server
- Loading branch information
Showing
18 changed files
with
535 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import express, { Application } from 'express'; | ||
import { CLIServerRoutes } from './routes/routes'; | ||
import { initLogger } from '@finos/calm-shared'; | ||
|
||
export function startServer(options: { port: string, schemaDirectory: string, verbose: boolean }) { | ||
const app: Application = express(); | ||
const cliServerRoutesInstance = new CLIServerRoutes(options.schemaDirectory, options.verbose); | ||
const allRoutes = cliServerRoutesInstance.router; | ||
|
||
app.use(express.json()); | ||
app.use('/', allRoutes); | ||
|
||
const port = options.port; | ||
|
||
app.listen(port, () => { | ||
const logger = initLogger(options.verbose); | ||
logger.info(`CALM Server is running on http://localhost:${port}`); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import request from 'supertest'; | ||
|
||
import express, { Application } from 'express'; | ||
import { HealthRouter } from './health-route'; | ||
|
||
describe('HealthRouter', () => { | ||
let app: Application; | ||
|
||
beforeEach(() => { | ||
app = express(); | ||
app.use(express.json()); | ||
|
||
const router: express.Router = express.Router(); | ||
app.use('/health', router); | ||
new HealthRouter(router); | ||
|
||
}); | ||
|
||
test('should return 200 for health check', async () => { | ||
const response = await request(app) | ||
.get('/health'); | ||
expect(response.status).toBe(200); | ||
expect(response.body).toEqual({ status: 'OK' }); | ||
}); | ||
}); | ||
|
||
// }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Router, Request, Response } from 'express'; | ||
|
||
|
||
export class HealthRouter { | ||
|
||
constructor(router: Router) { | ||
router.get('/', this.healthCheck); | ||
} | ||
|
||
private healthCheck(_req: Request, res: Response<StatusResponse>) { | ||
res.status(200).type('json').send(new StatusResponse('OK')); | ||
} | ||
|
||
} | ||
|
||
class StatusResponse { | ||
status: string; | ||
|
||
constructor(status: string) { | ||
this.status = status; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { Router } from 'express'; | ||
import { CLIServerRoutes } from './routes'; | ||
import { ValidationRouter } from './validation-route'; | ||
import { HealthRouter } from './health-route'; | ||
|
||
const mockUse = jest.fn(); | ||
const mockRouter = { | ||
use: mockUse | ||
}; | ||
|
||
jest.mock('express', () => ({ | ||
Router: jest.fn(() => mockRouter) | ||
})); | ||
|
||
jest.mock('./validation-route', () => { | ||
return { | ||
ValidationRouter: jest.fn() | ||
}; | ||
}); | ||
|
||
jest.mock('./health-route', () => { | ||
return { | ||
HealthRouter: jest.fn() | ||
}; | ||
}); | ||
|
||
describe('CLIServerRoutes', () => { | ||
let schemaDirectoryPath: string; | ||
let cliServerRoutes: CLIServerRoutes; | ||
let mockRouter: Router; | ||
|
||
beforeEach(() => { | ||
schemaDirectoryPath = '/path/to/schema'; | ||
cliServerRoutes = new CLIServerRoutes(schemaDirectoryPath); | ||
mockRouter = cliServerRoutes.router; | ||
}); | ||
|
||
it('should initialize router', () => { | ||
expect(Router).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should set up validate route', () => { | ||
expect(mockRouter.use).toHaveBeenCalledWith('/calm/validate', mockRouter); | ||
expect(ValidationRouter).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should set up health route', () => { | ||
expect(mockRouter.use).toHaveBeenCalledWith('/health', mockRouter); | ||
expect(HealthRouter).toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Router } from 'express'; | ||
import { ValidationRouter } from './validation-route'; | ||
import { HealthRouter } from './health-route'; | ||
|
||
const HEALTH_ROUTE_PATH = '/health'; | ||
const VALIDATE_ROUTE_PATH = '/calm/validate'; | ||
|
||
export class CLIServerRoutes { | ||
router: Router; | ||
|
||
constructor(schemaDirectoryPath: string, debug: boolean = false) { | ||
this.router = Router(); | ||
const validateRoute = this.router.use(VALIDATE_ROUTE_PATH, this.router); | ||
new ValidationRouter(validateRoute, schemaDirectoryPath, debug); | ||
const healthRoute = this.router.use(HEALTH_ROUTE_PATH, this.router); | ||
new HealthRouter(healthRoute); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import request from 'supertest'; | ||
import * as fs from 'fs'; | ||
|
||
import express, { Application } from 'express'; | ||
import { ValidationRouter } from './validation-route'; | ||
import path from 'path'; | ||
|
||
const schemaDirectory : string = __dirname + '/../../../../calm'; | ||
|
||
describe('ValidationRouter', () => { | ||
let app: Application; | ||
|
||
beforeEach(() => { | ||
app = express(); | ||
app.use(express.json()); | ||
|
||
const router: express.Router = express.Router(); | ||
new ValidationRouter(router, schemaDirectory); | ||
app.use('/calm/validate', router); | ||
}); | ||
|
||
test('should return 400 when $schema is not specified', async () => { | ||
const expectedFilePath = path.join(__dirname, '../../../test_fixtures/validation_route/invalid_api_gateway_instantiation_missing_schema_key.json'); | ||
const invalidArchitectureMissingSchema = JSON.parse( | ||
fs.readFileSync(expectedFilePath, 'utf-8') | ||
); | ||
const response = await request(app) | ||
.post('/calm/validate') | ||
.send(invalidArchitectureMissingSchema); | ||
|
||
expect(response.status).toBe(400); | ||
expect(response.body).toEqual({ error: 'The "$schema" field is missing from the request body' }); | ||
}); | ||
|
||
test('should return 400 when the $schema specified in the instantiation is not found', async () => { | ||
const expectedFilePath = path.join(__dirname, '../../../test_fixtures/validation_route/invalid_api_gateway_instantiation_schema_points_to_missing_schema.json'); | ||
const invalidArchitectureMissingSchema = JSON.parse( | ||
fs.readFileSync(expectedFilePath, 'utf-8') | ||
); | ||
const response = await request(app) | ||
.post('/calm/validate') | ||
.send(invalidArchitectureMissingSchema); | ||
|
||
expect(response.status).toBe(400); | ||
expect(response.body).toEqual({ error: 'The "$schema" field referenced is not available to the server' }); | ||
}); | ||
|
||
test('should return 201 when the schema is valid', async () => { | ||
const expectedFilePath = path.join(__dirname, '../../../test_fixtures/validation_route/valid_instantiation.json'); | ||
const validArchitecture = JSON.parse( | ||
fs.readFileSync(expectedFilePath, 'utf-8') | ||
); | ||
const response = await request(app) | ||
.post('/calm/validate') | ||
.send(validArchitecture); | ||
|
||
expect(response.status).toBe(201); | ||
expect(response.body).toHaveProperty('jsonSchemaValidationOutputs'); | ||
expect(response.body).toHaveProperty('spectralSchemaValidationOutputs'); | ||
expect(response.body).toHaveProperty('hasErrors'); | ||
expect(response.body).toHaveProperty('hasWarnings'); | ||
}); | ||
|
||
}); | ||
|
||
// }); |
Oops, something went wrong.