mirror of
https://github.com/postmanlabs/openapi-to-postman.git
synced 2022-11-29 22:05:00 +03:00
Merge branch 'develop' of github.com:postmanlabs/openapi-to-postman into feature/fix-invalid-path-match
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
# OpenAPI-Postman Changelog
|
||||
|
||||
#### v2.1.0 (January 27, 2021)
|
||||
#### v2.3.0 (February 19, 2021)
|
||||
* Fixed [issue](https://community.postman.com/t/user-feedback-updating-api-elements/13308/13) where content type header was reported missing in validation even if present.
|
||||
* Feature request [#9046](https://github.com/postmanlabs/postman-app-support/issues/9046) - Added support for validation of request body of type urlencoded.
|
||||
|
||||
#### v2.2.0 (January 28, 2021)
|
||||
* Fixed [issue](https://community.postman.com/t/openapi-import-with-multi-file-support/9439/8) with import folder flow on respective platform.
|
||||
* Fixed issue where collection did not contain name for specification with empty string as title.
|
||||
* Updated description of option to disable optional parameters.
|
||||
|
||||
@@ -418,7 +418,7 @@ module.exports = {
|
||||
_.forOwn(serverVariables, (value, key) => {
|
||||
let description = this.getParameterDescription(value);
|
||||
variables.push(new sdk.Variable({
|
||||
id: key,
|
||||
key: key,
|
||||
value: value.default || '',
|
||||
description: description
|
||||
}));
|
||||
@@ -426,7 +426,7 @@ module.exports = {
|
||||
}
|
||||
if (keyName) {
|
||||
variables.push(new sdk.Variable({
|
||||
id: keyName,
|
||||
key: keyName,
|
||||
value: serverUrl,
|
||||
type: 'string'
|
||||
}));
|
||||
@@ -1105,6 +1105,35 @@ module.exports = {
|
||||
return helper;
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates appropriate collection element based on parameter location
|
||||
*
|
||||
* @param {Object} param - Parameter object habing key, value and description (optional)
|
||||
* @param {String} location - Parameter location ("in" property of OAS defined parameter object)
|
||||
* @returns {Object} - SDK element
|
||||
*/
|
||||
generateSdkParam: function (param, location) {
|
||||
const sdkElementMap = {
|
||||
'query': sdk.QueryParam,
|
||||
'header': sdk.Header,
|
||||
'path': sdk.Variable
|
||||
};
|
||||
|
||||
let generatedParam = {
|
||||
key: param.key,
|
||||
value: param.value
|
||||
};
|
||||
|
||||
_.has(param, 'disabled') && (generatedParam.disabled = param.disabled);
|
||||
|
||||
// use appropriate sdk element based on location parmaeter is in for param generation
|
||||
if (sdkElementMap[location]) {
|
||||
generatedParam = new sdkElementMap[location](generatedParam);
|
||||
}
|
||||
param.description && (generatedParam.description = param.description);
|
||||
return generatedParam;
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates Auth helper for response, params (query, headers) in helper object is added in
|
||||
* request (originalRequest) part of example.
|
||||
@@ -1510,12 +1539,12 @@ module.exports = {
|
||||
case 'form':
|
||||
if (explode && _.isObject(paramValue)) {
|
||||
_.forEach(paramValue, (value, key) => {
|
||||
pmParams.push({
|
||||
pmParams.push(this.generateSdkParam({
|
||||
key: _.isArray(paramValue) ? paramName : key,
|
||||
value: (value === undefined ? '' : value),
|
||||
description,
|
||||
disabled
|
||||
});
|
||||
}, _.get(param, 'in')));
|
||||
});
|
||||
return pmParams;
|
||||
}
|
||||
@@ -1528,12 +1557,12 @@ module.exports = {
|
||||
case 'deepObject':
|
||||
if (_.isObject(paramValue)) {
|
||||
_.forOwn(paramValue, (value, key) => {
|
||||
pmParams.push({
|
||||
pmParams.push(this.generateSdkParam({
|
||||
key: param.name + '[' + key + ']',
|
||||
value: (value === undefined ? '' : value),
|
||||
description,
|
||||
disabled
|
||||
});
|
||||
}, _.get(param, 'in')));
|
||||
});
|
||||
}
|
||||
return pmParams;
|
||||
@@ -1559,12 +1588,12 @@ module.exports = {
|
||||
|
||||
// prepend starting value to serialised value (valid for empty value also)
|
||||
serialisedValue = startValue + serialisedValue;
|
||||
pmParams.push({
|
||||
pmParams.push(this.generateSdkParam({
|
||||
key: paramName,
|
||||
value: serialisedValue,
|
||||
description,
|
||||
disabled
|
||||
});
|
||||
}, _.get(param, 'in')));
|
||||
|
||||
return pmParams;
|
||||
},
|
||||
@@ -1672,55 +1701,36 @@ module.exports = {
|
||||
}
|
||||
description = (required ? '(Required) ' : '') + description +
|
||||
(enumValue ? ' (This can only be one of ' + enumValue + ')' : '');
|
||||
if (encoding.hasOwnProperty(key)) {
|
||||
encoding[key].name = key;
|
||||
encoding[key].schema = {
|
||||
type: typeof value
|
||||
};
|
||||
encoding[key].description = description;
|
||||
params = this.convertParamsWithStyle(encoding[key], value, PARAMETER_SOURCE.REQUEST, components,
|
||||
schemaCache, options);
|
||||
// TODO: Show warning for incorrect schema if !params
|
||||
params && params.forEach((element) => {
|
||||
// Collection v2.1 schema allows urlencoded param value to be only string
|
||||
if (typeof element.value !== 'string') {
|
||||
try {
|
||||
// convert other datatype to string (i.e. number, boolean etc)
|
||||
element.value = JSON.stringify(element.value);
|
||||
}
|
||||
catch (e) {
|
||||
// JSON.stringify can fail in few cases, suggest invalid type for such case
|
||||
// eslint-disable-next-line max-len
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Exceptions
|
||||
element.value = 'INVALID_URLENCODED_PARAM_TYPE';
|
||||
}
|
||||
}
|
||||
delete element.description;
|
||||
});
|
||||
paramArray.push(...params);
|
||||
}
|
||||
else {
|
||||
|
||||
!encoding[key] && (encoding[key] = {});
|
||||
encoding[key].name = key;
|
||||
encoding[key].schema = {
|
||||
type: typeof value
|
||||
};
|
||||
// for urlencoded body serialisation is treated similar to query param
|
||||
// reference https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#fixed-fields-13
|
||||
encoding[key].in = 'query';
|
||||
encoding[key].description = description;
|
||||
|
||||
params = this.convertParamsWithStyle(encoding[key], value, PARAMETER_SOURCE.REQUEST, components,
|
||||
schemaCache, options);
|
||||
// TODO: Show warning for incorrect schema if !params
|
||||
params && params.forEach((element) => {
|
||||
// Collection v2.1 schema allows urlencoded param value to be only string
|
||||
if (typeof value !== 'string') {
|
||||
if (typeof element.value !== 'string') {
|
||||
try {
|
||||
// convert other datatype to string (i.e. number, boolean etc)
|
||||
value = JSON.stringify(value);
|
||||
element.value = JSON.stringify(element.value);
|
||||
}
|
||||
catch (e) {
|
||||
// JSON.stringify can fail in few cases, suggest invalid type for such case
|
||||
// eslint-disable-next-line max-len
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Exceptions
|
||||
value = 'INVALID_URLENCODED_PARAM_TYPE';
|
||||
element.value = 'INVALID_URLENCODED_PARAM_TYPE';
|
||||
}
|
||||
}
|
||||
|
||||
param = new sdk.QueryParam({
|
||||
key: key,
|
||||
value: value
|
||||
});
|
||||
param.description = description;
|
||||
paramArray.push(param);
|
||||
}
|
||||
});
|
||||
paramArray.push(...params);
|
||||
});
|
||||
updateOptions = {
|
||||
mode: rDataMode,
|
||||
@@ -1865,7 +1875,7 @@ module.exports = {
|
||||
return null;
|
||||
}
|
||||
_.forOwn(response.headers, (value, key) => {
|
||||
if (key !== 'Content-Type') {
|
||||
if (_.toLower(key) !== 'content-type') {
|
||||
if (value.$ref) {
|
||||
// the convert to PmHeader function handles the
|
||||
// schema-faking
|
||||
@@ -2128,7 +2138,7 @@ module.exports = {
|
||||
convertedPathVar = _.get(this.convertParamsWithStyle(element, fakedData, PARAMETER_SOURCE.REQUEST,
|
||||
components, schemaCache, options), '[0]', {});
|
||||
|
||||
variableStore[element.name] = _.assign(convertedPathVar, { id: element.name, type: 'collection' });
|
||||
variableStore[element.name] = _.assign(convertedPathVar, { key: element.name, type: 'collection' });
|
||||
}
|
||||
});
|
||||
// accounting for the overriding of the root level and path level servers object if present at the operation level
|
||||
@@ -2159,7 +2169,7 @@ module.exports = {
|
||||
sanitizeResult.collectionVars.forEach((element) => {
|
||||
if (!variableStore[element.name]) {
|
||||
variableStore[element.name] = {
|
||||
id: element.name,
|
||||
key: element.name,
|
||||
value: element.value || '',
|
||||
description: element.description,
|
||||
type: 'collection'
|
||||
@@ -2256,7 +2266,6 @@ module.exports = {
|
||||
});
|
||||
});
|
||||
item.request.url.query.members.forEach((query) => {
|
||||
query.description = _.get(query, 'description.content', '');
|
||||
// Collection v2.1 schema allows query param value to be string/null
|
||||
if (typeof query.value !== 'string') {
|
||||
try {
|
||||
@@ -3729,7 +3738,8 @@ module.exports = {
|
||||
return false;
|
||||
}
|
||||
h.name = hName;
|
||||
return h.required;
|
||||
// exclude non-required and implicit header from further validation
|
||||
return h.required && !_.includes(IMPLICIT_HEADERS, _.toLower(hName));
|
||||
}), (header) => {
|
||||
if (!_.find(resHeaders, (param) => { return param.key === header.name; })) {
|
||||
|
||||
@@ -3801,6 +3811,160 @@ module.exports = {
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
else if (requestBody && requestBody.mode === 'urlencoded') {
|
||||
let urlencodedBodySchema = _.get(schemaPath, ['requestBody', 'content', URLENCODED, 'schema']),
|
||||
resolvedSchemaParams = [],
|
||||
pathPrefix = `${schemaPathPrefix}.requestBody.content[${URLENCODED}].schema`;
|
||||
|
||||
urlencodedBodySchema = deref.resolveRefs(urlencodedBodySchema, PARAMETER_SOURCE.REQUEST, components,
|
||||
schemaCache.schemaResolutionCache, PROCESSING_TYPE.VALIDATION, 'example', 0, {}, options.stackLimit);
|
||||
|
||||
// resolve each property as separate param similar to query parmas
|
||||
_.forEach(_.get(urlencodedBodySchema, 'properties'), (propSchema, propName) => {
|
||||
let resolvedProp = {
|
||||
name: propName,
|
||||
schema: propSchema,
|
||||
in: 'query' // serialization follows same behaviour as query params
|
||||
},
|
||||
encodingValue = _.get(schemaPath, ['requestBody', 'content', URLENCODED, 'encoding', propName]),
|
||||
pSerialisationInfo,
|
||||
isPropSeparable;
|
||||
|
||||
if (_.isObject(encodingValue)) {
|
||||
_.has(encodingValue, 'style') && (resolvedProp.style = encodingValue.style);
|
||||
_.has(encodingValue, 'explode') && (resolvedProp.explode = encodingValue.explode);
|
||||
}
|
||||
|
||||
if (_.includes(_.get(urlencodedBodySchema, 'required'), propName)) {
|
||||
resolvedProp.required = true;
|
||||
}
|
||||
|
||||
pSerialisationInfo = this.getParamSerialisationInfo(resolvedProp, PARAMETER_SOURCE.REQUEST,
|
||||
components, schemaCache);
|
||||
isPropSeparable = _.includes(['form', 'deepObject'], pSerialisationInfo.style);
|
||||
|
||||
if (isPropSeparable && propSchema.type === 'array' && pSerialisationInfo.explode) {
|
||||
// add schema of items and instead array
|
||||
resolvedSchemaParams.push(_.assign({}, resolvedProp, {
|
||||
schema: _.get(propSchema, 'items'),
|
||||
isResolvedParam: true
|
||||
}));
|
||||
}
|
||||
else if (isPropSeparable && propSchema.type === 'object' && pSerialisationInfo.explode) {
|
||||
// add schema of all properties instead entire object
|
||||
_.forEach(_.get(propSchema, 'properties', {}), (value, key) => {
|
||||
resolvedSchemaParams.push({
|
||||
name: key,
|
||||
schema: value,
|
||||
isResolvedParam: true
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
resolvedSchemaParams.push(resolvedProp);
|
||||
}
|
||||
});
|
||||
|
||||
return async.map(requestBody.urlencoded, (uParam, cb) => {
|
||||
let mismatches = [],
|
||||
index = _.findIndex(requestBody.urlencoded, uParam),
|
||||
resolvedParamValue = uParam.value;
|
||||
|
||||
const schemaParam = _.find(resolvedSchemaParams, (param) => { return param.name === uParam.key; });
|
||||
|
||||
if (!schemaParam) {
|
||||
// no schema param found
|
||||
if (options.showMissingInSchemaErrors) {
|
||||
mismatches.push({
|
||||
property: mismatchProperty,
|
||||
transactionJsonPath: transactionPathPrefix + `.urlencoded[${index}]`,
|
||||
schemaJsonPath: null,
|
||||
reasonCode: 'MISSING_IN_SCHEMA',
|
||||
reason: `The Url Encoded body param "${uParam.key}" was not found in the schema`
|
||||
});
|
||||
}
|
||||
return cb(null, mismatches);
|
||||
}
|
||||
|
||||
if (!schemaParam.isResolvedParam) {
|
||||
resolvedParamValue = this.deserialiseParamValue(schemaParam, uParam.value, PARAMETER_SOURCE.REQUEST,
|
||||
components, schemaCache);
|
||||
}
|
||||
// store value of transaction to use in mismatch object
|
||||
schemaParam.actualValue = uParam.value;
|
||||
|
||||
// param found in spec. check param's schema
|
||||
setTimeout(() => {
|
||||
if (!schemaParam.schema) {
|
||||
// no errors to show if there's no schema present in the spec
|
||||
return cb(null, []);
|
||||
}
|
||||
this.checkValueAgainstSchema(mismatchProperty,
|
||||
transactionPathPrefix + `.urlencoded[${index}].value`,
|
||||
uParam.key,
|
||||
resolvedParamValue,
|
||||
pathPrefix + '.properties[' + schemaParam.name + ']',
|
||||
schemaParam.schema,
|
||||
PARAMETER_SOURCE.REQUEST,
|
||||
components, options, schemaCache, cb
|
||||
);
|
||||
}, 0);
|
||||
}, (err, res) => {
|
||||
let mismatches = [],
|
||||
mismatchObj,
|
||||
// fetches property name from schem path
|
||||
getPropNameFromSchemPath = (schemaPath) => {
|
||||
let regex = /\.properties\[(.+)\]/gm;
|
||||
return _.last(regex.exec(schemaPath));
|
||||
};
|
||||
|
||||
// update actual value and suggested value from JSON to serialized strings
|
||||
_.forEach(_.flatten(res), (mismatchObj) => {
|
||||
if (!_.isEmpty(mismatchObj)) {
|
||||
let propertyName = getPropNameFromSchemPath(mismatchObj.schemaJsonPath),
|
||||
schemaParam = _.find(resolvedSchemaParams, (param) => { return param.name === propertyName; }),
|
||||
serializedParamValue;
|
||||
|
||||
if (schemaParam) {
|
||||
// serialize param value (to be used in suggested value)
|
||||
serializedParamValue = _.get(this.convertParamsWithStyle(schemaParam, _.get(mismatchObj,
|
||||
'suggestedFix.suggestedValue'), PARAMETER_SOURCE.REQUEST, components, schemaCache, options),
|
||||
'[0].value');
|
||||
_.set(mismatchObj, 'suggestedFix.actualValue', schemaParam.actualValue);
|
||||
_.set(mismatchObj, 'suggestedFix.suggestedValue', serializedParamValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_.each(resolvedSchemaParams, (uParam) => {
|
||||
// report mismatches only for reuired properties
|
||||
if (!_.find(requestBody.urlencoded, (param) => { return param.key === uParam.name; }) && uParam.required) {
|
||||
mismatchObj = {
|
||||
property: mismatchProperty,
|
||||
transactionJsonPath: transactionPathPrefix + '.urlencoded',
|
||||
schemaJsonPath: pathPrefix + '.properties[' + uParam.name + ']',
|
||||
reasonCode: 'MISSING_IN_REQUEST',
|
||||
reason: `The Url Encoded body param "${uParam.name}" was not found in the transaction`
|
||||
};
|
||||
|
||||
if (options.suggestAvailableFixes) {
|
||||
mismatchObj.suggestedFix = {
|
||||
key: uParam.name,
|
||||
actualValue: null,
|
||||
suggestedValue: {
|
||||
key: uParam.name,
|
||||
value: safeSchemaFaker(uParam.schema || {}, 'example', PROCESSING_TYPE.VALIDATION,
|
||||
PARAMETER_SOURCE.REQUEST, components, SCHEMA_FORMATS.DEFAULT, options.indentCharacter, schemaCache,
|
||||
options.stackLimit)
|
||||
}
|
||||
};
|
||||
}
|
||||
mismatches.push(mismatchObj);
|
||||
}
|
||||
});
|
||||
return callback(null, _.concat(_.flatten(res), mismatches));
|
||||
});
|
||||
}
|
||||
else {
|
||||
return callback(null, []);
|
||||
}
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openapi-to-postmanv2",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openapi-to-postmanv2",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"description": "Convert a given OpenAPI specification to Postman Collection v2.0",
|
||||
"homepage": "https://github.com/postmanlabs/openapi-to-postman",
|
||||
"bugs": "https://github.com/postmanlabs/openapi-to-postman/issues",
|
||||
|
||||
@@ -91,15 +91,11 @@
|
||||
"formParam1": {
|
||||
"description": "Description of formParam1",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
"type": "string"
|
||||
},
|
||||
"formParam2": {
|
||||
"description": "Description of formParam2",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,15 +116,11 @@
|
||||
"urlencodedParam1": {
|
||||
"description": "Description of urlencodedParam1",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
"type": "string"
|
||||
},
|
||||
"urlencodedParam2": {
|
||||
"description": "Description of urlencodedParam2",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ paths:
|
||||
description: Null response
|
||||
default:
|
||||
description: unexpected error
|
||||
headers:
|
||||
content-type:
|
||||
description: content-type of response body
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
|
||||
161
test/data/validationData/urlencodedBodyCollection.json
Normal file
161
test/data/validationData/urlencodedBodyCollection.json
Normal file
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"item": [
|
||||
{
|
||||
"id": "f5983708-1a61-43a4-919b-ca40a34fe2a3",
|
||||
"name": "pet",
|
||||
"description": {
|
||||
"content": "",
|
||||
"type": "text/plain"
|
||||
},
|
||||
"item": [
|
||||
{
|
||||
"id": "9c4d4bf3-c8f6-47f5-83d6-6e25f89c1314",
|
||||
"name": "Updates a pet in the store with form data",
|
||||
"request": {
|
||||
"name": "Updates a pet in the store with form data",
|
||||
"description": {},
|
||||
"url": {
|
||||
"path": [
|
||||
"pets",
|
||||
":petId"
|
||||
],
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"query": [],
|
||||
"variable": [
|
||||
{
|
||||
"description": "(Required) ID of pet that needs to be updated",
|
||||
"type": "any",
|
||||
"value": "elit nulla",
|
||||
"key": "petId"
|
||||
}
|
||||
]
|
||||
},
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/x-www-form-urlencoded"
|
||||
}
|
||||
],
|
||||
"method": "POST",
|
||||
"auth": null,
|
||||
"body": {
|
||||
"mode": "urlencoded",
|
||||
"urlencoded": [
|
||||
{
|
||||
"key": "prop1",
|
||||
"value": "hello"
|
||||
},
|
||||
{
|
||||
"key": "prop2",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"key": "propObjectNonExplodable",
|
||||
"value": "prop3,hello,prop4,true"
|
||||
},
|
||||
{
|
||||
"key": "propArray",
|
||||
"value": "str1"
|
||||
},
|
||||
{
|
||||
"key": "propArray",
|
||||
"value": "999"
|
||||
},
|
||||
{
|
||||
"key": "propSimple",
|
||||
"value": "123"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": [
|
||||
{
|
||||
"id": "613fc0d2-9836-48a6-9518-8f239ba9427f",
|
||||
"name": "Pet updated.",
|
||||
"originalRequest": {
|
||||
"url": {
|
||||
"path": [
|
||||
"pets",
|
||||
":petId"
|
||||
],
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"query": [],
|
||||
"variable": [
|
||||
{
|
||||
"type": "any",
|
||||
"key": "petId"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "POST",
|
||||
"body": {
|
||||
"mode": "urlencoded",
|
||||
"urlencoded": [
|
||||
{
|
||||
"key": "prop1",
|
||||
"value": "hello"
|
||||
},
|
||||
{
|
||||
"key": "prop2",
|
||||
"value": "world"
|
||||
},
|
||||
{
|
||||
"key": "propObjectNonExplodable",
|
||||
"value": "prop1,hello,prop2,world"
|
||||
},
|
||||
{
|
||||
"key": "propArray",
|
||||
"value": "str1"
|
||||
},
|
||||
{
|
||||
"key": "propArray",
|
||||
"value": "str2"
|
||||
},
|
||||
{
|
||||
"key": "propSimple",
|
||||
"value": "123"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"status": "OK",
|
||||
"code": 200,
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "text/plain"
|
||||
}
|
||||
],
|
||||
"body": "",
|
||||
"cookie": [],
|
||||
"_postman_previewlanguage": "text"
|
||||
}
|
||||
],
|
||||
"event": []
|
||||
}
|
||||
],
|
||||
"event": []
|
||||
}
|
||||
],
|
||||
"event": [],
|
||||
"variable": [
|
||||
{
|
||||
"id": "baseUrl",
|
||||
"type": "string",
|
||||
"value": "http://petstore.swagger.io/v1"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"_postman_id": "acd16ff0-eda5-48b4-b0de-4d35138da21d",
|
||||
"name": "Swagger Petstore",
|
||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||
"description": {
|
||||
"content": "",
|
||||
"type": "text/plain"
|
||||
}
|
||||
}
|
||||
}
|
||||
68
test/data/validationData/urlencodedBodySpec.yaml
Normal file
68
test/data/validationData/urlencodedBodySpec.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
version: 1.0.0
|
||||
title: Swagger Petstore
|
||||
license:
|
||||
name: MIT
|
||||
servers:
|
||||
- url: http://petstore.swagger.io/v1
|
||||
paths:
|
||||
/pets/{petId}:
|
||||
post:
|
||||
tags:
|
||||
- pet
|
||||
summary: Updates a pet in the store with form data
|
||||
operationId: updatePetWithForm
|
||||
parameters:
|
||||
- name: petId
|
||||
in: path
|
||||
description: ID of pet that needs to be updated
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
'application/x-www-form-urlencoded':
|
||||
schema:
|
||||
properties:
|
||||
propObjectExplodable:
|
||||
type: object
|
||||
properties:
|
||||
prop1:
|
||||
type: string
|
||||
example: hello
|
||||
prop2:
|
||||
type: string
|
||||
example: world
|
||||
propObjectNonExplodable:
|
||||
type: object
|
||||
properties:
|
||||
prop3:
|
||||
type: string
|
||||
example: hello
|
||||
prop4:
|
||||
type: string
|
||||
example: world
|
||||
propArray:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: exampleString
|
||||
example:
|
||||
- str1
|
||||
- str2
|
||||
propSimple:
|
||||
type: integer
|
||||
example: 123
|
||||
required:
|
||||
- status
|
||||
encoding:
|
||||
propObjectExplodable:
|
||||
style: form
|
||||
explode: true
|
||||
propObjectNonExplodable:
|
||||
style: form
|
||||
explode: false
|
||||
responses:
|
||||
'200':
|
||||
description: Pet updated.
|
||||
@@ -144,14 +144,14 @@ describe('CONVERT FUNCTION TESTS ', function() {
|
||||
expect(conversionResult.output[0].data).to.have.property('item');
|
||||
expect(conversionResult.output[0].data).to.have.property('variable');
|
||||
expect(conversionResult.output[0].data.variable).to.be.an('array');
|
||||
expect(conversionResult.output[0].data.variable[1].id).to.equal('format');
|
||||
expect(conversionResult.output[0].data.variable[1].key).to.equal('format');
|
||||
expect(conversionResult.output[0].data.variable[1].value).to.equal('json');
|
||||
expect(conversionResult.output[0].data.variable[2].id).to.equal('path');
|
||||
expect(conversionResult.output[0].data.variable[2].key).to.equal('path');
|
||||
expect(conversionResult.output[0].data.variable[2].value).to.equal('send-email');
|
||||
expect(conversionResult.output[0].data.variable[3].id).to.equal('new-path-variable-1');
|
||||
expect(conversionResult.output[0].data.variable[3].key).to.equal('new-path-variable-1');
|
||||
// serialised value for object { R: 100, G: 200, B: 150 }
|
||||
expect(conversionResult.output[0].data.variable[3].value).to.equal('R,100,G,200,B,150');
|
||||
expect(conversionResult.output[0].data.variable[4].id).to.equal('new-path-variable-2');
|
||||
expect(conversionResult.output[0].data.variable[4].key).to.equal('new-path-variable-2');
|
||||
// serialised value for array ["exampleString", "exampleString"]
|
||||
expect(conversionResult.output[0].data.variable[4].value).to.equal('exampleString,exampleString');
|
||||
done();
|
||||
@@ -902,8 +902,8 @@ describe('CONVERT FUNCTION TESTS ', function() {
|
||||
requestUrl = conversionResult.output[0].data.item[0].request.url;
|
||||
collectionVars = conversionResult.output[0].data.variable;
|
||||
expect(requestUrl.host).to.eql(['{{baseUrl}}']);
|
||||
expect(_.find(collectionVars, { id: 'baseUrl' }).value).to.eql('{{BASE_URI}}/api');
|
||||
expect(_.find(collectionVars, { id: 'BASE_URI' }).value).to.eql('https://api.example.com');
|
||||
expect(_.find(collectionVars, { key: 'baseUrl' }).value).to.eql('{{BASE_URI}}/api');
|
||||
expect(_.find(collectionVars, { key: 'BASE_URI' }).value).to.eql('https://api.example.com');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -231,7 +231,7 @@ describe('SCHEMA UTILITY FUNCTION TESTS ', function () {
|
||||
},
|
||||
retVal = SchemaUtils.convertToPmCollectionVariables(serverVariables, null, null);
|
||||
expect(retVal).to.be.an('array');
|
||||
expect(retVal[0].id).to.equal('v1');
|
||||
expect(retVal[0].key).to.equal('v1');
|
||||
expect(retVal[0].value).to.equal('v2.0');
|
||||
});
|
||||
|
||||
@@ -249,9 +249,9 @@ describe('SCHEMA UTILITY FUNCTION TESTS ', function () {
|
||||
|
||||
expect(retVal).to.be.an('array');
|
||||
|
||||
expect(retVal[0].id).to.equal('v1');
|
||||
expect(retVal[0].key).to.equal('v1');
|
||||
expect(retVal[0].value).to.equal('v2.0');
|
||||
expect(retVal[1].id).to.equal('baseUrl');
|
||||
expect(retVal[1].key).to.equal('baseUrl');
|
||||
expect(retVal[1].value).to.equal('hello.com');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -415,6 +415,10 @@ describe('VALIDATE FUNCTION TESTS ', function () {
|
||||
the mismatch for header-1 should contain correct index as in request.
|
||||
*/
|
||||
expect(_.endsWith(resultObj.mismatches[0].transactionJsonPath, '[2].value')).to.eql(true);
|
||||
_.forEach(resultObj.responses, (response) => {
|
||||
expect(response.matched).to.be.true;
|
||||
expect(response.mismatches).to.have.lengthOf(0);
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -628,6 +632,44 @@ describe('VALIDATE FUNCTION TESTS ', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to validate schema with request body of content type "application/x-www-form-urlencoded" ' +
|
||||
'against transaction with valid UrlEncoded body correctly', function (done) {
|
||||
let urlencodedBodySpec = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH +
|
||||
'/urlencodedBodySpec.yaml'), 'utf-8'),
|
||||
urlencodedBodyCollection = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH +
|
||||
'/urlencodedBodyCollection.json'), 'utf-8'),
|
||||
resultObj,
|
||||
historyRequest = [],
|
||||
schemaPack = new Converter.SchemaPack({ type: 'string', data: urlencodedBodySpec },
|
||||
{ suggestAvailableFixes: true });
|
||||
|
||||
getAllTransactions(JSON.parse(urlencodedBodyCollection), historyRequest);
|
||||
|
||||
schemaPack.validateTransaction(historyRequest, (err, result) => {
|
||||
expect(err).to.be.null;
|
||||
expect(result).to.be.an('object');
|
||||
resultObj = result.requests[historyRequest[0].id].endpoints[0];
|
||||
expect(resultObj.mismatches).to.have.lengthOf(3);
|
||||
|
||||
// for explodable property of type object named "propObjectExplodable",
|
||||
// second property named "prop2" is incorrect, while property "prop1" is correct
|
||||
expect(resultObj.mismatches[0].transactionJsonPath).to.eql('$.request.body.urlencoded[1].value');
|
||||
expect(resultObj.mismatches[0].suggestedFix.actualValue).to.eql('false');
|
||||
expect(resultObj.mismatches[0].suggestedFix.suggestedValue).to.eql('world');
|
||||
|
||||
// for non explodable property of type object, entire property with updated value should be suggested
|
||||
expect(resultObj.mismatches[1].transactionJsonPath).to.eql('$.request.body.urlencoded[2].value');
|
||||
expect(resultObj.mismatches[1].suggestedFix.actualValue).to.eql('prop3,hello,prop4,true');
|
||||
expect(resultObj.mismatches[1].suggestedFix.suggestedValue).to.eql('prop3,hello,prop4,world');
|
||||
|
||||
// for type array property named "propArray" second element is incorrect
|
||||
expect(resultObj.mismatches[2].transactionJsonPath).to.eql('$.request.body.urlencoded[4].value');
|
||||
expect(resultObj.mismatches[2].suggestedFix.actualValue).to.eql('999');
|
||||
expect(resultObj.mismatches[2].suggestedFix.suggestedValue).to.eql('exampleString');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('findMatchingRequestFromSchema function', function () {
|
||||
it('#GITHUB-9396 Should maintain correct order of matched endpoint', function (done) {
|
||||
let schema = {
|
||||
|
||||
Reference in New Issue
Block a user