in lib/apiScenario/postmanCollectionGenerator.ts [294:423]
private async generateHtmlReport() {
const trafficValidationResult = new Array<TrafficValidationIssue>();
const reportExportPath = path.resolve(
this.opt.outputFolder,
`${defaultNewmanDir(this.scenarioDef.name, this.opt.runId!)}`
);
let providerNamespace;
for (const dir of fs.readdirSync(reportExportPath, { withFileTypes: true })) {
if (dir.isDirectory()) {
const report = JSON.parse(
await this.fileLoader.load(path.join(reportExportPath, dir.name, "report.json"))
) as ApiScenarioTestResult;
providerNamespace = report.providerNamespace;
for (const r of report.stepResult) {
const trafficValidationIssue: TrafficValidationIssue = {
errors: [
...(r.liveValidationResult?.requestValidationResult.errors ?? []),
...(r.liveValidationResult?.responseValidationResult.errors ?? []),
...(r.roundtripValidationResult?.errors ?? []),
],
specFilePath: r.specFilePath,
operationInfo: r.liveValidationResult?.requestValidationResult.operationInfo ?? {
operationId: r.operationId,
apiVersion: report.apiVersion ?? "unknown",
},
};
// mock
trafficValidationIssue.operationInfo!.position = {
line: 0,
column: 0,
};
if (this.opt.savePayload) {
trafficValidationIssue.payloadFilePath = r.payloadPath;
}
for (const runtimeError of r.runtimeError ?? []) {
trafficValidationIssue.errors?.push(this.convertRuntimeException(runtimeError));
}
if (r.liveValidationResult?.requestValidationResult.runtimeException) {
trafficValidationIssue.errors?.push(
this.convertRuntimeException(
r.liveValidationResult!.requestValidationResult.runtimeException
)
);
}
if (r.liveValidationResult?.responseValidationResult.runtimeException) {
trafficValidationIssue.errors?.push(
this.convertRuntimeException(
r.liveValidationResult!.responseValidationResult.runtimeException
)
);
}
trafficValidationResult.push(trafficValidationIssue);
}
}
}
const operationIdCoverageResult = this.swaggerAnalyzer.calculateOperationCoverageBySpec(
this.scenarioDef
);
const operationCoverageResult: OperationCoverageInfo[] = [];
operationIdCoverageResult.forEach((result, key) => {
let specPath = this.fileLoader.resolvePath(key);
if (process.env.REPORT_SPEC_PATH_PREFIX) {
specPath = path.join(
process.env.REPORT_SPEC_PATH_PREFIX,
specPath.substring(specPath.indexOf("specification"))
);
}
operationCoverageResult.push({
totalOperations: result.totalOperationNumber,
spec: specPath,
coverageRate: result.coverage,
apiVersion: getApiVersionFromFilePath(specPath),
unCoveredOperations: result.uncoveredOperationIds.length,
coveredOperations: result.totalOperationNumber - result.uncoveredOperationIds.length,
coveredOperationsList: result.coveredOperationIds.map((id) => {
return { operationId: id };
}),
validationFailOperations: new Set(
trafficValidationResult
.filter((it) => key.indexOf(it.specFilePath!) !== -1 && it.errors!.length > 0)
.map((t) => t.operationInfo?.operationId)
).size,
unCoveredOperationsList: result.uncoveredOperationIds.map((id) => {
return { operationId: id };
}),
unCoveredOperationsListGen: Object.values(
result.uncoveredOperationIds
.map((id) => {
return { operationId: id, key: id.split("_")[0] };
})
.reduce((res: { [key: string]: unCoveredOperationsFormat }, item) => {
/* eslint-disable no-unused-expressions */
res[item.key]
? res[item.key].operationIdList.push(item)
: (res[item.key] = {
operationIdList: [item],
});
/* eslint-enable no-unused-expressions */
return res;
}, {})
),
});
});
const options: TrafficValidationOptions = {
reportPath: path.resolve(reportExportPath, "report.html"),
overrideLinkInReport: false,
sdkPackage: providerNamespace,
markdownPath: this.opt.markdown ? path.resolve(reportExportPath, "report.md") : undefined,
};
const generator = new HtmlReportGenerator(
trafficValidationResult,
operationCoverageResult,
0,
options
);
await generator.generateHtmlReport();
}