Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 65 additions & 12 deletions libV2/schemaUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1258,23 +1258,75 @@ let QUERYPARAM = 'query',
case 'form':
if (explode && _.isObject(paramValue)) {
const isArrayValue = _.isArray(paramValue);

_.forEach(paramValue, (value, key) => {
pmParams.push({
key: isArrayValue ? paramName : key,
value: (value === undefined ? '' : _.toString(value)),
description,
disabled
// Arrays
if (isArrayValue) {
_.forEach(paramValue, (value) => {
pmParams.push({
key: paramName,
value: (value === undefined ? '' : _.toString(value)),
description,
disabled
});
});
});
return pmParams;
}

return pmParams;
// Objects:
// If declared properties exist, include only declared properties.
// Else, exclude top-level schema keys.
const schemaProps = _.get(param, 'schema.properties');
const hasProps = _.isObject(schemaProps) && !_.isEmpty(schemaProps);
if (hasProps) {
_.forEach(paramValue, (value, key) => {
if (!_.has(schemaProps, key)) { return; }
pmParams.push({
key,
value: (value === undefined ? '' : _.toString(value)),
description,
disabled
});
});
}
else {
const schemaKeys = Object.keys(_.get(param, 'schema', {}));
_.forEach(paramValue, (value, key) => {
if (schemaKeys.includes(key)) { return; }
pmParams.push({
key,
value: (value === undefined ? '' : _.toString(value)),
description,
disabled
});
});
}
if (pmParams.length) {
return pmParams;
}
}

break;
case 'deepObject':
if (_.isObject(paramValue) && !_.isArray(paramValue)) {
let extractedParams = extractDeepObjectParams(paramValue, paramName);
let filteredValue;
const schemaProps = _.get(param, 'schema.properties');
const hasProps = _.isObject(schemaProps) && !_.isEmpty(schemaProps);
if (hasProps) {
filteredValue = _.pick(paramValue, Object.keys(schemaProps));
// Strip each declared property's own schema keys from its value before extraction
_.forEach(filteredValue, (propValue, propName) => {
if (_.isObject(propValue)) {
// taking only the keys that are declared in the schema
const propSchemaKeys = Object.keys(_.get(schemaProps, propName, {}));
filteredValue[propName] = _.omit(propValue, propSchemaKeys);
}
});
}
else {
const schemaKeys = Object.keys(_.get(param, 'schema', {}));
filteredValue = _.omit(paramValue, schemaKeys);
}

let extractedParams = extractDeepObjectParams(filteredValue, paramName);

_.forEach(extractedParams, (extractedParam) => {
pmParams.push({
Expand All @@ -1284,8 +1336,9 @@ let QUERYPARAM = 'query',
disabled
});
});

return pmParams;
if (pmParams.length) {
return pmParams;
}
}
else if (_.isArray(paramValue)) {
isNotSerializable = true;
Expand Down
112 changes: 112 additions & 0 deletions test/unit/convertV2WithTypes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,118 @@ describe('convertV2WithTypes', function() {
});
});

it('should not emit schema.deprecated as query param key for form+explode and keep original param', function(done) {
const oas = {
openapi: '3.0.0',
info: { title: 'Form Explode Deprecated Test', version: '1.0.0' },
paths: {
'/pets': {
get: {
parameters: [
{
name: 'qp',
in: 'query',
schema: { deprecated: true }
}
],
responses: { '200': { description: 'ok' } }
}
}
}
};

Converter.convertV2WithTypes({ type: 'json', data: oas }, {}, (err, conversionResult) => {
expect(err).to.be.null;
expect(conversionResult.result).to.equal(true);

const items = conversionResult.output[0].data.item;
const request = items[0].item ? items[0].item[0].request : items[0].request;
const query = request.url.query || [];

expect(query.some((p) => { return p.key === 'deprecated'; })).to.equal(false);
expect(query.some((p) => { return p.key === 'qp'; })).to.equal(true);
done();
});
});

it('should not emit qp[deprecated] for deepObject and keep original param', function(done) {
const oas = {
openapi: '3.0.0',
info: { title: 'DeepObject Deprecated Test', version: '1.0.0' },
paths: {
'/pets': {
get: {
parameters: [
{
name: 'qp',
in: 'query',
style: 'deepObject',
explode: true,
schema: { deprecated: true }
}
],
responses: { '200': { description: 'ok' } }
}
}
}
};

Converter.convertV2WithTypes({ type: 'json', data: oas }, {}, (err, conversionResult) => {
expect(err).to.be.null;
expect(conversionResult.result).to.equal(true);

const items = conversionResult.output[0].data.item;
const request = items[0].item ? items[0].item[0].request : items[0].request;
const query = request.url.query || [];

expect(query.some((p) => { return (/^qp\[deprecated\]/).test(p.key); })).to.equal(false);
expect(query.some((p) => { return p.key === 'qp'; })).to.equal(true);
done();
});
});

it('should include declared schema.properties (including keys like type) for form+explode', function(done) {
const oas = {
openapi: '3.0.0',
info: { title: 'Declared Properties Test', version: '1.0.0' },
paths: {
'/pets': {
get: {
parameters: [
{
name: 'qp',
in: 'query',
schema: {
type: 'object',
deprecated: true,
properties: {
name: { type: 'string' },
type: { type: 'string', deprecated: true }
}
}
}
],
responses: { '200': { description: 'ok' } }
}
}
}
};

Converter.convertV2WithTypes({ type: 'json', data: oas }, {}, (err, conversionResult) => {
expect(err).to.be.null;
expect(conversionResult.result).to.equal(true);

const items = conversionResult.output[0].data.item;
const request = items[0].item ? items[0].item[0].request : items[0].request;
const query = request.url.query || [];

expect(query.some((p) => { return p.key === 'name'; })).to.equal(true);
expect(query.some((p) => { return p.key === 'type'; })).to.equal(true);
expect(query.some((p) => { return p.key === 'deprecated'; })).to.equal(false);
done();
});
});

it('should resolve nested array and object schema types correctly in extractedTypes', function(done) {
const example = {
name: 'Buddy',
Expand Down
Loading