diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 32d9cc8d05..5c5e1b1db3 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -29,6 +29,7 @@ module.exports = { { files: ['*-mock.js', '*.test.js'], rules: { + 'no-empty-function': 'off', 'no-unused-vars': 'off', }, }, diff --git a/src/controllers/http-api/http-api-router.js b/src/controllers/http-api/http-api-router.js index 3643850f1f..cadf110dfd 100644 --- a/src/controllers/http-api/http-api-router.js +++ b/src/controllers/http-api/http-api-router.js @@ -3,7 +3,6 @@ import { HTTP_API_ROUTES } from '../../constants/constants.js'; class HttpApiRouter { constructor(ctx) { - this.config = ctx.config; this.httpClientModuleManager = ctx.httpClientModuleManager; this.apiRoutes = HTTP_API_ROUTES; @@ -19,6 +18,7 @@ class HttpApiRouter { const versionedController = `${stringUtil.toCamelCase( operation, )}HttpApiController${stringUtil.capitalize(version)}`; + this[versionedController] = ctx[versionedController]; } } diff --git a/test/unit/api/http-api-router.test.js b/test/unit/api/http-api-router.test.js new file mode 100644 index 0000000000..0c8e3af4d8 --- /dev/null +++ b/test/unit/api/http-api-router.test.js @@ -0,0 +1,80 @@ +import { beforeEach, describe, it } from 'mocha'; +import { expect } from 'chai'; +import sinon from 'sinon'; +import HttpApiRouter from '../../../src/controllers/http-api/http-api-router.js'; +import JsonSchemaServiceMock from '../mock/json-schema-service-mock.js'; +import HttpClientModuleManagerMock from '../mock/http-client-module-manager-mock.js'; +import { HTTP_API_ROUTES } from '../../../src/constants/constants.js'; + +describe('HTTP API Router test', async () => { + let httpApiRouter; + const controllerMocks = {}; + + beforeEach(() => { + // Mock Controllers + Object.keys(HTTP_API_ROUTES).forEach((version) => { + Object.keys(HTTP_API_ROUTES[version]).forEach((operation) => { + const versionedController = `${operation}HttpApiController${ + version.charAt(1).toUpperCase() + version.slice(2) + }`; + controllerMocks[versionedController] = { handleRequest: sinon.stub() }; + }); + }); + + // Mock context + const ctx = { + httpClientModuleManager: new HttpClientModuleManagerMock(), + jsonSchemaService: new JsonSchemaServiceMock(), + ...controllerMocks, + }; + + // Initialize HttpApiRouter with mocks + httpApiRouter = new HttpApiRouter(ctx); + }); + + it('Router has all defined routes', async () => { + // Extract unique HTTP methods present across all versions + const httpMethods = new Set(); + Object.values(HTTP_API_ROUTES).forEach((routes) => { + Object.values(routes).forEach((route) => { + httpMethods.add(route.method); + }); + }); + + // Create spies for each extracted HTTP method on each router instance and httpClientModuleManager + const spies = {}; + Object.keys(HTTP_API_ROUTES).forEach((version) => { + spies[version] = {}; + Array.from(httpMethods).forEach((method) => { + spies[version][method] = sinon.spy(httpApiRouter.routers[version], method); + }); + }); + const httpClientModuleManagerUseSpy = sinon.spy( + httpApiRouter.httpClientModuleManager, + 'use', + ); + + // Initialize the routes + await httpApiRouter.initialize(); + + // Validate each route + Object.entries(HTTP_API_ROUTES).forEach(([version, routes]) => { + expect(httpClientModuleManagerUseSpy.calledWith(`/${version}`)).to.equal(true); + + Object.values(routes).forEach((routeDetails) => { + const { method, path } = routeDetails; + expect(spies[version][method].calledWith(path)).to.equal(true); + }); + }); + expect(httpClientModuleManagerUseSpy.calledWith('/latest')).to.equal(true); + expect(httpClientModuleManagerUseSpy.calledWith('/')).to.equal(true); + + // Restore all spies + Object.values(spies).forEach((versionSpies) => { + Object.values(versionSpies).forEach((spy) => { + spy.restore(); + }); + }); + httpClientModuleManagerUseSpy.restore(); + }); +}); diff --git a/test/unit/mock/http-client-module-manager-mock.js b/test/unit/mock/http-client-module-manager-mock.js new file mode 100644 index 0000000000..7a98216032 --- /dev/null +++ b/test/unit/mock/http-client-module-manager-mock.js @@ -0,0 +1,25 @@ +import express from 'express'; + +class HttpClientModuleManagerMock { + createRouterInstance() { + return express.Router(); + } + + initializeBeforeMiddlewares() {} + + async listen() {} + + use(path, callback) {} + + get() {} + + post() {} + + selectMiddlewares(options) { + return []; + } + + initializeAfterMiddlewares() {} +} + +export default HttpClientModuleManagerMock; diff --git a/test/unit/mock/json-schema-service-mock.js b/test/unit/mock/json-schema-service-mock.js new file mode 100644 index 0000000000..45e16b0ff7 --- /dev/null +++ b/test/unit/mock/json-schema-service-mock.js @@ -0,0 +1,3 @@ +class JsonSchemaServiceMock {} + +export default JsonSchemaServiceMock;