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