fix oneOf child no type

This commit is contained in:
Luis Tejeda
2022-09-20 13:44:46 -05:00
parent bdfeadb49d
commit 81b8581a3b
6 changed files with 869 additions and 3 deletions

View File

@@ -28,7 +28,8 @@ const _ = require('lodash'),
'double'
],
DEFAULT_SCHEMA_UTILS = require('./30XUtils/schemaUtils30X'),
traverseUtility = require('traverse');
traverseUtility = require('traverse'),
PROPERTIES_TO_ASSIGN_ON_CASCADE = ['type', 'nullable'];
/**
* @param {*} currentNode - the object from which you're trying to find references
@@ -171,6 +172,11 @@ module.exports = {
resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
}
return { anyOf: _.map(schema.anyOf, (schemaElement) => {
PROPERTIES_TO_ASSIGN_ON_CASCADE.forEach((prop) => {
if (_.isNil(schemaElement[prop]) && !_.isNil(schema[prop])) {
schemaElement[prop] = schema[prop];
}
});
return this.resolveRefs(schemaElement, parameterSourceOption, components, schemaResolutionCache, resolveFor,
resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
}) };
@@ -181,8 +187,14 @@ module.exports = {
resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
}
return { oneOf: _.map(schema.oneOf, (schemaElement) => {
return this.resolveRefs(schemaElement, parameterSourceOption, components, schemaResolutionCache, resolveFor,
resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
PROPERTIES_TO_ASSIGN_ON_CASCADE.forEach((prop) => {
if (_.isNil(schemaElement[prop]) && !_.isNil(schema[prop])) {
schemaElement[prop] = schema[prop];
}
});
return this.resolveRefs(schemaElement, parameterSourceOption, components, schemaResolutionCache,
resolveFor, resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
}) };
}
if (schema.allOf) {

View File

@@ -0,0 +1,189 @@
{
"openapi": "3.1.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"license": {
"name": "MIT"
}
},
"servers": [
{
"url": "http://petstore.swagger.io/v1"
}
],
"paths": {
"/pets": {
"get": {
"summary": "List all pets",
"operationId": "listPets",
"tags": [
"pets"
],
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "A paged array of pets",
"headers": {
"x-next": {
"description": "A link to the next page of responses",
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pets"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"summary": "Create a pet",
"operationId": "createPets",
"tags": [
"pets"
],
"responses": {
"201": {
"description": "Null response"
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/pets/{petId}": {
"get": {
"summary": "Info for a specific pet",
"operationId": "showPetById",
"tags": [
"pets"
],
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"description": "The id of the pet to retrieve",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Expected response to a valid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"actualDelivery": {
"type": "string",
"nullable": true,
"oneOf": [
{
"enum": [
""
]
},
{
"format": "date-time",
"pattern": "^\\d{4}-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12]\\d)(T| )(2[0-3]|[01][0-9]):[0-5]\\d(|(:[0-5]\\dZ?)|(:[0-5]\\d\\.\\d{3})|(:[0-5]\\d\\.\\d{3}[+-]\\d{2}:\\d{2}))$"
}
]
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
},
"Error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}
}

View File

@@ -0,0 +1,352 @@
{
"item": [
{
"id": "ea0665ed-5e87-44ea-a4e5-378b09291348",
"name": "pets",
"description": {
"content": "",
"type": "text/plain"
},
"item": [
{
"id": "8d8dab29-2d55-4bd2-b19f-7793efd1d1e3",
"name": "List all pets",
"request": {
"name": "List all pets",
"description": {},
"url": {
"path": [
"pets"
],
"host": [
"{{baseUrl}}"
],
"query": [
{
"disabled": false,
"key": "limit",
"value": "1827513",
"description": "How many items to return at one time (max 100)"
}
],
"variable": []
},
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"method": "GET",
"auth": null
},
"response": [
{
"id": "08413bb8-52b6-4d4c-9660-ed92fa62c2ae",
"name": "A paged array of pets",
"originalRequest": {
"url": {
"path": [
"pets"
],
"host": [
"{{baseUrl}}"
],
"query": [
{
"key": "limit",
"value": "1827513"
}
],
"variable": []
},
"method": "GET",
"body": {}
},
"status": "OK",
"code": 200,
"header": [
{
"disabled": false,
"description": "A link to the next page of responses",
"key": "x-next",
"value": "veniam aliqua nulla"
},
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": "[\n {\n \"id\": -23271102,\n \"name\": \"consectetur incididunt amet eu ea\",\n \"actualDelivery\": null\n },\n {\n \"id\": -95645533,\n \"name\": \"nulla esse\",\n \"actualDelivery\": \"\"\n }\n]",
"cookie": [],
"_postman_previewlanguage": "json"
},
{
"id": "2004316e-3bcf-4a89-b292-29f1721c7af1",
"name": "unexpected error",
"originalRequest": {
"url": {
"path": [
"pets"
],
"host": [
"{{baseUrl}}"
],
"query": [
{
"key": "limit",
"value": "1827513"
}
],
"variable": []
},
"method": "GET",
"body": {}
},
"status": "Internal Server Error",
"code": 500,
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": "{\n \"code\": -90272305,\n \"message\": \"enim ut exercitation tempor\"\n}",
"cookie": [],
"_postman_previewlanguage": "json"
}
],
"event": [],
"protocolProfileBehavior": {
"disableBodyPruning": true
}
},
{
"id": "98538861-fa3c-41a5-aebe-ddafcfc8f5b5",
"name": "Create a pet",
"request": {
"name": "Create a pet",
"description": {},
"url": {
"path": [
"pets"
],
"host": [
"{{baseUrl}}"
],
"query": [],
"variable": []
},
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"method": "POST",
"auth": null
},
"response": [
{
"id": "4aaf0c36-5610-4cd5-b6e8-cd694700e8e7",
"name": "Null response",
"originalRequest": {
"url": {
"path": [
"pets"
],
"host": [
"{{baseUrl}}"
],
"query": [],
"variable": []
},
"method": "POST",
"body": {}
},
"status": "Created",
"code": 201,
"header": [
{
"key": "Content-Type",
"value": "text/plain"
}
],
"body": "",
"cookie": [],
"_postman_previewlanguage": "text"
},
{
"id": "c9da228f-07de-40aa-a044-fd0b03501ef1",
"name": "unexpected error",
"originalRequest": {
"url": {
"path": [
"pets"
],
"host": [
"{{baseUrl}}"
],
"query": [],
"variable": []
},
"method": "POST",
"body": {}
},
"status": "Internal Server Error",
"code": 500,
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": "{\n \"code\": -90272305,\n \"message\": \"enim ut exercitation tempor\"\n}",
"cookie": [],
"_postman_previewlanguage": "json"
}
],
"event": [],
"protocolProfileBehavior": {
"disableBodyPruning": true
}
},
{
"id": "4a11ebf8-1f2d-4d84-aaa8-659949ea4453",
"name": "Info for a specific pet",
"request": {
"name": "Info for a specific pet",
"description": {},
"url": {
"path": [
"pets",
":petId"
],
"host": [
"{{baseUrl}}"
],
"query": [],
"variable": [
{
"disabled": false,
"type": "any",
"value": "veniam aliqua nulla",
"key": "petId",
"description": "(Required) The id of the pet to retrieve"
}
]
},
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"method": "GET",
"auth": null
},
"response": [
{
"id": "3668a899-7e64-405e-94a9-be88bdd6efda",
"name": "Expected response to a valid request",
"originalRequest": {
"url": {
"path": [
"pets",
":petId"
],
"host": [
"{{baseUrl}}"
],
"query": [],
"variable": [
{
"disabled": false,
"type": "any",
"value": "veniam aliqua nulla",
"key": "petId",
"description": "(Required) The id of the pet to retrieve"
}
]
},
"method": "GET",
"body": {}
},
"status": "OK",
"code": 200,
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": "{\n \"id\": -94365708,\n \"name\": \"consectetur ullamco\",\n \"actualDelivery\": \"1988-12-23 15:15:15\"\n}",
"cookie": [],
"_postman_previewlanguage": "json"
},
{
"id": "290947ac-e737-4901-ad7d-477ef14cf0ec",
"name": "unexpected error",
"originalRequest": {
"url": {
"path": [
"pets",
":petId"
],
"host": [
"{{baseUrl}}"
],
"query": [],
"variable": [
{
"disabled": false,
"type": "any",
"value": "veniam aliqua nulla",
"key": "petId",
"description": "(Required) The id of the pet to retrieve"
}
]
},
"method": "GET",
"body": {}
},
"status": "Internal Server Error",
"code": 500,
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": "{\n \"code\": -90272305,\n \"message\": \"enim ut exercitation tempor\"\n}",
"cookie": [],
"_postman_previewlanguage": "json"
}
],
"event": [],
"protocolProfileBehavior": {
"disableBodyPruning": true
}
}
],
"event": []
}
],
"event": [],
"variable": [
{
"type": "string",
"value": "http://petstore.swagger.io/v1",
"key": "baseUrl"
}
],
"info": {
"_postman_id": "d8469366-fa38-4929-8f27-ef24140fede8",
"name": "Swagger Petstore",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"description": {
"content": "",
"type": "text/plain"
}
}
}

View File

@@ -0,0 +1,189 @@
{
"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": {
"summary": "List all pets",
"operationId": "listPets",
"tags": [
"pets"
],
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "A paged array of pets",
"headers": {
"x-next": {
"description": "A link to the next page of responses",
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pets"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"summary": "Create a pet",
"operationId": "createPets",
"tags": [
"pets"
],
"responses": {
"201": {
"description": "Null response"
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/pets/{petId}": {
"get": {
"summary": "Info for a specific pet",
"operationId": "showPetById",
"tags": [
"pets"
],
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"description": "The id of the pet to retrieve",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Expected response to a valid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"actualDelivery": {
"type": "string",
"nullable": true,
"oneOf": [
{
"enum": [
""
]
},
{
"format": "date-time",
"pattern": "^\\d{4}-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12]\\d)(T| )(2[0-3]|[01][0-9]):[0-5]\\d(|(:[0-5]\\dZ?)|(:[0-5]\\d\\.\\d{3})|(:[0-5]\\d\\.\\d{3}[+-]\\d{2}:\\d{2}))$"
}
]
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
},
"Error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}
}

View File

@@ -746,6 +746,13 @@ describe('VALIDATE FUNCTION TESTS ', function () {
VALIDATION_DATA_SCENARIOS_FOLDER_31_PATH
),
'/invalidTypeProperty.yaml'
),
oneOfChildPropertyNoType = getSpecsPathByVersion(
getFoldersByVersion(
VALIDATION_DATA_FOLDER_PATH,
VALIDATION_DATA_SCENARIOS_FOLDER_31_PATH
),
'/oneOfChildNoTypeSpec.json'
);
emptyParameterSpecs.forEach((specData) => {
@@ -1233,6 +1240,31 @@ describe('VALIDATE FUNCTION TESTS ', function () {
});
});
});
oneOfChildPropertyNoType.forEach((specData) => {
it('Should correctly ' +
specData.version, function (done) {
let invalidTypePropertySpec = fs.readFileSync(specData.path, 'utf-8'),
invalidTypePropertyCollection = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH +
'/oneOfChildNoTypeColl.json'), 'utf-8'),
options = { allowUrlPathVarMatching: true, detailedBlobValidation: true },
resultObj,
historyRequest = [],
schemaPack = new Converter.SchemaPack({ type: 'string', data: invalidTypePropertySpec }, options);
getAllTransactions(JSON.parse(invalidTypePropertyCollection), 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];
const responseId = _.keys(resultObj.responses)[0],
responseMissmatches = resultObj.responses[responseId].mismatches;
expect(responseMissmatches).to.have.lengthOf(0);
done();
});
});
});
});
describe('getPostmanUrlSuffixSchemaScore function', function () {

View File

@@ -408,6 +408,98 @@ describe('validateSchema', function () {
result = validateSchema(schema, valueToUse);
expect(result).to.be.empty;
});
it('Should return 0 errors with oneOf string nullable and correct values', function () {
const schema = {
type: 'array',
items: {
type: 'object',
required: [
'id'
],
properties: {
id: {
type: 'integer',
format: 'int64'
},
actualDelivery: {
oneOf: [
{
enum: [
''
],
type: 'string',
nullable: true
},
{
type: 'string',
pattern: '^\\d{4}-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12]\\d)(T| )(2[0-3]|[01][0-9]):' +
'[0-5]\\d(|(:[0-5]\\dZ?)|(:[0-5]\\d\\.\\d{3})|(:[0-5]\\d\\.\\d{3}[+-]\\d{2}:\\d{2}))$',
nullable: true
}
]
}
}
}
},
valueToUse = [{
id: 122,
actualDelivery: null
},
{
id: 122,
actualDelivery: ''
},
{
id: 122,
actualDelivery: '1988-12-23 15:15:15'
}],
result = validateSchema(schema, valueToUse);
expect(result).to.be.empty;
});
it('Should return 1 error with oneOf string nullable and incorrect value', function() {
const schema = {
type: 'array',
items: {
type: 'object',
required: [
'id'
],
properties: {
id: {
type: 'integer',
format: 'int64'
},
actualDelivery: {
oneOf: [
{
enum: [
''
],
type: 'string',
nullable: true
},
{
type: 'string',
pattern: '^\\d{4}-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12]\\d)(T| )(2[0-3]|[01][0-9]):' +
'[0-5]\\d(|(:[0-5]\\dZ?)|(:[0-5]\\d\\.\\d{3})|(:[0-5]\\d\\.\\d{3}[+-]\\d{2}:\\d{2}))$',
nullable: true
}
]
}
}
}
},
valueToUse = [
{
id: 122,
actualDelivery: 'not valid'
}],
result = validateSchema(schema, valueToUse);
expect(result[0].keyword).to.equal('enum');
expect(result[1].keyword).to.equal('pattern');
});
});
describe('getDraftToUse', function() {