Merge pull request #462 from postmanlabs/fix31TypesbyExamples

Fix31 types by examples
This commit is contained in:
Carlos-Veloz
2022-02-03 09:55:17 -06:00
committed by GitHub
4 changed files with 204 additions and 5 deletions

View File

@@ -50,6 +50,45 @@ module.exports = {
return isTypeMatching; return isTypeMatching;
}, },
/**
* Identifies the correct type from the list according to the example
*
* @param {*} examples provided example values
* @param {Array} typesArray the types array of the schema
* @returns {string} the most according type to the example
*/
findTypeByExample(examples, typesArray) {
const mapTypes = {
'boolean': 'boolean',
'null': 'null',
'undefined': 'null',
'number': 'number',
'bigInt': 'number',
'object': 'object',
'string': 'string'
};
let foundType,
foundExample;
for (let index = 0; index < examples.length; index++) {
const example = examples[index];
let exampleType = typeof example,
mappedType = mapTypes[exampleType];
if (mappedType === 'number') {
mappedType = Number.isInteger(example) ? 'integer' : mappedType;
}
foundType = typesArray.find((type) => {
return type === mappedType;
});
if (foundType) {
foundExample = example;
break;
}
}
return { foundType, foundExample };
},
/** /**
* Takes the first element from 'examples' property in a schema and adds a new 'example' property. * Takes the first element from 'examples' property in a schema and adds a new 'example' property.
* This method is used before faking the schema. (Schema faker uses the example property to fakle the schema) * This method is used before faking the schema. (Schema faker uses the example property to fakle the schema)
@@ -65,14 +104,23 @@ module.exports = {
typeIsAnArray = schema.hasOwnProperty('type') && typeIsAnArray = schema.hasOwnProperty('type') &&
Array.isArray(schema.type); Array.isArray(schema.type);
if (typeIsAnArray) { if (hasExamplesInRoot && typeIsAnArray) {
let typeAndExample = this.findTypeByExample(schema.examples, schema.type),
foundType = typeAndExample.foundType,
foundExample = typeAndExample.foundExample;
schema.type = foundType ? foundType : schema.type[0];
schema.example = foundExample ? foundExample : schema.examples[0];
}
if (hasExamplesInRoot && !typeIsAnArray) {
schema.example = schema.examples[0];
}
if (!hasExamplesInRoot && typeIsAnArray) {
schema.type = schema.type[0]; schema.type = schema.type[0];
} }
if (hasExamplesInRoot) { if (!hasExamplesInRoot && hasChildItems) {
schema.example = schema.examples[0];
}
else if (hasChildItems) {
schema.items = this.fixExamplesByVersion(schema.items); schema.items = this.fixExamplesByVersion(schema.items);
} }
else if (hasProperties) { else if (hasProperties) {

View File

@@ -0,0 +1,33 @@
openapi: "3.1.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/test:
post:
summary: schema with examples
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/schema1"
responses:
default:
description: ok
components:
schemas:
schema1:
type:
- object
properties:
id:
type:
- string
- integer
examples:
- 1234
- 12

View File

@@ -524,6 +524,67 @@ describe('fixExamplesByVersion method', function() {
fixedSchemaWithExample = concreteUtils.fixExamplesByVersion(providedSchema); fixedSchemaWithExample = concreteUtils.fixExamplesByVersion(providedSchema);
expect(JSON.stringify(fixedSchemaWithExample)).to.be.equal(JSON.stringify(expectedSchemaAfterFix)); expect(JSON.stringify(fixedSchemaWithExample)).to.be.equal(JSON.stringify(expectedSchemaAfterFix));
}); });
it('Should return example 123 when the types is an array with string and integer', function() {
const providedSchema = {
required: [
'id'
],
type: ['string', 'integer'],
examples: [123, 1234]
},
expectedSchemaAfterFix = {
required: [
'id'
],
type: 'integer',
examples: [123, 1234],
example: 123
},
fixedSchemaWithExample = concreteUtils.fixExamplesByVersion(providedSchema);
expect(JSON.stringify(fixedSchemaWithExample)).to.be.equal(JSON.stringify(expectedSchemaAfterFix));
});
it('Should return example "Not an Integer" and type integer when type and example dont match', function() {
const providedSchema = {
required: [
'id'
],
type: ['integer'],
examples: ['Not an Integer']
},
expectedSchemaAfterFix = {
required: [
'id'
],
type: 'integer',
examples: ['Not an Integer'],
example: 'Not an Integer'
},
fixedSchemaWithExample = concreteUtils.fixExamplesByVersion(providedSchema);
expect(JSON.stringify(fixedSchemaWithExample)).to.be.equal(JSON.stringify(expectedSchemaAfterFix));
});
it('Should return example "test" and type string when first example did not match any type', function() {
const providedSchema = {
required: [
'id'
],
type: ['string', 'integer'],
examples: [true, 'test']
},
expectedSchemaAfterFix = {
required: [
'id'
],
type: 'string',
examples: [true, 'test'],
example: 'test'
},
fixedSchemaWithExample = concreteUtils.fixExamplesByVersion(providedSchema);
expect(JSON.stringify(fixedSchemaWithExample)).to.be.equal(JSON.stringify(expectedSchemaAfterFix));
});
}); });
describe('isBinaryContentType method', function() { describe('isBinaryContentType method', function() {
@@ -605,3 +666,44 @@ describe('getOuterPropsIfIsSupported method', function() {
expect(JSON.stringify(resolvedSchema.required)).to.be.equal(JSON.stringify(expectedRequiredValue)); expect(JSON.stringify(resolvedSchema.required)).to.be.equal(JSON.stringify(expectedRequiredValue));
}); });
}); });
describe('findTypeByExample method', function () {
it('should return integer when the example is 123 and the types are string and integer', function () {
const result = concreteUtils.findTypeByExample([123], ['string', 'integer']);
expect(result.foundType).to.equal('integer');
expect(result.foundExample).to.equal(123);
});
it('should return number when the example is 123.5 and the types are string and integer', function () {
const result = concreteUtils.findTypeByExample([123.5], ['string', 'number']);
expect(result.foundType).to.equal('number');
expect(result.foundExample).to.equal(123.5);
});
it('should return string when the example is "123" and the types are integer and string', function () {
const result = concreteUtils.findTypeByExample(['123'], ['integer', 'string']);
expect(result.foundType).to.equal('string');
expect(result.foundExample).to.equal('123');
});
it('should return boolean when the example is true and the types are integer, string and boolean', function () {
const result = concreteUtils.findTypeByExample([true], ['integer', 'string', 'boolean']);
expect(result.foundType).to.equal('boolean');
expect(result.foundExample).to.equal(true);
});
it('should return string when the example is "true" and the types are integer, string and boolean', function () {
const result = concreteUtils.findTypeByExample(['true'], ['integer', 'string', 'boolean']);
expect(result.foundType).to.equal('string');
expect(result.foundExample).to.equal('true');
});
it('should return boolean when the examples are "true" and false and the types are integer and boolean', function () {
const result = concreteUtils.findTypeByExample(['true', false], ['integer', 'boolean']);
expect(result.foundType).to.equal('boolean');
expect(result.foundExample).to.equal(false);
});
});

View File

@@ -103,6 +103,22 @@ describe('Testing openapi 3.1 schema pack convert', function() {
.to.be.equal('{\n \"objectType\": 1234\n}'); .to.be.equal('{\n \"objectType\": 1234\n}');
}); });
}); });
it('Should convert a provided input with examples in schema and takes the first example in examples 2', function() {
const fileSource = path.join(__dirname, OPENAPI_31_FOLDER + '/simpleSchemaWithExamplesNotMachingType.yaml'),
fileData = fs.readFileSync(fileSource, 'utf8'),
input = {
type: 'string',
data: fileData
},
converter = new SchemaPack(input, { requestParametersResolution: 'Example' });
converter.convert((err, result) => {
expect(err).to.be.null;
expect(result.output[0].data.item[0].response[0].originalRequest.body.raw)
.to.be.equal('{\n \"id\": 1234\n}');
});
});
}); });