private async generateHtmlReport()

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();
  }