mirror of
https://github.com/postmanlabs/openapi-to-postman.git
synced 2022-11-29 22:05:00 +03:00
Merge pull request #386 from postmanlabs/feature/fix-deepobject-conversion
Fixed issue where params with style deepObject were converted to only one level of key-value pair.
This commit is contained in:
@@ -1515,6 +1515,28 @@ module.exports = {
|
|||||||
return pmParams;
|
return pmParams;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursicely extracts key-value pair from deep objects.
|
||||||
|
*
|
||||||
|
* @param {*} deepObject - Deep object
|
||||||
|
* @param {*} objectKey - key associated with deep object
|
||||||
|
* @returns {Array} array of param key-value pairs
|
||||||
|
*/
|
||||||
|
extractDeepObjectParams: function (deepObject, objectKey) {
|
||||||
|
let extractedParams = [];
|
||||||
|
// console.log(deepObject);
|
||||||
|
|
||||||
|
_.forEach(deepObject, (value, key) => {
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
extractedParams = _.concat(extractedParams, this.extractDeepObjectParams(value, objectKey + '[' + key + ']'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
extractedParams.push({ key: objectKey + '[' + key + ']', value });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return extractedParams;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of parameters
|
* Returns an array of parameters
|
||||||
* Handles array/object/string param types
|
* Handles array/object/string param types
|
||||||
@@ -1573,10 +1595,12 @@ module.exports = {
|
|||||||
break;
|
break;
|
||||||
case 'deepObject':
|
case 'deepObject':
|
||||||
if (_.isObject(paramValue)) {
|
if (_.isObject(paramValue)) {
|
||||||
_.forOwn(paramValue, (value, key) => {
|
let extractedParams = this.extractDeepObjectParams(paramValue, paramName);
|
||||||
|
|
||||||
|
_.forEach(extractedParams, (extractedParam) => {
|
||||||
pmParams.push(this.generateSdkParam({
|
pmParams.push(this.generateSdkParam({
|
||||||
key: param.name + '[' + key + ']',
|
key: extractedParam.key,
|
||||||
value: (value === undefined ? '' : value),
|
value: extractedParam.value || '',
|
||||||
description,
|
description,
|
||||||
disabled
|
disabled
|
||||||
}, _.get(param, 'in')));
|
}, _.get(param, 'in')));
|
||||||
@@ -2811,6 +2835,50 @@ module.exports = {
|
|||||||
return { type, subtype };
|
return { type, subtype };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts all child parameters from explodable param
|
||||||
|
*
|
||||||
|
* @param {*} schema - Corresponding schema object of parent parameter to be devided into child params
|
||||||
|
* @param {*} paramKey - Parameter name of parent param object
|
||||||
|
* @param {*} metaInfo - meta information of param (i.e. required)
|
||||||
|
* @returns {Array} - Extracted child parameters
|
||||||
|
*/
|
||||||
|
extractChildParamSchema: function (schema, paramKey, metaInfo) {
|
||||||
|
let childParamSchemas = [];
|
||||||
|
|
||||||
|
_.forEach(_.get(schema, 'properties', {}), (value, key) => {
|
||||||
|
if (_.get(value, 'type') === 'object') {
|
||||||
|
childParamSchemas = _.concat(childParamSchemas, this.extractChildParamSchema(value,
|
||||||
|
`${paramKey}[${key}]`, metaInfo));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let required = _.get(metaInfo, 'required') || false,
|
||||||
|
pathPrefix = _.get(metaInfo, 'pathPrefix');
|
||||||
|
|
||||||
|
childParamSchemas.push({
|
||||||
|
name: `${paramKey}[${key}]`,
|
||||||
|
schema: value,
|
||||||
|
required,
|
||||||
|
isResolvedParam: true,
|
||||||
|
pathPrefix
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return childParamSchemas;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether given parameter is of complex array type from param key
|
||||||
|
*
|
||||||
|
* @param {*} paramKey - Parmaeter key that is to be tested
|
||||||
|
* @returns {Boolean} - result
|
||||||
|
*/
|
||||||
|
isParamComplexArray: function (paramKey) {
|
||||||
|
// this checks if parameter key numbered element (i.e. itemArray[1] is complex array param)
|
||||||
|
let regex = /\[[\d]+\]/gm;
|
||||||
|
return regex.test(paramKey);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds valid JSON media type object from content object
|
* Finds valid JSON media type object from content object
|
||||||
*
|
*
|
||||||
@@ -3369,22 +3437,36 @@ module.exports = {
|
|||||||
isPropSeparable = _.includes(['form', 'deepObject'], style);
|
isPropSeparable = _.includes(['form', 'deepObject'], style);
|
||||||
|
|
||||||
if (isPropSeparable && paramSchema.type === 'array' && explode) {
|
if (isPropSeparable && paramSchema.type === 'array' && explode) {
|
||||||
// add schema of items and instead array
|
/**
|
||||||
resolvedSchemaParams.push(_.assign({}, param, {
|
* avoid validation of complex array type param as OAS doesn't define serialisation
|
||||||
schema: _.get(paramSchema, 'items'),
|
* of Array with deepObject style
|
||||||
isResolvedParam: true
|
*/
|
||||||
}));
|
if (!_.includes(['array', 'object'], _.get(paramSchema, 'items.type'))) {
|
||||||
|
// add schema of corresponding items instead array
|
||||||
|
resolvedSchemaParams.push(_.assign({}, param, {
|
||||||
|
schema: _.get(paramSchema, 'items'),
|
||||||
|
isResolvedParam: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (isPropSeparable && paramSchema.type === 'object' && explode) {
|
else if (isPropSeparable && paramSchema.type === 'object' && explode) {
|
||||||
// add schema of all properties instead entire object
|
// resolve all child params of parent param with deepObject style
|
||||||
_.forEach(_.get(paramSchema, 'properties', {}), (propSchema, propName) => {
|
if (style === 'deepObject') {
|
||||||
resolvedSchemaParams.push({
|
resolvedSchemaParams = _.concat(resolvedSchemaParams, this.extractChildParamSchema(paramSchema,
|
||||||
name: propName,
|
param.name, { required: _.get(param, 'required'), pathPrefix }));
|
||||||
schema: propSchema,
|
}
|
||||||
isResolvedParam: true,
|
else {
|
||||||
pathPrefix
|
// add schema of all properties instead entire object
|
||||||
|
_.forEach(_.get(paramSchema, 'properties', {}), (propSchema, propName) => {
|
||||||
|
resolvedSchemaParams.push({
|
||||||
|
name: propName,
|
||||||
|
schema: propSchema,
|
||||||
|
required: _.get(param, 'required') || false,
|
||||||
|
isResolvedParam: true,
|
||||||
|
pathPrefix
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resolvedSchemaParams.push(param);
|
resolvedSchemaParams.push(param);
|
||||||
@@ -3399,7 +3481,10 @@ module.exports = {
|
|||||||
const schemaParam = _.find(resolvedSchemaParams, (param) => { return param.name === pQuery.key; });
|
const schemaParam = _.find(resolvedSchemaParams, (param) => { return param.name === pQuery.key; });
|
||||||
|
|
||||||
if (!schemaParam) {
|
if (!schemaParam) {
|
||||||
// no schema param found
|
// skip validation of complex array params
|
||||||
|
if (this.isParamComplexArray(pQuery.key)) {
|
||||||
|
return cb(null, mismatches);
|
||||||
|
}
|
||||||
if (options.showMissingInSchemaErrors) {
|
if (options.showMissingInSchemaErrors) {
|
||||||
mismatches.push({
|
mismatches.push({
|
||||||
property: mismatchProperty,
|
property: mismatchProperty,
|
||||||
@@ -3440,7 +3525,7 @@ module.exports = {
|
|||||||
let mismatches = [],
|
let mismatches = [],
|
||||||
mismatchObj;
|
mismatchObj;
|
||||||
|
|
||||||
_.each(_.filter(schemaParams, (q) => { return q.required; }), (qp) => {
|
_.each(_.filter(resolvedSchemaParams, (q) => { return q.required; }), (qp) => {
|
||||||
if (!_.find(requestQueryParams, (param) => { return param.key === qp.name; })) {
|
if (!_.find(requestQueryParams, (param) => { return param.key === qp.name; })) {
|
||||||
|
|
||||||
// assign parameter example(s) as schema examples;
|
// assign parameter example(s) as schema examples;
|
||||||
@@ -3807,7 +3892,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Only application/json is validated for now
|
// Only application/json and application/x-www-form-urlencoded is validated for now
|
||||||
checkRequestBody: function (requestBody, transactionPathPrefix, schemaPathPrefix, schemaPath,
|
checkRequestBody: function (requestBody, transactionPathPrefix, schemaPathPrefix, schemaPath,
|
||||||
components, options, schemaCache, callback) {
|
components, options, schemaCache, callback) {
|
||||||
// check for body modes
|
// check for body modes
|
||||||
@@ -3828,7 +3913,6 @@ module.exports = {
|
|||||||
jsonContentType = this.getJsonContentType(_.get(schemaPath, 'requestBody.content', {}));
|
jsonContentType = this.getJsonContentType(_.get(schemaPath, 'requestBody.content', {}));
|
||||||
jsonSchemaBody = _.get(schemaPath, ['requestBody', 'content', jsonContentType, 'schema']);
|
jsonSchemaBody = _.get(schemaPath, ['requestBody', 'content', jsonContentType, 'schema']);
|
||||||
|
|
||||||
// only raw for now
|
|
||||||
if (requestBody && requestBody.mode === 'raw' && jsonSchemaBody) {
|
if (requestBody && requestBody.mode === 'raw' && jsonSchemaBody) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
return this.checkValueAgainstSchema(mismatchProperty,
|
return this.checkValueAgainstSchema(mismatchProperty,
|
||||||
@@ -3878,21 +3962,35 @@ module.exports = {
|
|||||||
isPropSeparable = _.includes(['form', 'deepObject'], pSerialisationInfo.style);
|
isPropSeparable = _.includes(['form', 'deepObject'], pSerialisationInfo.style);
|
||||||
|
|
||||||
if (isPropSeparable && propSchema.type === 'array' && pSerialisationInfo.explode) {
|
if (isPropSeparable && propSchema.type === 'array' && pSerialisationInfo.explode) {
|
||||||
// add schema of items and instead array
|
/**
|
||||||
resolvedSchemaParams.push(_.assign({}, resolvedProp, {
|
* avoid validation of complex array type param as OAS doesn't define serialisation
|
||||||
schema: _.get(propSchema, 'items'),
|
* of Array with deepObject style
|
||||||
isResolvedParam: true
|
*/
|
||||||
}));
|
if (!_.includes(['array', 'object'], _.get(propSchema, 'items.type'))) {
|
||||||
|
// add schema of corresponding items instead array
|
||||||
|
resolvedSchemaParams.push(_.assign({}, resolvedProp, {
|
||||||
|
schema: _.get(propSchema, 'items'),
|
||||||
|
isResolvedParam: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (isPropSeparable && propSchema.type === 'object' && pSerialisationInfo.explode) {
|
else if (isPropSeparable && propSchema.type === 'object' && pSerialisationInfo.explode) {
|
||||||
// add schema of all properties instead entire object
|
// resolve all child params of parent param with deepObject style
|
||||||
_.forEach(_.get(propSchema, 'properties', {}), (value, key) => {
|
if (pSerialisationInfo.style === 'deepObject') {
|
||||||
resolvedSchemaParams.push({
|
resolvedSchemaParams = _.concat(resolvedSchemaParams, this.extractChildParamSchema(propSchema,
|
||||||
name: key,
|
propName, { required: resolvedProp.required || false }));
|
||||||
schema: value,
|
}
|
||||||
isResolvedParam: true
|
else {
|
||||||
|
// add schema of all properties instead entire object
|
||||||
|
_.forEach(_.get(propSchema, 'properties', {}), (value, key) => {
|
||||||
|
resolvedSchemaParams.push({
|
||||||
|
name: key,
|
||||||
|
schema: value,
|
||||||
|
isResolvedParam: true,
|
||||||
|
required: resolvedProp.required || false
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resolvedSchemaParams.push(resolvedProp);
|
resolvedSchemaParams.push(resolvedProp);
|
||||||
@@ -3907,7 +4005,10 @@ module.exports = {
|
|||||||
const schemaParam = _.find(resolvedSchemaParams, (param) => { return param.name === uParam.key; });
|
const schemaParam = _.find(resolvedSchemaParams, (param) => { return param.name === uParam.key; });
|
||||||
|
|
||||||
if (!schemaParam) {
|
if (!schemaParam) {
|
||||||
// no schema param found
|
// skip validation of complex array params
|
||||||
|
if (this.isParamComplexArray(uParam.key)) {
|
||||||
|
return cb(null, mismatches);
|
||||||
|
}
|
||||||
if (options.showMissingInSchemaErrors) {
|
if (options.showMissingInSchemaErrors) {
|
||||||
mismatches.push({
|
mismatches.push({
|
||||||
property: mismatchProperty,
|
property: mismatchProperty,
|
||||||
@@ -3971,7 +4072,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_.each(resolvedSchemaParams, (uParam) => {
|
_.each(resolvedSchemaParams, (uParam) => {
|
||||||
// report mismatches only for reuired properties
|
// report mismatches only for required properties
|
||||||
if (!_.find(requestBody.urlencoded, (param) => { return param.key === uParam.name; }) && uParam.required) {
|
if (!_.find(requestBody.urlencoded, (param) => { return param.key === uParam.name; }) && uParam.required) {
|
||||||
mismatchObj = {
|
mismatchObj = {
|
||||||
property: mismatchProperty,
|
property: mismatchProperty,
|
||||||
|
|||||||
160
test/data/validationData/queryParamDeepObjectCollection.json
Normal file
160
test/data/validationData/queryParamDeepObjectCollection.json
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
{
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"id": "9861bc73-aafe-4c44-8c91-f42e4d820ae6",
|
||||||
|
"name": "pet",
|
||||||
|
"description": {
|
||||||
|
"content": "",
|
||||||
|
"type": "text/plain"
|
||||||
|
},
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"id": "23d37c51-7a63-412e-b15a-10c336d49615",
|
||||||
|
"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"
|
||||||
|
],
|
||||||
|
"host": [
|
||||||
|
"{{baseUrl}}"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "user[id]",
|
||||||
|
"value": "notAnInteger",
|
||||||
|
"description": "(Required) info about user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "user[name]",
|
||||||
|
"value": "John Johanson",
|
||||||
|
"description": "(Required) info about user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "user[address][city]",
|
||||||
|
"value": "Delhi",
|
||||||
|
"description": "(Required) info about user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propArrayComplex[0][prop1ArrayComp]",
|
||||||
|
"value": "notAnInteger",
|
||||||
|
"description": "(Required) deepObject with complex array structure"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propArrayComplex[0][prop2ArrayComp]",
|
||||||
|
"value": "qui anim",
|
||||||
|
"description": "(Required) deepObject with complex array structure"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propArrayComplex[1][prop1ArrayComp]",
|
||||||
|
"value": "87313126",
|
||||||
|
"description": "(Required) deepObject with complex array structure"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propArrayComplex[1][prop2ArrayComp]",
|
||||||
|
"value": "reprehenderit",
|
||||||
|
"description": "(Required) deepObject with complex array structure"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"variable": []
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"auth": null
|
||||||
|
},
|
||||||
|
"response": [
|
||||||
|
{
|
||||||
|
"id": "76137f7a-7d78-4f8b-837f-d678124c0b8e",
|
||||||
|
"name": "Pet updated.",
|
||||||
|
"originalRequest": {
|
||||||
|
"url": {
|
||||||
|
"path": [
|
||||||
|
"pets"
|
||||||
|
],
|
||||||
|
"host": [
|
||||||
|
"{{baseUrl}}"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "user[id]",
|
||||||
|
"value": "123"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "user[name]",
|
||||||
|
"value": "John Johanson"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "user[address][city]",
|
||||||
|
"value": "Delhi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "user[address][country]",
|
||||||
|
"value": "India"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "propArrayComplex[0][prop1ArrayComp]",
|
||||||
|
"value": "70013937"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "propArrayComplex[0][prop2ArrayComp]",
|
||||||
|
"value": "pariatur sit consectetur minim"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "propArrayComplex[1][prop1ArrayComp]",
|
||||||
|
"value": "-77852940"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "propArrayComplex[1][prop2ArrayComp]",
|
||||||
|
"value": "amet"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"variable": []
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"body": {}
|
||||||
|
},
|
||||||
|
"status": "OK",
|
||||||
|
"code": 200,
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "text/plain"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": "",
|
||||||
|
"cookie": [],
|
||||||
|
"_postman_previewlanguage": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"event": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"event": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"event": [],
|
||||||
|
"variable": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"value": "http://petstore.swagger.io/v1",
|
||||||
|
"key": "baseUrl"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info": {
|
||||||
|
"_postman_id": "c3eff23a-fbd9-40b7-9029-7e9699d9bb1b",
|
||||||
|
"name": "Swagger Petstore",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||||
|
"description": {
|
||||||
|
"content": "",
|
||||||
|
"type": "text/plain"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
test/data/validationData/queryParamDeepObjectSpec.yaml
Normal file
56
test/data/validationData/queryParamDeepObjectSpec.yaml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
openapi: "3.0.0"
|
||||||
|
info:
|
||||||
|
version: 1.0.0
|
||||||
|
title: Swagger Petstore
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
servers:
|
||||||
|
- url: http://petstore.swagger.io/v1
|
||||||
|
paths:
|
||||||
|
/pets:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- pet
|
||||||
|
summary: Updates a pet in the store with form data
|
||||||
|
operationId: updatePetWithForm
|
||||||
|
parameters:
|
||||||
|
- name: user
|
||||||
|
in: query
|
||||||
|
description: info about user
|
||||||
|
required: true
|
||||||
|
style: deepObject
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
example: 123
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
example: John Johanson
|
||||||
|
address:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
city:
|
||||||
|
type: string
|
||||||
|
example: Delhi
|
||||||
|
country:
|
||||||
|
type: string
|
||||||
|
example: India
|
||||||
|
- name: propArrayComplex
|
||||||
|
in: query
|
||||||
|
description: deepObject with complex array structure
|
||||||
|
required: true
|
||||||
|
style: deepObject
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
prop1ArrayComp:
|
||||||
|
type: integer
|
||||||
|
prop2ArrayComp:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Pet updated.
|
||||||
@@ -66,6 +66,46 @@
|
|||||||
{
|
{
|
||||||
"key": "propSimple",
|
"key": "propSimple",
|
||||||
"value": "123"
|
"value": "123"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propDeepObject[id]",
|
||||||
|
"value": "123"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propDeepObject[name]",
|
||||||
|
"value": "John Johanson"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propDeepObject[address][city]",
|
||||||
|
"value": "123"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propDeepObject[address][country]",
|
||||||
|
"value": "India"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propArrayComplex[0][prop1ArrayComp]",
|
||||||
|
"value": "notAnInteger"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propArrayComplex[0][prop2ArrayComp]",
|
||||||
|
"value": "irure labore Lorem consequat l"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propArrayComplex[1][prop1ArrayComp]",
|
||||||
|
"value": "-14216671"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"disabled": false,
|
||||||
|
"key": "propArrayComplex[1][prop2ArrayComp]",
|
||||||
|
"value": "officia"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,33 @@ paths:
|
|||||||
propSimple:
|
propSimple:
|
||||||
type: integer
|
type: integer
|
||||||
example: 123
|
example: 123
|
||||||
|
propDeepObject:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
example: 123
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
example: John Johanson
|
||||||
|
address:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
city:
|
||||||
|
type: string
|
||||||
|
example: Delhi
|
||||||
|
country:
|
||||||
|
type: string
|
||||||
|
example: India
|
||||||
|
propArrayComplex:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
prop1ArrayComp:
|
||||||
|
type: integer
|
||||||
|
prop2ArrayComp:
|
||||||
|
type: string
|
||||||
required:
|
required:
|
||||||
- status
|
- status
|
||||||
encoding:
|
encoding:
|
||||||
@@ -63,6 +90,12 @@ paths:
|
|||||||
propObjectNonExplodable:
|
propObjectNonExplodable:
|
||||||
style: form
|
style: form
|
||||||
explode: false
|
explode: false
|
||||||
|
propDeepObject:
|
||||||
|
style: deepObject
|
||||||
|
explode: true
|
||||||
|
propArrayComplex:
|
||||||
|
style: deepObject
|
||||||
|
explode: true
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Pet updated.
|
description: Pet updated.
|
||||||
|
|||||||
@@ -1427,18 +1427,34 @@ describe('SCHEMA UTILITY FUNCTION TESTS ', function () {
|
|||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: 'string'
|
type: 'string'
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
city: { type: 'string' },
|
||||||
|
state: { type: 'string' },
|
||||||
|
country: { type: 'string' }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
it('schemaFaker = true', function (done) {
|
it('schemaFaker = true', function (done) {
|
||||||
let pmParam = SchemaUtils.convertToPmQueryParameters(param);
|
let pmParam = SchemaUtils.convertToPmQueryParameters(param);
|
||||||
|
expect(pmParam).to.have.lengthOf(5);
|
||||||
expect(pmParam[0].key).to.equal(param.name + '[id]');
|
expect(pmParam[0].key).to.equal(param.name + '[id]');
|
||||||
expect(pmParam[1].key).to.equal(param.name + '[name]');
|
expect(pmParam[1].key).to.equal(param.name + '[name]');
|
||||||
expect(pmParam[0].description).to.equal(param.description);
|
expect(pmParam[2].key).to.equal(param.name + '[address][city]');
|
||||||
expect(pmParam[1].description).to.equal(param.description);
|
expect(pmParam[3].key).to.equal(param.name + '[address][state]');
|
||||||
|
expect(pmParam[4].key).to.equal(param.name + '[address][country]');
|
||||||
|
|
||||||
|
_.map(pmParam, (val, ind) => { expect(pmParam[ind].description).to.equal(param.description); });
|
||||||
|
|
||||||
expect(pmParam[0].value).to.equal('<long>');
|
expect(pmParam[0].value).to.equal('<long>');
|
||||||
expect(pmParam[1].value).to.equal('<string>');
|
expect(pmParam[1].value).to.equal('<string>');
|
||||||
|
expect(pmParam[2].value).to.equal('<string>');
|
||||||
|
expect(pmParam[3].value).to.equal('<string>');
|
||||||
|
expect(pmParam[4].value).to.equal('<string>');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
it('schemaFaker = false', function (done) {
|
it('schemaFaker = false', function (done) {
|
||||||
|
|||||||
@@ -640,6 +640,51 @@ describe('VALIDATE FUNCTION TESTS ', function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should be able to validate schema with deepObject style query params against corresponding ' +
|
||||||
|
'transactions', function (done) {
|
||||||
|
let queryParamDeepObjectSpec = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH +
|
||||||
|
'/queryParamDeepObjectSpec.yaml'), 'utf-8'),
|
||||||
|
queryParamDeepObjectCollection = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH +
|
||||||
|
'/queryParamDeepObjectCollection.json'), 'utf-8'),
|
||||||
|
resultObj,
|
||||||
|
historyRequest = [],
|
||||||
|
schemaPack = new Converter.SchemaPack({ type: 'string', data: queryParamDeepObjectSpec },
|
||||||
|
{ suggestAvailableFixes: true, showMissingInSchemaErrors: true });
|
||||||
|
|
||||||
|
getAllTransactions(JSON.parse(queryParamDeepObjectCollection), 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(2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* no mismatches should be found for complex array type params as validation is skipped for them,
|
||||||
|
* even though corresponding value is of incorrect type
|
||||||
|
*/
|
||||||
|
_.forEach(resultObj.mismatches, (mismatch) => {
|
||||||
|
expect(mismatch.suggestedFix.key).to.not.eql('propArrayComplex[0][prop1ArrayComp]');
|
||||||
|
});
|
||||||
|
|
||||||
|
// for deepObject param "user", child param "user[id]" is of incorrect type
|
||||||
|
expect(resultObj.mismatches[0].reasonCode).to.eql('INVALID_TYPE');
|
||||||
|
expect(resultObj.mismatches[0].transactionJsonPath).to.eql('$.request.url.query[0].value');
|
||||||
|
expect(resultObj.mismatches[0].suggestedFix.actualValue).to.eql('notAnInteger');
|
||||||
|
expect(resultObj.mismatches[0].suggestedFix.suggestedValue).to.eql(123);
|
||||||
|
|
||||||
|
// for deepObject param "user", child param "user[address][country]" is missing in transaction
|
||||||
|
expect(resultObj.mismatches[1].reasonCode).to.eql('MISSING_IN_REQUEST');
|
||||||
|
expect(resultObj.mismatches[1].suggestedFix.key).to.eql('user[address][country]');
|
||||||
|
expect(resultObj.mismatches[1].suggestedFix.actualValue).to.be.null;
|
||||||
|
expect(resultObj.mismatches[1].suggestedFix.suggestedValue).to.eql({
|
||||||
|
key: 'user[address][country]',
|
||||||
|
value: 'India'
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getPostmanUrlSuffixSchemaScore function', function () {
|
describe('getPostmanUrlSuffixSchemaScore function', function () {
|
||||||
@@ -668,7 +713,7 @@ describe('VALIDATE FUNCTION TESTS ', function () {
|
|||||||
resultObj,
|
resultObj,
|
||||||
historyRequest = [],
|
historyRequest = [],
|
||||||
schemaPack = new Converter.SchemaPack({ type: 'string', data: urlencodedBodySpec },
|
schemaPack = new Converter.SchemaPack({ type: 'string', data: urlencodedBodySpec },
|
||||||
{ suggestAvailableFixes: true });
|
{ suggestAvailableFixes: true, showMissingInSchemaErrors: true });
|
||||||
|
|
||||||
getAllTransactions(JSON.parse(urlencodedBodyCollection), historyRequest);
|
getAllTransactions(JSON.parse(urlencodedBodyCollection), historyRequest);
|
||||||
|
|
||||||
@@ -676,7 +721,15 @@ describe('VALIDATE FUNCTION TESTS ', function () {
|
|||||||
expect(err).to.be.null;
|
expect(err).to.be.null;
|
||||||
expect(result).to.be.an('object');
|
expect(result).to.be.an('object');
|
||||||
resultObj = result.requests[historyRequest[0].id].endpoints[0];
|
resultObj = result.requests[historyRequest[0].id].endpoints[0];
|
||||||
expect(resultObj.mismatches).to.have.lengthOf(3);
|
expect(resultObj.mismatches).to.have.lengthOf(4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* no mismatches should be found for complex array type params as validation is skipped for them,
|
||||||
|
* even though corresponding value is of incorrect type
|
||||||
|
*/
|
||||||
|
_.forEach(resultObj.mismatches, (mismatch) => {
|
||||||
|
expect(mismatch.suggestedFix.key).to.not.eql('propArrayComplex[0][prop1ArrayComp]');
|
||||||
|
});
|
||||||
|
|
||||||
// for explodable property of type object named "propObjectExplodable",
|
// for explodable property of type object named "propObjectExplodable",
|
||||||
// second property named "prop2" is incorrect, while property "prop1" is correct
|
// second property named "prop2" is incorrect, while property "prop1" is correct
|
||||||
@@ -693,6 +746,11 @@ describe('VALIDATE FUNCTION TESTS ', function () {
|
|||||||
expect(resultObj.mismatches[2].transactionJsonPath).to.eql('$.request.body.urlencoded[4].value');
|
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.actualValue).to.eql('999');
|
||||||
expect(resultObj.mismatches[2].suggestedFix.suggestedValue).to.eql('exampleString');
|
expect(resultObj.mismatches[2].suggestedFix.suggestedValue).to.eql('exampleString');
|
||||||
|
|
||||||
|
// for deepObject property named "propDeepObject" child param "propDeepObject[address][city]" is of incorrect type
|
||||||
|
expect(resultObj.mismatches[3].transactionJsonPath).to.eql('$.request.body.urlencoded[8].value');
|
||||||
|
expect(resultObj.mismatches[3].suggestedFix.actualValue).to.eql('123');
|
||||||
|
expect(resultObj.mismatches[3].suggestedFix.suggestedValue).to.eql('Delhi');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user