Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: oas2 collectionFormat when not 'multi' #1550

Merged
merged 1 commit into from
May 28, 2020
Merged
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
14 changes: 11 additions & 3 deletions src/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import qs from 'qs'
import jsYaml from 'js-yaml'
import isString from 'lodash/isString'
import isFunction from 'lodash/isFunction'
import isNil from 'lodash/isNil'
import FormData from './internal/form-data-monkey-patch'

// For testing
Expand Down Expand Up @@ -182,9 +183,16 @@ function formatValue(input, skipEncoding) {
}

let encodeFn = encodeURIComponent
// skipEncoding is an option to skip using the encodeURIComponent
// and allow reassignment to a different "encoding" function
// we should only use encodeURIComponent for known url strings
if (skipEncoding) {
if (isString(value)) encodeFn = str => str
else encodeFn = obj => JSON.stringify(obj)
if (isString(value) || Array.isArray(value)) {
encodeFn = str => str
}
else {
encodeFn = obj => JSON.stringify(obj)
}
}

if (typeof value === 'object' && !Array.isArray(value)) {
Expand Down Expand Up @@ -214,7 +222,7 @@ function buildFormData(reqForm) {
* @return {FormData} - new FormData instance
*/
return Object.entries(reqForm).reduce((formData, [name, input]) => {
if (!input.collectionFormat && !input.isOAS3formatArray) {
if ((isNil(input.collectionFormat) || input.collectionFormat !== 'multi') && !input.isOAS3formatArray) {
formData.append(name, formatValue(input, true))
}
else {
Expand Down
52 changes: 51 additions & 1 deletion test/data/sample-multipart-oas2.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,62 @@ export default {
{
in: 'formData',
name: 'email[]',
description: 'The list of emails.',
description: 'The list of emails as multi.',
type: 'array',
collectionFormat: 'multi',
items: {
type: 'string'
}
},
{
in: 'formData',
name: 'none[]',
description: 'The list of emails as none.',
type: 'array',
collectionFormat: 'none',
items: {
type: 'string'
}
},
{
in: 'formData',
name: 'csv[]',
description: 'The list of emails as csv.',
type: 'array',
collectionFormat: 'csv',
items: {
type: 'string'
}
},
{
in: 'formData',
name: 'tsv[]',
description: 'The list of emails as tsv.',
type: 'array',
collectionFormat: 'tsv',
items: {
type: 'string'
}
},
{
in: 'formData',
name: 'ssv[]',
description: 'The list of emails as ssv.',
type: 'array',
collectionFormat: 'ssv',
items: {
type: 'string'
}
},
{
in: 'formData',
name: 'pipes[]',
description: 'The list of emails as pipes.',
type: 'array',
collectionFormat: 'pipes',
items: {
type: 'string'
}
}
],
responses: {
Expand Down
54 changes: 51 additions & 3 deletions test/http-multipart.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,16 @@ describe('buildRequest - openapi 2.0', () => {
parameters: {
'formData.hhlContent:sort': 'id',
'formData.hhlContent:order': 'desc',
'formData.email[]': ["person1", "person2"] // eslint-disable-line quotes
'formData.email[]': ["person1", "person2"], // eslint-disable-line quotes
'formData.none[]': ['foo', 'bar'],
'formData.csv[]': ['foo', 'bar'],
'formData.tsv[]': ['foo', 'bar'],
'formData.ssv[]': ['foo', 'bar'],
'formData.pipes[]': ['foo', 'bar'],
}
})

test('should return FormData entry list and entry item entries (in order)', () => {
test('should return appropriate response media type', () => {
expect(req).toMatchObject({
method: 'POST',
url: '/api/v1/land/content/ViewOfAuthOwner',
Expand All @@ -36,14 +41,50 @@ describe('buildRequest - openapi 2.0', () => {
'Content-Type': 'multipart/form-data'
},
})
})

test('should build request body as FormData', () => {
const validateFormDataInstance = req.body instanceof FormData
expect(validateFormDataInstance).toEqual(true)
})

test('should return "collectionFormat: multi" as FormData entry list and entry item entries (in order)', () => {
const itemEntries = req.body.getAll('email[]')
expect(itemEntries.length).toEqual(2)
expect(itemEntries[0]).toEqual('person1')
expect(itemEntries[1]).toEqual('person2')
})

test('should return "collectionFormat: none" as single FormData entry in csv format', () => {
const itemEntriesNone = req.body.getAll('none[]')
expect(itemEntriesNone.length).toEqual(1)
expect(itemEntriesNone[0]).toEqual('foo,bar')
})

test('should return "collectionFormat: csv" as single FormData entry in csv format', () => {
const itemEntriesCsv = req.body.getAll('csv[]')
expect(itemEntriesCsv.length).toEqual(1)
expect(itemEntriesCsv[0]).toEqual('foo,bar')
})

test('should return "collectionFormat: tsv" as single FormData entry in tsv format', () => {
const itemEntriesTsv = req.body.getAll('tsv[]')
expect(itemEntriesTsv.length).toEqual(1)
expect(itemEntriesTsv[0]).toEqual('foo%09bar')
})

test('should return "collectionFormat: ssv" as single FormData entry in ssv format', () => {
const itemEntriesSsv = req.body.getAll('ssv[]')
expect(itemEntriesSsv.length).toEqual(1)
expect(itemEntriesSsv[0]).toEqual('foo%20bar')
})

test('should return "collectionFormat: pipes" as single FormData entry in pipes format', () => {
const itemEntriesPipes = req.body.getAll('pipes[]')
expect(itemEntriesPipes.length).toEqual(1)
expect(itemEntriesPipes[0]).toEqual('foo|bar')
})

/**
* Dev test only: assumes local server exists for POST
* Expect server response format: { message: 'ok', data: returnData }
Expand Down Expand Up @@ -113,7 +154,7 @@ describe('buildRequest - openapi 3.0', () => {
}
})

test('should return FormData entry list and item entries (in order)', () => {
test('should return appropriate response media type', () => {
expect(req).toMatchObject({
method: 'POST',
url: '/api/v1/land/content/ViewOfAuthOwner',
Expand All @@ -122,13 +163,20 @@ describe('buildRequest - openapi 3.0', () => {
'Content-Type': 'multipart/form-data'
},
})
})

test('should build request body as FormData', () => {
const validateFormDataInstance = req.body instanceof FormData
expect(validateFormDataInstance).toEqual(true)
})

test('should return FormData entry list and item entries (in order)', () => {
const itemEntries = req.body.getAll('email[]')
expect(itemEntries.length).toEqual(2)
expect(itemEntries[0]).toEqual('person1')
expect(itemEntries[1]).toEqual('person2')
})

/**
* Dev test only: assumes local server exists for POST
* Expect server response format: { message: 'ok', data: returnData }
Expand Down