New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@pactflow/swagger-mock-validator

Package Overview
Dependencies
Maintainers
6
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@pactflow/swagger-mock-validator - npm Package Compare versions

Comparing version 11.4.0 to 11.5.0

10

CHANGELOG.md

@@ -0,1 +1,11 @@

<a name="11.5.0"></a>
# [11.5.0](https://github.com/pactflow/swagger-mock-validator/compare/11.4.0...11.5.0) (2023-05-12)
### Features
* handle more varieties of json ([e59bcdf](https://github.com/pactflow/swagger-mock-validator/commit/e59bcdf))
<a name="11.4.0"></a>

@@ -2,0 +12,0 @@ # [11.4.0](https://github.com/pactflow/swagger-mock-validator/compare/11.3.1...11.4.0) (2023-05-05)

40

dist/swagger-mock-validator/spec-parser/openapi3/openapi3-parser/get-content-schema.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getContentSchemasByContentType = exports.getDefaultContentSchema = void 0;
exports.schemaByContentType = void 0;
const get_schema_with_spec_definitions_1 = require("./get-schema-with-spec-definitions");
const content_negotiation_1 = require("../../../validate-spec-and-mock/content-negotiation");
const defaultMediaType = 'application/json';

@@ -10,28 +11,25 @@ const findDefaultMediaType = (content) => {

};
const getApplicationJsonContentSchema = (content, spec) => {
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 getDefaultContentSchema = (content, spec) => content
? getApplicationJsonContentSchema(content, spec)
: { mediaType: defaultMediaType };
exports.getDefaultContentSchema = getDefaultContentSchema;
// tslint:disable:cyclomatic-complexity
const getContentSchemasByContentType = (content, spec) => {
const result = {};
const schemaByContentType = (content, spec) => (mediaType) => {
var _a;
if (!content) {
return result;
return undefined;
}
const effectiveMediaType = mediaType || findDefaultMediaType(content);
const normalizedMediaType = (0, content_negotiation_1.normalizeMediaType)(effectiveMediaType);
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);
}
const contentMediaType = mediaTypes.find(type => (0, content_negotiation_1.areMediaTypesCompatible)((0, content_negotiation_1.normalizeMediaType)(type), normalizedMediaType));
if (!contentMediaType) {
return undefined;
}
return result;
const schema = (_a = content[contentMediaType]) === null || _a === void 0 ? void 0 : _a.schema;
if (!schema) {
return undefined;
}
return {
schema: (0, get_schema_with_spec_definitions_1.getSchemaWithSpecDefinitions)(schema, spec),
mediaType: contentMediaType
};
};
exports.getContentSchemasByContentType = getContentSchemasByContentType;
exports.schemaByContentType = schemaByContentType;
// tslint:enable:cyclomatic-complexity

@@ -9,19 +9,12 @@ "use strict";

const parseRequestBody = (parentOperation, requestBody, 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, actualMediaType) => {
return {
location: `${parentOperation.location}.requestBody.content.${actualMediaType || mediaType}.schema.${pathToGet}`,
parentOperation,
value: _.get(schema, pathToGet)
};
},
name: '',
required: requestBody.required || false,
schema,
schemasByContentType
}
: undefined;
return {
getFromSchema: (path, schema, mediaType) => ({
location: `${parentOperation.location}.requestBody.content.${mediaType}.schema.${path}`,
parentOperation,
value: _.get(schema, path)
}),
name: '',
required: requestBody.required || false,
schemaByContentType: (0, get_content_schema_1.schemaByContentType)(requestBody.content, spec)
};
};

@@ -38,6 +31,5 @@ const createConsumesWithMimeTypes = (parentOperation, mimeTypes) => ({

const dereferencedRequestBody = (0, dereference_component_1.dereferenceComponent)(requestBody, spec);
const requestBodyParameter = parseRequestBody(parentOperation, dereferencedRequestBody, spec);
return {
consumes: createConsumesWithMimeTypes(parentOperation, (0, get_content_mime_types_1.getContentMimeTypes)(dereferencedRequestBody.content)),
requestBodyParameter
requestBodyParameter: parseRequestBody(parentOperation, dereferencedRequestBody, spec)
};

@@ -44,0 +36,0 @@ };

@@ -11,12 +11,8 @@ "use strict";

const dereferencedResponse = (0, dereference_component_1.dereferenceComponent)(response, 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, actualMediaType) => {
return {
location: `${responseLocation}.content.${actualMediaType || mediaType}.schema.${pathToGet}`,
parentOperation,
value: _.get(schema, pathToGet)
};
},
getFromSchema: (path, schema, mediaType) => ({
location: `${responseLocation}.content.${mediaType}.schema.${path}`,
parentOperation,
value: _.get(schema, path)
}),
headers: (0, parse_response_headers_1.parseResponseHeaders)(dereferencedResponse.headers, parentOperation, `${responseLocation}.headers`, spec),

@@ -30,4 +26,3 @@ location: `${responseLocation}`,

},
schema,
schemasByContentType,
schemaByContentType: (0, get_content_schema_1.schemaByContentType)(dereferencedResponse.content, spec),
value: response

