UNPKG

@microsoft.azure/autorest.testserver

Version:
100 lines 4.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateSpecCoverageCommand = void 0; const path_1 = require("path"); const express_1 = require("express"); const api_1 = require("../../api"); const app_1 = require("../../app"); const constants_1 = require("../../constants"); const legacy_1 = require("../../legacy"); const logger_1 = require("../../logger"); const services_1 = require("../../services"); const utils_1 = require("../../utils"); const validateSpecCoverageCommand = async (options) => { const files = await (0, utils_1.findFilesFromPattern)((0, path_1.join)(constants_1.ProjectRoot, "swagger/*.json")); logger_1.logger.info(`Validating spec coverage, found ${files.length} specs.`); const paths = await (0, services_1.getPathsFromSpecs)(files); logger_1.logger.info(`Found ${paths.length} paths.`); const registeredPaths = await loadRegisteredRoutes(); logger_1.logger.info(`Found ${registeredPaths.length} mock paths.`); const errors = findSpecCoverageErrors(paths, registeredPaths); if (errors.length > 0) { for (const error of errors) { logger_1.logger.warn(`Route ${error.path.path} is missing a mocked API for methods: ${error.methods.join(",")}`); } logger_1.logger.warn(`Validate spec coverage found ${errors.length} missing endpoints.`); if (errors.length > options.maxErrorCount) { logger_1.logger.error(`Number of missing endpoint ${errors.length} is more than the number allowed ${options.maxErrorCount}. Failing.`); process.exit(-1); } } else { process.exit(0); } }; exports.validateSpecCoverageCommand = validateSpecCoverageCommand; const findSpecCoverageErrors = (paths, registeredPaths) => { const errors = []; for (const path of paths) { const missingMethods = validateRouteDefined(path, registeredPaths); if (missingMethods.length > 0) { errors.push({ path: path, methods: missingMethods }); } else { logger_1.logger.debug(`Route ${path.path} has a mocked API.`); } } return errors; }; /** * Validat the given path is defined in the mock api. * @param path Path to validate * @param registeredPaths List of all registered mock apis. * @returns list of methods that are not implemented for the given path. */ const validateRouteDefined = (path, registeredPaths) => { const methodFound = {}; for (const registeredPath of registeredPaths) { if (registeredPath.regexp.test(path.path)) { for (const [method, defined] of Object.entries(registeredPath.route.methods)) { if (defined) { methodFound[method] = true; } } } } return path.methods .filter((x) => x !== "options") .filter((x) => !methodFound[x]) .filter((x) => !x.startsWith("x-")); }; const loadRegisteredRoutes = async () => { await (0, app_1.requireMockRoutes)(app_1.ROUTE_FOLDER); const apiRouter = api_1.app; const legacyRouter = (0, express_1.Router)(); (0, legacy_1.registerLegacyRoutes)(legacyRouter); return [...apiRouter.router.stack, ...legacyRouter.stack].flatMap((x) => findRoutesFromMiddleware(x)); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const findRoutesFromMiddleware = (middleware) => { const routes = []; if (middleware.route) { routes.push({ route: middleware.route, regexp: middleware.regexp }); } else if (middleware.name === "router") { for (const nested of middleware.handle.stack) { if (nested.route) { routes.push({ route: nested.route, regexp: concatRegexp(middleware.regexp, nested.regexp) }); } } } return routes; }; /** * Combine the router regex with the child regex. */ function concatRegexp(router, child) { const reg = router.source.replace("\\/?(?=\\/|$)", child.source.slice(1)); return new RegExp(reg, child.flags); } //# sourceMappingURL=validate-spec-coverage-command.js.map