From b54b8fbef027c933c81acab87c20eb65af11e13c Mon Sep 17 00:00:00 2001 From: Ayush Shrivastav Date: Sun, 8 Dec 2024 18:19:28 +0530 Subject: [PATCH] AB-289-added tests and fixes --- libV2/index.js | 15 ++- libV2/schemaUtils.js | 17 ++- test/unit/convertV2.test.js | 2 +- test/unit/convertV2WithTypes.test.js | 158 +++++++++++++++++++++++++++ 4 files changed, 185 insertions(+), 7 deletions(-) create mode 100644 test/unit/convertV2WithTypes.test.js diff --git a/libV2/index.js b/libV2/index.js index 69736c5d..73193626 100644 --- a/libV2/index.js +++ b/libV2/index.js @@ -220,15 +220,24 @@ module.exports = { if (!_.isEmpty(collection.variable)) { collection.variable = _.uniqBy(collection.variable, 'key'); } - + if (context.enableTypeFetching) { + return cb(null, { + result: true, + output: [{ + type: 'collection', + data: collection + }], + analytics: this.analytics || {}, + extractedTypes: finalExtractedTypesList || [] + }); + } return cb(null, { result: true, output: [{ type: 'collection', data: collection }], - analytics: this.analytics || {}, - extractedTypes: context.enableTypeFetching ? finalExtractedTypesList : [] + analytics: this.analytics || {} }); }, diff --git a/libV2/schemaUtils.js b/libV2/schemaUtils.js index 28c6098f..cf892fe4 100644 --- a/libV2/schemaUtils.js +++ b/libV2/schemaUtils.js @@ -767,11 +767,24 @@ let QUERYPARAM = 'query', let res = processSchema(prop).properties; propertyDetails.properties = res; } + else if (prop.type === 'array' && prop.items) { + propertyDetails.items = processSchema(prop.items); + } schemaDetails.properties[key] = propertyDetails; } return schemaDetails; } + else if (resolvedSchema.type === 'array' && resolvedSchema.items) { + // Handle array type schema + const arrayDetails = { + type: resolvedSchema.type || 'unknown', + items: processSchema(resolvedSchema.items) + }; + if (resolvedSchema.minItems !== undefined) { arrayDetails.minItems = resolvedSchema.minItems; } + if (resolvedSchema.maxItems !== undefined) { arrayDetails.maxItems = resolvedSchema.maxItems; } + return arrayDetails; + } return { type: resolvedSchema.type || 'unknown' }; @@ -2615,10 +2628,8 @@ module.exports = { resolvedExampleTypes } = resolveResponseForPostmanRequest(context, operationItem[method], request); - methodPath = method + path; requestBlock = { request: unifiedRequestTypes, response: resolvedExampleTypes }; - requestObj = { [methodPath]: requestBlock }; - extractedTypesList.push(requestObj); + extractedTypesList.push(requestBlock); // add accept header if found and not present already if (!_.isEmpty(acceptHeader)) { diff --git a/test/unit/convertV2.test.js b/test/unit/convertV2.test.js index 985e3499..98038d10 100644 --- a/test/unit/convertV2.test.js +++ b/test/unit/convertV2.test.js @@ -205,9 +205,9 @@ describe('The convert v2 Function', function() { tooManyRefs, function(done) { var openapi = fs.readFileSync(tooManyRefs, 'utf8'); Converter.convertV2({ type: 'string', data: openapi }, { schemaFaker: true }, (err, conversionResult) => { - expect(err).to.be.null; expect(conversionResult.result).to.equal(true); + expect(conversionResult).to.not.have.property('extractedTypes'); expect(conversionResult.output.length).to.equal(1); expect(conversionResult.output[0].type).to.equal('collection'); expect(conversionResult.output[0].data).to.have.property('info'); diff --git a/test/unit/convertV2WithTypes.test.js b/test/unit/convertV2WithTypes.test.js new file mode 100644 index 00000000..c90a5c54 --- /dev/null +++ b/test/unit/convertV2WithTypes.test.js @@ -0,0 +1,158 @@ +/* eslint-disable one-var */ +const expect = require('chai').expect, + Converter = require('../../index.js'), + fs = require('fs'), + path = require('path'), + VALID_OPENAPI_PATH = '../data/valid_openapi', + Ajv = require('ajv'), + testSpec = path.join(__dirname, VALID_OPENAPI_PATH + '/test.json'), + testSpec1 = path.join(__dirname, VALID_OPENAPI_PATH + '/test1.json'), + readOnlyNestedSpec = + path.join(__dirname, VALID_OPENAPI_PATH, '/readOnlyNested.json'), + ajv = new Ajv({ allErrors: true, strict: false }), + transformSchema = (schema) => { + const properties = schema.properties, + rest = Object.keys(schema) + .filter((key) => { return key !== 'properties'; }) + .reduce((acc, key) => { + acc[key] = schema[key]; + return acc; + }, {}), + + transformedProperties = Object.entries(properties).reduce( + (acc, [key, value]) => { + acc[key] = { + type: value.type, + enum: value.enum !== null ? value.enum : undefined, + minLength: value.minLength !== null ? value.minLength : undefined, + maxLength: value.maxLength !== null ? value.maxLength : undefined, + minimum: value.minimum !== null ? value.minimum : undefined, + maximum: value.maximum !== null ? value.maximum : undefined, + pattern: value.pattern !== null ? value.pattern : undefined, + format: value.format !== null ? value.format : undefined + }; + return acc; + }, + {} + ), + + + transformedObject = Object.assign({}, rest, { properties: transformedProperties }); + + return transformedObject; + }; + + +describe('convertV2WithTypes should generate collection confirming to collection schema', function() { + + it('Should generate collection conforming to schema for and fail if not valid ' + + testSpec, function(done) { + var openapi = fs.readFileSync(testSpec, 'utf8'); + Converter.convertV2WithTypes({ type: 'string', data: openapi }, { schemaFaker: true }, (err, conversionResult) => { + expect(err).to.be.null; + expect(conversionResult.result).to.equal(true); + expect(conversionResult.output.length).to.equal(1); + expect(conversionResult.output[0].type).to.equal('collection'); + expect(conversionResult.output[0].data).to.have.property('info'); + expect(conversionResult.output[0].data).to.have.property('item'); + done(); + }); + }); + + it('Should generate collection conforming to schema for and fail if not valid ' + + testSpec1, function(done) { + Converter.convertV2WithTypes( + { type: 'file', data: testSpec1 }, { requestNameSource: 'url' }, (err, conversionResult) => { + expect(err).to.be.null; + expect(conversionResult.result).to.equal(true); + expect(conversionResult.output.length).to.equal(1); + expect(conversionResult.output[0].type).to.equal('collection'); + expect(conversionResult.output[0].data).to.have.property('info'); + expect(conversionResult.output[0].data).to.have.property('item'); + + done(); + }); + }); +}); + + +describe('convertV2WithTypes', function() { + it('should contain extracted types' + testSpec1, function () { + Converter.convertV2WithTypes( + { type: 'file', data: testSpec1 }, { requestNameSource: 'url' }, (err, conversionResult) => { + expect(err).to.be.null; + expect(conversionResult.result).to.equal(true); + expect(conversionResult.extractedTypes).to.not.be.undefined; + expect(conversionResult.extractedTypes.length).to.not.equal(0); + } + ); + }); + + it('should validate the schema' + testSpec1, function() { + const example = { + code: 200, + message: 'Success' + }; + Converter.convertV2WithTypes( + { type: 'file', data: testSpec1 }, { requestNameSource: 'url' }, (err, conversionResult) => { + + expect(err).to.be.null; + expect(conversionResult.extractedTypes).to.be.an('array').that.is.not.empty; + const element = conversionResult.extractedTypes[0]; + + expect(element).to.be.an('object').that.includes.keys('request'); + expect(element).to.be.an('object').that.includes.keys('response'); + const { response } = element; + expect(response).to.be.an('object').that.is.not.empty; + const [key, value] = Object.entries(response)[1]; + expect(key).to.be.a('string'); + const schema = JSON.parse(value.body), + transformedSchema = transformSchema(schema), + validate = ajv.compile(transformedSchema), + valid = validate(example); + + expect(value).to.have.property('body').that.is.a('string'); + + + expect(valid, `Validation failed for key: ${key} with errors: ${JSON.stringify(validate.errors)}`).to.be.true; + }); + }); + + it('should resolve nested array and object schema types correctly in extractedTypes', function(done) { + const example = { + name: 'Buddy', + pet: { + id: 123, + name: 'Charlie', + address: { + addressCode: { + code: 'A123' + }, + city: 'New York' + } + } + }, + openapi = fs.readFileSync(readOnlyNestedSpec, 'utf8'), + options = { schemaFaker: true, exampleParametersResolution: 'schema' }; + + Converter.convertV2WithTypes({ type: 'string', data: openapi }, options, (err, conversionResult) => { + expect(err).to.be.null; + expect(conversionResult.extractedTypes).to.be.an('array').that.is.not.empty; + + // Validate the first extracted type + const element = conversionResult.extractedTypes[0]; + const { response } = element; + + // Get the schema from the response + const [key, value] = Object.entries(response)[0]; + expect(value).to.have.property('body').that.is.a('string'); + + const schema = JSON.parse(value.body), + transformedSchema = transformSchema(schema), + validate = ajv.compile(transformedSchema), + valid = validate(example); + expect(valid, `Validation failed for key: ${key} with errors: ${JSON.stringify(validate.errors)}`).to.be.true; + done(); + }); + }); +});