@@ -34,0 +29,0 @@ };

@@ -13,8 +13,5 @@ "use strict";

const addDefinitionsToSchema = (schema, spec) => {
if (schema) {
const modifiedSchema = _.cloneDeep(schema);
modifiedSchema.definitions = spec.definitions;
return modifiedSchema;
}
return undefined;
const modifiedSchema = _.cloneDeep(schema);
modifiedSchema.definitions = spec.definitions;
return modifiedSchema;
};

@@ -91,8 +88,7 @@ const mergePathAndOperationParameters = (pathParameters, operationParameters) => {

const responseLocation = `${parsedResponses.location}.${responseStatus}`;
const originalSchema = response.schema;
parsedResponses[responseStatus] = {
getFromSchema: (pathToGet) => ({
location: `${responseLocation}.schema.${pathToGet}`,
getFromSchema: (path, schema) => ({
location: `${responseLocation}.schema.${path}`,
parentOperation,
value: _.get(originalSchema, pathToGet)
value: _.get(schema, path)
}),

@@ -103,3 +99,11 @@ headers: parseResponseHeaders(response.headers, responseLocation, parentOperation),

produces,
schema: addDefinitionsToSchema(response.schema, specJson),
schemaByContentType: (mediaType) => {
if (!response.schema) {
return undefined;
}
return {
schema: addDefinitionsToSchema(response.schema, specJson),
mediaType
};
},
value: response

@@ -120,6 +124,6 @@ };

return {
getFromSchema: (pathToGet) => ({
location: `${parameter.location}.schema.${pathToGet}`,
getFromSchema: (path, schema, _mediaType) => ({
location: `${parameter.location}.schema.${path}`,
parentOperation: parameter.parentOperation,
value: _.get(parameter.value.schema, pathToGet)
value: _.get(schema, path)
}),

@@ -130,3 +134,11 @@ location: parameter.location,

required: parameter.value.required,
schema: modifiedSchema,
schemaByContentType: (mediaType) => {
if (!parameter.value.schema) {
return undefined;
}
return {
schema: modifiedSchema,
mediaType
};
},
value: parameter.value

@@ -133,0 +145,0 @@ };

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isMediaTypeSupported = void 0;
exports.isTypesOfJson = exports.isMediaTypeSupported = exports.normalizeMediaType = exports.areMediaTypesCompatible = void 0;
const PARAMETER_SEPARATOR = ';';

@@ -23,2 +23,3 @@ const WILDCARD = '*';

};
exports.areMediaTypesCompatible = areMediaTypesCompatible;
const normalizeMediaType = (mediaType) => {

@@ -30,9 +31,17 @@ return mediaType

};
exports.normalizeMediaType = normalizeMediaType;
const isMediaTypeSupported = (actualMediaType, supportedMediaTypes) => {
const normalizedActualMediaType = normalizeMediaType(actualMediaType);
const normalizedActualMediaType = (0, exports.normalizeMediaType)(actualMediaType);
return supportedMediaTypes.some((supportedMediaType) => {
const normalizedSupportedMediaType = normalizeMediaType(supportedMediaType);
return areMediaTypesCompatible(normalizedActualMediaType, normalizedSupportedMediaType);
const normalizedSupportedMediaType = (0, exports.normalizeMediaType)(supportedMediaType);
return (0, exports.areMediaTypesCompatible)(normalizedActualMediaType, normalizedSupportedMediaType);
});
};
exports.isMediaTypeSupported = isMediaTypeSupported;
const isTypesOfJson = (supportedMediaTypes) => {
return supportedMediaTypes.some((supportedMediaType) => {
const mediaType = (0, exports.normalizeMediaType)(supportedMediaType);
return mediaType.startsWith('application/') && mediaType.endsWith('json') || mediaType === '*/*';
});
};
exports.isTypesOfJson = isTypesOfJson;

@@ -12,10 +12,17 @@ "use strict";

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 expectedMediaType = (_a = parsedMockInteraction.requestHeaders['content-type']) === null || _a === void 0 ? void 0 : _a.value;
const schemaForMediaType = parsedSpecRequestBody.schemaByContentType(expectedMediaType);
if (!schemaForMediaType) {
return [
result_1.result.build({
code: 'request.body.unknown',
message: 'No matching schema found for request body',
mockSegment: parsedMockInteraction.requestBody,
source: 'spec-mock-validation',
specSegment: parsedSpecOperation
})
];
}
const validationErrors = (0, validate_json_1.validateJson)(schema, parsedMockRequestBody.value);
const { schema, mediaType } = schemaForMediaType;
const validationErrors = (0, validate_json_1.validateJson)(schemaForMediaType.schema, parsedMockRequestBody.value);
return _.map(validationErrors, (error) => result_1.result.build({

@@ -26,3 +33,3 @@ code: 'request.body.incompatible',

source: 'spec-mock-validation',
specSegment: parsedSpecRequestBody.getFromSchema(error.schemaPath.replace(/\//g, '.').substring(2), contentType)
specSegment: parsedSpecRequestBody.getFromSchema(error.schemaPath.replace(/\//g, '.').substring(2), schema, mediaType)
}));

@@ -34,3 +41,3 @@ };

const isNotSupportedMediaType = (parsedSpecOperation) => parsedSpecOperation.consumes.value.length > 0 &&
!(0, content_negotiation_1.isMediaTypeSupported)('application/json', parsedSpecOperation.consumes.value);
!(0, content_negotiation_1.isTypesOfJson)(parsedSpecOperation.consumes.value);
const shouldSkipValidation = (parsedMockInteraction, parsedSpecOperation) => isNotSupportedMediaType(parsedSpecOperation) ||

@@ -41,34 +48,2 @@ specAndMockHaveNoBody(parsedMockInteraction, parsedSpecOperation) ||

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 [];

@@ -75,0 +50,0 @@ }

@@ -29,5 +29,6 @@ "use strict";

const isNotSupportedMediaType = (parsedSpecResponse) => parsedSpecResponse.produces.value.length > 0 &&
!(0, content_negotiation_1.isMediaTypeSupported)('application/json', parsedSpecResponse.produces.value);
!(0, content_negotiation_1.isTypesOfJson)(parsedSpecResponse.produces.value);
const shouldSkipValidation = (parsedMockInteraction, parsedSpecResponse) => isMockInteractionWithoutResponseBody(parsedMockInteraction) ||
isNotSupportedMediaType(parsedSpecResponse);
// tslint:disable:cyclomatic-complexity
const validateParsedMockResponseBody = (parsedMockInteraction, parsedSpecResponse, opts) => {

@@ -38,3 +39,5 @@ var _a;

}
if (!parsedSpecResponse.schema) {
const expectedMediaType = (_a = parsedMockInteraction.requestHeaders.accept) === null || _a === void 0 ? void 0 : _a.value;
const schemaForMediaType = parsedSpecResponse.schemaByContentType(expectedMediaType);
if (!schemaForMediaType) {
return [

@@ -50,17 +53,11 @@ result_1.result.build({

}
// 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
let schema = schemaForMediaType.schema;
const mediaType = schemaForMediaType.mediaType;
if (!opts.additionalPropertiesInResponse) {
responseBodyToValidate = setAdditionalPropertiesToFalseInSchema(responseBodyToValidate);
schema = setAdditionalPropertiesToFalseInSchema(schema);
}
if (!opts.requiredPropertiesInResponse) {
responseBodyToValidate = removeRequiredPropertiesFromSchema(responseBodyToValidate);
schema = removeRequiredPropertiesFromSchema(schema);
}
const validationErrors = (0, validate_json_1.validateJson)(responseBodyToValidate, parsedMockInteraction.responseBody.value);
const validationErrors = (0, validate_json_1.validateJson)(schema, parsedMockInteraction.responseBody.value);
return _.map(validationErrors, (error) => {

@@ -75,3 +72,3 @@ const message = error.keyword === 'additionalProperties'

source: 'spec-mock-validation',
specSegment: parsedSpecResponse.getFromSchema(error.schemaPath.replace(/\//g, '.').substring(2), contentType)
specSegment: parsedSpecResponse.getFromSchema(error.schemaPath.replace(/\//g, '.').substring(2), schema, mediaType)
});

@@ -81,1 +78,2 @@ });

exports.validateParsedMockResponseBody = validateParsedMockResponseBody;
// tslint:enable:cyclomatic-complexity
{
"name": "@pactflow/swagger-mock-validator",
"version": "11.4.0",
"version": "11.5.0",
"description": "A CLI tool to validate mocks against swagger/OpenApi specs.",

@@ -5,0 +5,0 @@ "bin": {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc