From a0291e324970fca0ee353bf9790c0f1fe3d71072 Mon Sep 17 00:00:00 2001 From: Zhenhua Hu Date: Sat, 21 Oct 2023 07:48:01 +0800 Subject: [PATCH] [JSON Report] Expose new properties in JSON Report (#1011) * add code * update ChangeLog.md --------- Co-authored-by: Scott Beddall (from Dev Box) --- ChangeLog.md | 4 ++++ lib/report/generateReport.ts | 22 +++++++++++----------- lib/validate.ts | 27 ++++++++++++++++++++++++++- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 44 insertions(+), 15 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 227f12e9..df1ba5a5 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,9 @@ # Change Log - oav +## 10/19/2023 3.3.0 + +- #1011 Ehancing JSON report by exposing new properties including `coveredSpecFiles`, `unCoveredOperationsList`, `errorLink` and `schemaPathWithPosition`. + ## 10/19/2023 3.2.14 - #1010 Fix an issue with details of `Failed Operations` not displayed in Windows-generated HTML report. diff --git a/lib/report/generateReport.ts b/lib/report/generateReport.ts index 3d71cf4a..cf5af99c 100644 --- a/lib/report/generateReport.ts +++ b/lib/report/generateReport.ts @@ -64,6 +64,16 @@ export interface resultForRendering index?: number; } +export async function loadErrorDefinitions(): Promise> { + const errorDefinitionDoc = + require("../../../documentation/error-definitions.json") as ErrorDefinitionDoc; + const errorsMap: Map = new Map(); + errorDefinitionDoc.ErrorDefinitions.forEach((def) => { + errorsMap.set(def.code, def); + }); + return errorsMap; +} + // used to pass data to the template rendering engine export class CoverageView { public package: string; @@ -137,7 +147,7 @@ export class CoverageView { public async prepareDataForRendering() { try { this.markdown = await this.readMarkdown(); - const errorDefinitions = await this.loadErrorDefinitions(); + const errorDefinitions = await loadErrorDefinitions(); let errorsForRendering: LiveValidationIssueForRendering[]; this.sortedValidationResults.forEach((element) => { const payloadFile = element.payloadFilePath?.substring( @@ -293,16 +303,6 @@ export class CoverageView { } } - private async loadErrorDefinitions(): Promise> { - const errorDefinitionDoc = - require("../../../documentation/error-definitions.json") as ErrorDefinitionDoc; - const errorsMap: Map = new Map(); - errorDefinitionDoc.ErrorDefinitions.forEach((def) => { - errorsMap.set(def.code, def); - }); - return errorsMap; - } - private sortOperationIds() { this.sortedValidationResults = this.validationResults.sort(function (op1, op2) { const opId1 = op1.operationInfo!.operationId; diff --git a/lib/validate.ts b/lib/validate.ts index c126efda..e89af612 100644 --- a/lib/validate.ts +++ b/lib/validate.ts @@ -24,7 +24,7 @@ import { TrafficValidationOptions, TrafficValidator, } from "./swaggerValidator/trafficValidator"; -import { ReportGenerator } from "./report/generateReport"; +import { ReportGenerator, loadErrorDefinitions } from "./report/generateReport"; export interface Options extends XMsExampleExtractor.Options { consoleLogLevel?: unknown; @@ -214,13 +214,27 @@ export async function validateTraffic( }); } if (options.jsonReportPath) { + const errorDefinitions = await loadErrorDefinitions(); const report = { + coveredSpecFiles: validator.operationCoverageResult.map((item) => + options.overrideLinkInReport + ? `${options.specLinkPrefix}/${item.spec?.substring( + item.spec?.indexOf("specification") + )}` + : `${item.spec}` + ), allOperations: validator.operationCoverageResult .map((item) => item.totalOperations) .reduce((a, b) => a + b, 0), coveredOperations: validator.operationCoverageResult .map((item) => item.coveredOperations) .reduce((a, b) => a + b, 0), + unCoveredOperationsList: validator.operationCoverageResult.map((item) => { + return { + spec: item.spec, + operationIds: item.unCoveredOperationsList.map((opeartion) => opeartion.operationId), + }; + }), failedOperations: validator.operationCoverageResult .map((item) => item.validationFailOperations) .reduce((a, b) => a + b, 0), @@ -229,11 +243,22 @@ export async function validateTraffic( trafficValidationResult, (item) => item.errors?.map((it) => { + const errorDef = errorDefinitions.get(it.code); + const specFilePath = item.specFilePath || ""; + const overrideLinkInReport = options.overrideLinkInReport || false; + const specLinkPrefix = options.specLinkPrefix || ""; return { + spec: specFilePath, errorCode: it.code, + errorLink: errorDef?.link, errorMessage: it.message, issueSource: it.issueSource, operationId: item.operationInfo?.operationId, + schemaPathWithPosition: overrideLinkInReport + ? `${specLinkPrefix}/${specFilePath.substring( + specFilePath.indexOf("specification") + )}#L${it.source.position.line}` + : `${specFilePath}#L${it.source.position.line}`, }; }) ?? [] ) diff --git a/package-lock.json b/package-lock.json index 42fc067c..81278301 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oav", - "version": "3.2.13", + "version": "3.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "oav", - "version": "3.2.13", + "version": "3.3.0", "license": "MIT", "dependencies": { "@apidevtools/swagger-parser": "10.0.3", diff --git a/package.json b/package.json index 449bf053..30ceea1f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oav", - "version": "3.2.14", + "version": "3.3.0", "author": { "name": "Microsoft Corporation", "email": "azsdkteam@microsoft.com",