private validateResponse()

in lib/swaggerValidator/modelValidator.ts [146:309]


  private validateResponse(operation: Operation, exampleContent: any, exampleFileUrl: string) {
    const exampleResponsesObj = exampleContent.responses;
    if (
      exampleResponsesObj === null ||
      exampleResponsesObj === undefined ||
      typeof exampleResponsesObj !== "object"
    ) {
      throw new Error(
        `For operation:${operation.operationId}, responses in example file ${exampleFileUrl} cannot be null or undefined and must be of type 'object'.`
      );
    }

    const definedResponsesInSwagger: string[] = [];
    for (const statusCode of openapiToolsCommon.keys(operation.responses)) {
      definedResponsesInSwagger.push(statusCode);
    }
    // loop for each response code
    for (const exampleResponseStatusCode of openapiToolsCommon.keys(exampleResponsesObj)) {
      const responseDefinition = operation.responses;

      const responseSchema = responseDefinition[exampleResponseStatusCode];
      if (!responseSchema) {
        const meta = getOavErrorMeta(ErrorCodeConstants.RESPONSE_STATUS_CODE_NOT_IN_SPEC as any, {
          exampleResponseStatusCode,
          operationId: operation.operationId,
        });
        this.addErrorsFromErrorCode(
          operation.operationId!,
          exampleFileUrl,
          meta,
          responseDefinition,
          undefined,
          exampleResponsesObj,
          `$response.${exampleResponseStatusCode}`,
          ValidationResultSource.RESPONSE
        );
        continue;
      }

      // remove response entry after validation
      const responseIndex = definedResponsesInSwagger.indexOf(exampleResponseStatusCode);
      if (responseIndex > -1) {
        definedResponsesInSwagger.splice(responseIndex, 1);
      }

      const exampleResponseHeaders = exampleResponsesObj[exampleResponseStatusCode].headers || {};
      const exampleResponseBody = exampleResponsesObj[exampleResponseStatusCode].body;

      // Fail when example provides the response body but the swagger spec doesn't define the schema for the response.
      if (exampleResponseBody !== undefined) {
        if (!responseSchema.schema) {
          // having response body but doesn't have schema defined in response swagger definition
          const meta = getOavErrorMeta(ErrorCodeConstants.RESPONSE_SCHEMA_NOT_IN_SPEC as any, {
            exampleResponseStatusCode,
            operationId: operation.operationId,
          });
          this.addErrorsFromErrorCode(
            operation.operationId!,
            exampleFileUrl,
            meta,
            responseDefinition,
            undefined,
            exampleResponsesObj,
            `$response.${exampleResponseStatusCode}/body`,
            ValidationResultSource.RESPONSE
          );
          continue;
        } else if (responseSchema.schema.type !== typeof exampleResponseBody) {
          const validBody = this.validateBodyType(
            operation.operationId!,
            responseSchema,
            exampleResponseBody,
            exampleFileUrl,
            responseDefinition,
            exampleResponsesObj,
            exampleResponseStatusCode
          );
          if (!validBody) {
            continue;
          }
        }
      } else if (exampleResponseBody === undefined && responseSchema.schema) {
        // Fail when example doesn't provide the response body but the swagger spec define the schema for the response.
        const meta = getOavErrorMeta(ErrorCodeConstants.RESPONSE_BODY_NOT_IN_EXAMPLE as any, {
          exampleResponseStatusCode,
          operationId: operation.operationId,
        });
        this.addErrorsFromErrorCode(
          operation.operationId!,
          exampleFileUrl,
          meta,
          responseDefinition,
          undefined,
          exampleResponsesObj,
          `$response.${exampleResponseStatusCode}`,
          ValidationResultSource.RESPONSE
        );
        continue;
      }
      // validate headers
      const headers = transformLiveHeader(exampleResponseHeaders, responseSchema);
      this.validateLroOperation(
        exampleFileUrl,
        operation,
        exampleResponseStatusCode,
        headers,
        exampleResponseHeaders
      );
      if (responseSchema.schema !== undefined) {
        if (headers["content-type"] !== undefined) {
          this.validateContentType(
            operation.operationId!,
            exampleFileUrl,
            operation.produces!,
            headers,
            false,
            exampleResponseStatusCode,
            operation,
            exampleResponseHeaders
          );
        }
        const validate = responseSchema._validate!;
        const ctx = {
          isResponse: true,
          statusCode: exampleResponseStatusCode,
          httpMethod: operation._method,
        };
        const ajvValidatorErrors = validate(ctx, {
          headers,
          body: exampleResponseBody,
        });
        this.schemaIssuesToModelValidationIssues(
          operation.operationId!,
          false,
          ajvValidatorErrors,
          exampleFileUrl,
          exampleContent,
          undefined,
          exampleResponseStatusCode,
          operation._method
        );
      }
    }

    // report missing response in example
    for (const statusCodeInSwagger of definedResponsesInSwagger) {
      if (statusCodeInSwagger !== "default") {
        const meta = getOavErrorMeta(
          ErrorCodeConstants.RESPONSE_STATUS_CODE_NOT_IN_EXAMPLE as any,
          { statusCodeInSwagger, operationId: operation.operationId }
        );
        this.addErrorsFromErrorCode(
          operation.operationId!,
          exampleFileUrl,
          meta,
          operation.responses[statusCodeInSwagger],
          undefined,
          exampleResponsesObj,
          `response`,
          ValidationResultSource.RESPONSE
        );
      }
    }
  }