oav/lib/apiScenario/swaggerAnalyzer.ts

133 строки
5.2 KiB
TypeScript
Исходник Постоянная ссылка Обычный вид История

import { JSONPath } from "jsonpath-plus";
import { inject, injectable } from "inversify";
import _ from "lodash";
import { TYPES } from "../inversifyUtils";
import { FileLoaderOption, FileLoader } from "../swagger/fileLoader";
import { JsonLoader, JsonLoaderOption } from "../swagger/jsonLoader";
import { SwaggerLoader, SwaggerLoaderOption } from "../swagger/swaggerLoader";
import { Path, SwaggerSpec, Schema, LowerHttpMethods, Operation } from "../swagger/swaggerTypes";
import { AjvSchemaValidator } from "../swaggerValidator/ajvSchemaValidator";
import { SchemaValidator } from "../swaggerValidator/schemaValidator";
import { allOfTransformer } from "../transform/allOfTransformer";
import { getTransformContext, TransformContext } from "../transform/context";
import { discriminatorTransformer } from "../transform/discriminatorTransformer";
import { noAdditionalPropertiesTransformer } from "../transform/noAdditionalPropertiesTransformer";
import { referenceFieldsTransformer } from "../transform/referenceFieldsTransformer";
import { resolveNestedDefinitionTransformer } from "../transform/resolveNestedDefinitionTransformer";
import { xmsPathsTransformer } from "../transform/xmsPathsTransformer";
import { applyGlobalTransformers, applySpecTransformers } from "../transform/transformer";
import { traverseSwagger, traverseSwaggerAsync } from "../transform/traverseSwagger";
import { getProvider } from "../util/utils";
V2 (#655) * fix bug * fix bug * separate schema def * fix types * remove type & add scenario * fix testResourceLoader * fix jsonpatch * fix schemas * fix schema * fix types * fix schema * fix raw types * save * fix loader * simplify VariableScope in memory * fix * fix testScenarioGenerator * fix * fix runner * fix tslint * restore shareScope * fix bug * requiredVariables * variable type * fix resolve variables * bump js-yaml version * define patternProperties * restore plain structure * implement apiScenaroYamlLoader * expectedResponse & use Example operationId * fix variableEnv bug * support patch * fix bug * implement Patch per ARM RPC * log step name * templateGenerator * update export types * add armTemplate parameters convension * fix bug * fix request schema * cleanUpSteps * error handling when execution * revert * revert cliSuppressExceptions * Update validate-examples-regression-sample.yml for Azure Pipelines * Update azure-pipelines.yml for Azure Pipelines * Revert "Update azure-pipelines.yml for Azure Pipelines" This reverts commit 273b05ef82f9d38327af572a63721464df15b936. * Revert "Update validate-examples-regression-sample.yml for Azure Pipelines" This reverts commit d758018bdbfdab2598743237062ff0dce48e1dbd. * npm install with v6 * Refactor VariableEnv * fix bug * variableEnv * fix outputVariables * revert placeholder * add resolveVariables option and turn off in postmanCollectionRunner * fix pathVariable * use output method to make output variable global * update * fix prettier * rename to apiScenario * rename command * restore folder name * restore fixture * remove fixture from .gitignore * fix * fix test * resove armTemplate * systemData is readOnly * Fix bug * fix VariableEnv * fix resolveString * fix convention for cleanUp steps * apply patch * fix xmsExampleExtract bug * fix xMsExampleExtractor * rename folder and add Changelog Co-authored-by: ruowan <ruowan@microsoft.com>
2021-09-30 06:27:59 +03:00
import { ScenarioDefinition } from "./apiScenarioTypes";
import { SchemaSearcher } from "./schemaSearcher";
import { CoverageCalculator, OperationCoverageResult } from "./coverageCalculator";
export interface SwaggerAnalyzerOption
extends FileLoaderOption,
JsonLoaderOption,
SwaggerLoaderOption {
swaggerFilePaths?: string[];
noExternalDependencyResourceType?: boolean;
filerTopLevelResourceType?: boolean;
}
@injectable()
export class SwaggerAnalyzer {
private swaggerSpecs: SwaggerSpec[];
private initialized: boolean = false;
private transformContext: TransformContext;
private schemaValidator: SchemaValidator;
// eslint-disable-next-line @typescript-eslint/explicit-member-accessibility
constructor(
@inject(TYPES.opts) private opts: SwaggerAnalyzerOption,
public jsonLoader: JsonLoader,
private swaggerLoader: SwaggerLoader,
private fileLoader: FileLoader
) {
this.swaggerSpecs = [];
this.schemaValidator = new AjvSchemaValidator(this.jsonLoader);
this.transformContext = getTransformContext(this.jsonLoader, this.schemaValidator, [
xmsPathsTransformer,
resolveNestedDefinitionTransformer,
referenceFieldsTransformer,
discriminatorTransformer,
allOfTransformer,
noAdditionalPropertiesTransformer,
]);
}
V2 (#655) * fix bug * fix bug * separate schema def * fix types * remove type & add scenario * fix testResourceLoader * fix jsonpatch * fix schemas * fix schema * fix types * fix schema * fix raw types * save * fix loader * simplify VariableScope in memory * fix * fix testScenarioGenerator * fix * fix runner * fix tslint * restore shareScope * fix bug * requiredVariables * variable type * fix resolve variables * bump js-yaml version * define patternProperties * restore plain structure * implement apiScenaroYamlLoader * expectedResponse & use Example operationId * fix variableEnv bug * support patch * fix bug * implement Patch per ARM RPC * log step name * templateGenerator * update export types * add armTemplate parameters convension * fix bug * fix request schema * cleanUpSteps * error handling when execution * revert * revert cliSuppressExceptions * Update validate-examples-regression-sample.yml for Azure Pipelines * Update azure-pipelines.yml for Azure Pipelines * Revert "Update azure-pipelines.yml for Azure Pipelines" This reverts commit 273b05ef82f9d38327af572a63721464df15b936. * Revert "Update validate-examples-regression-sample.yml for Azure Pipelines" This reverts commit d758018bdbfdab2598743237062ff0dce48e1dbd. * npm install with v6 * Refactor VariableEnv * fix bug * variableEnv * fix outputVariables * revert placeholder * add resolveVariables option and turn off in postmanCollectionRunner * fix pathVariable * use output method to make output variable global * update * fix prettier * rename to apiScenario * rename command * restore folder name * restore fixture * remove fixture from .gitignore * fix * fix test * resove armTemplate * systemData is readOnly * Fix bug * fix VariableEnv * fix resolveString * fix convention for cleanUp steps * apply patch * fix xmsExampleExtract bug * fix xMsExampleExtractor * rename folder and add Changelog Co-authored-by: ruowan <ruowan@microsoft.com>
2021-09-30 06:27:59 +03:00
public calculateOperationCoverage(testDef: ScenarioDefinition): OperationCoverageResult {
return CoverageCalculator.calculateOperationCoverage(testDef, this.swaggerSpecs);
}
public calculateOperationCoverageBySpec(
testDef: ScenarioDefinition
): Map<string, OperationCoverageResult> {
return CoverageCalculator.calculateOperationCoverageBySpec(testDef, this.swaggerSpecs);
}
public getOperations(): { [key: string]: string[] } {
const operations: { [key: string]: string[] } = {};
for (const swaggerSpec of this.swaggerSpecs) {
const allOperationIds = new Set<string>();
traverseSwagger(swaggerSpec, {
onOperation: (operation: Operation, _path: Path, _method: LowerHttpMethods) => {
allOperationIds.add(operation.operationId!);
},
});
operations[swaggerSpec._filePath] = Array.from(allOperationIds);
}
return operations;
}
public async getOperationListPath(): Promise<Path[]> {
const ret: Path[] = [];
for (const swaggerSpec of this.swaggerSpecs) {
await traverseSwaggerAsync(swaggerSpec, {
onPath: async (path, pathTemplate) => {
const resourceProvider = getProvider(pathTemplate);
if (resourceProvider) {
if (path._pathTemplate === `/providers/${resourceProvider}/operations`) {
ret.push(path);
}
}
},
});
}
return ret;
}
public async initialize() {
if (this.initialized) {
throw new Error("Already initialized");
}
for (const swaggerFilePath of this.opts.swaggerFilePaths ?? []) {
const swaggerSpec = await this.swaggerLoader.load(swaggerFilePath);
this.swaggerSpecs.push(swaggerSpec);
applySpecTransformers(swaggerSpec, this.transformContext);
}
applyGlobalTransformers(this.transformContext);
this.initialized = true;
}
public async getAllSecretKey(): Promise<string[]> {
let ret: string[] = [];
const allXmsSecretsPath = '$..[?(@["x-ms-secret"])]~';
for (const swaggerPath of this.opts.swaggerFilePaths ?? []) {
const swagger = JSON.parse(await this.fileLoader.load(swaggerPath));
const allXmsSecretKeys = JSONPath({
path: allXmsSecretsPath,
json: swagger,
});
ret = ret.concat(allXmsSecretKeys);
}
return ret;
}
public findSchemaByJsonPointer(jsonPointer: string, schema: Schema, body?: any) {
return SchemaSearcher.findSchemaByJsonPointer(jsonPointer, schema, this.jsonLoader, body);
}
}