@microsoft.azure/autorest.testserver
Version:
Autorest test server.
100 lines • 4.12 kB
JavaScript
;
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