@pactflow/swagger-mock-validator
Advanced tools
Comparing version 11.3.1 to 11.4.0
@@ -0,1 +1,13 @@ | ||
<a name="11.4.0"></a> | ||
# [11.4.0](https://github.com/pactflow/swagger-mock-validator/compare/11.3.1...11.4.0) (2023-05-05) | ||
### Features | ||
* hide debug behind feature toggle ([c692494](https://github.com/pactflow/swagger-mock-validator/commit/c692494)) | ||
* log where validation passes when it should've failed ([5691531](https://github.com/pactflow/swagger-mock-validator/commit/5691531)) | ||
* Respect request and response content-types ([5c86507](https://github.com/pactflow/swagger-mock-validator/commit/5c86507)) | ||
<a name="11.3.1"></a> | ||
@@ -2,0 +14,0 @@ ## [11.3.1](https://github.com/pactflow/swagger-mock-validator/compare/11.3.0...11.3.1) (2023-03-20) |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getContentSchema = void 0; | ||
exports.getContentSchemasByContentType = exports.getDefaultContentSchema = void 0; | ||
const get_schema_with_spec_definitions_1 = require("./get-schema-with-spec-definitions"); | ||
const defaultMediaType = 'application/json'; | ||
const findApplicationJsonMediaType = (content) => Object.keys(content).find((mediaType) => mediaType.indexOf('application/json') === 0) | ||
|| defaultMediaType; | ||
const findDefaultMediaType = (content) => { | ||
const mediaTypes = Object.keys(content); | ||
return mediaTypes.find((mediaType) => mediaType.startsWith('application/json')) || mediaTypes.find((mediaType) => mediaType.match(/application\/.+json/)) || mediaTypes[0] || defaultMediaType; | ||
}; | ||
const getApplicationJsonContentSchema = (content, spec) => { | ||
const jsonMediaType = findApplicationJsonMediaType(content); | ||
const jsonContent = content[jsonMediaType]; | ||
const jsonSchema = jsonContent ? jsonContent.schema : undefined; | ||
return jsonSchema | ||
? { schema: (0, get_schema_with_spec_definitions_1.getSchemaWithSpecDefinitions)(jsonSchema, spec), mediaType: jsonMediaType } | ||
: { mediaType: jsonMediaType }; | ||
const mediaType = findDefaultMediaType(content); | ||
const schema = content[mediaType] ? content[mediaType].schema : undefined; | ||
return schema | ||
? { schema: (0, get_schema_with_spec_definitions_1.getSchemaWithSpecDefinitions)(schema, spec), mediaType } | ||
: { mediaType }; | ||
}; | ||
const getContentSchema = (content, spec) => content | ||
const getDefaultContentSchema = (content, spec) => content | ||
? getApplicationJsonContentSchema(content, spec) | ||
: { mediaType: defaultMediaType }; | ||
exports.getContentSchema = getContentSchema; | ||
exports.getDefaultContentSchema = getDefaultContentSchema; | ||
// tslint:disable:cyclomatic-complexity | ||
const getContentSchemasByContentType = (content, spec) => { | ||
const result = {}; | ||
if (!content) { | ||
return result; | ||
} | ||
const mediaTypes = Object.keys(content); | ||
for (const mediaType of mediaTypes) { | ||
if (content[mediaType] && content[mediaType].schema) { | ||
result[mediaType] = (0, get_schema_with_spec_definitions_1.getSchemaWithSpecDefinitions)(content[mediaType].schema, spec); | ||
} | ||
} | ||
return result; | ||
}; | ||
exports.getContentSchemasByContentType = getContentSchemasByContentType; | ||
// tslint:enable:cyclomatic-complexity |
@@ -9,8 +9,9 @@ "use strict"; | ||
const parseRequestBody = (parentOperation, requestBody, spec) => { | ||
const { schema, mediaType } = (0, get_content_schema_1.getContentSchema)(requestBody.content, spec); | ||
const { schema, mediaType } = (0, get_content_schema_1.getDefaultContentSchema)(requestBody.content, spec); | ||
const schemasByContentType = (0, get_content_schema_1.getContentSchemasByContentType)(requestBody.content, spec); | ||
return schema | ||
? { | ||
getFromSchema: (pathToGet) => { | ||
getFromSchema: (pathToGet, actualMediaType) => { | ||
return { | ||
location: `${parentOperation.location}.requestBody.content.${mediaType}.schema.${pathToGet}`, | ||
location: `${parentOperation.location}.requestBody.content.${actualMediaType || mediaType}.schema.${pathToGet}`, | ||
parentOperation, | ||
@@ -22,3 +23,4 @@ value: _.get(schema, pathToGet) | ||
required: requestBody.required || false, | ||
schema | ||
schema, | ||
schemasByContentType | ||
} | ||
@@ -25,0 +27,0 @@ : undefined; |
@@ -11,7 +11,8 @@ "use strict"; | ||
const dereferencedResponse = (0, dereference_component_1.dereferenceComponent)(response, spec); | ||
const { schema, mediaType } = (0, get_content_schema_1.getContentSchema)(dereferencedResponse.content, spec); | ||
const { schema, mediaType } = (0, get_content_schema_1.getDefaultContentSchema)(dereferencedResponse.content, spec); | ||
const schemasByContentType = (0, get_content_schema_1.getContentSchemasByContentType)(dereferencedResponse.content, spec); | ||
return { | ||
getFromSchema: (pathToGet) => { | ||
getFromSchema: (pathToGet, actualMediaType) => { | ||
return { | ||
location: `${responseLocation}.content.${mediaType}.schema.${pathToGet}`, | ||
location: `${responseLocation}.content.${actualMediaType || mediaType}.schema.${pathToGet}`, | ||
parentOperation, | ||
@@ -30,2 +31,3 @@ value: _.get(schema, pathToGet) | ||
schema, | ||
schemasByContentType, | ||
value: response | ||
@@ -32,0 +34,0 @@ }; |
@@ -8,4 +8,14 @@ "use strict"; | ||
const validate_json_1 = require("./validate-json"); | ||
const validateRequestBodyAgainstSchema = (parsedMockRequestBody, parsedSpecRequestBody) => { | ||
const validationErrors = (0, validate_json_1.validateJson)(parsedSpecRequestBody.schema, parsedMockRequestBody.value); | ||
const validateRequestBodyAgainstSchema = (parsedMockInteraction, parsedSpecOperation) => { | ||
var _a; | ||
const parsedMockRequestBody = parsedMockInteraction.requestBody; | ||
const parsedSpecRequestBody = parsedSpecOperation.requestBodyParameter; | ||
// start with a default schema | ||
let schema = parsedSpecRequestBody.schema; | ||
// switch schema based on content-type | ||
const contentType = (_a = parsedMockInteraction.requestHeaders['content-type']) === null || _a === void 0 ? void 0 : _a.value; | ||
if (contentType && parsedSpecRequestBody.schemasByContentType && parsedSpecRequestBody.schemasByContentType[contentType]) { | ||
schema = parsedSpecRequestBody.schemasByContentType[contentType]; | ||
} | ||
const validationErrors = (0, validate_json_1.validateJson)(schema, parsedMockRequestBody.value); | ||
return _.map(validationErrors, (error) => result_1.result.build({ | ||
@@ -16,3 +26,3 @@ code: 'request.body.incompatible', | ||
source: 'spec-mock-validation', | ||
specSegment: parsedSpecRequestBody.getFromSchema(error.schemaPath.replace(/\//g, '.').substring(2)) | ||
specSegment: parsedSpecRequestBody.getFromSchema(error.schemaPath.replace(/\//g, '.').substring(2), contentType) | ||
})); | ||
@@ -30,6 +40,38 @@ }; | ||
if (shouldSkipValidation(parsedMockInteraction, parsedSpecOperation)) { | ||
// this is temporary code to identify passing validations that should've failed | ||
// tslint:disable:cyclomatic-complexity | ||
if (process.env.DEBUG_CONTENT_TYPE_ISSUE && isNotSupportedMediaType(parsedSpecOperation)) { | ||
const debugValidation = (validation) => { | ||
var _a; | ||
console.error(JSON.stringify({ | ||
message: 'Passing validation that should\'ve failed due to unsupported media type', | ||
pact_request: { | ||
'content-type': (_a = parsedMockInteraction.requestHeaders['content-type']) === null || _a === void 0 ? void 0 : _a.value | ||
}, | ||
oas_consumes: { | ||
'content-type': parsedSpecOperation.consumes.value | ||
}, | ||
validation | ||
})); | ||
}; | ||
if (parsedSpecOperation.requestBodyParameter) { | ||
debugValidation(validateRequestBodyAgainstSchema(parsedMockInteraction, parsedSpecOperation)); | ||
} | ||
else { | ||
debugValidation([ | ||
result_1.result.build({ | ||
code: 'request.body.unknown', | ||
message: 'No schema found for request body', | ||
mockSegment: parsedMockInteraction.requestBody, | ||
source: 'spec-mock-validation', | ||
specSegment: parsedSpecOperation | ||
}) | ||
]); | ||
} | ||
} | ||
// tslint:enable:cyclomatic-complexity | ||
return []; | ||
} | ||
if (parsedSpecOperation.requestBodyParameter) { | ||
return validateRequestBodyAgainstSchema(parsedMockInteraction.requestBody, parsedSpecOperation.requestBodyParameter); | ||
return validateRequestBodyAgainstSchema(parsedMockInteraction, parsedSpecOperation); | ||
} | ||
@@ -36,0 +78,0 @@ return [ |
@@ -33,2 +33,3 @@ "use strict"; | ||
const validateParsedMockResponseBody = (parsedMockInteraction, parsedSpecResponse, opts) => { | ||
var _a; | ||
if (shouldSkipValidation(parsedMockInteraction, parsedSpecResponse)) { | ||
@@ -48,6 +49,12 @@ return []; | ||
} | ||
// start with a default schema | ||
let responseBodyToValidate = parsedSpecResponse.schema; | ||
// switch schema based on content-type | ||
const contentType = (_a = parsedMockInteraction.responseHeaders['content-type']) === null || _a === void 0 ? void 0 : _a.value; | ||
if (contentType && parsedSpecResponse.schemasByContentType && parsedSpecResponse.schemasByContentType[contentType]) { | ||
responseBodyToValidate = parsedSpecResponse.schemasByContentType[contentType]; | ||
} | ||
// tslint:disable:cyclomatic-complexity | ||
if (!opts.additionalPropertiesInResponse) { | ||
responseBodyToValidate = setAdditionalPropertiesToFalseInSchema(parsedSpecResponse.schema); | ||
responseBodyToValidate = setAdditionalPropertiesToFalseInSchema(responseBodyToValidate); | ||
} | ||
@@ -67,3 +74,3 @@ if (!opts.requiredPropertiesInResponse) { | ||
source: 'spec-mock-validation', | ||
specSegment: parsedSpecResponse.getFromSchema(error.schemaPath.replace(/\//g, '.').substring(2)) | ||
specSegment: parsedSpecResponse.getFromSchema(error.schemaPath.replace(/\//g, '.').substring(2), contentType) | ||
}); | ||
@@ -70,0 +77,0 @@ }); |
{ | ||
"name": "@pactflow/swagger-mock-validator", | ||
"version": "11.3.1", | ||
"version": "11.4.0", | ||
"description": "A CLI tool to validate mocks against swagger/OpenApi specs.", | ||
@@ -5,0 +5,0 @@ "bin": { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
216370
2976
2