From d7411ba022c2c1de466b908fcce6f0f76683c806 Mon Sep 17 00:00:00 2001 From: Dmitry Ostrikov Date: Wed, 21 Aug 2024 18:15:46 +0300 Subject: [PATCH 1/4] fix(oas): combine `PathItemObject` and `OperationObject` parameters fixes #248 --- packages/oas/src/utils/params.ts | 20 ++++-- packages/oas/tests/DefaultConverter.spec.ts | 14 +++++ ...ath-item.params.resolution.oas.result.json | 63 +++++++++++++++++++ .../path-item.params.resolution.oas.yaml | 47 ++++++++++++++ 4 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json create mode 100644 packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml diff --git a/packages/oas/src/utils/params.ts b/packages/oas/src/utils/params.ts index 2b67cb0f..24a6b1a5 100644 --- a/packages/oas/src/utils/params.ts +++ b/packages/oas/src/utils/params.ts @@ -1,17 +1,27 @@ import type { ParameterObject } from '../types'; -import { getOperation } from './operation'; import type { OpenAPI } from '@har-sdk/core'; +const isParameter = (param: unknown): param is ParameterObject => + param && typeof param === 'object' && 'in' in param && 'name' in param; + +const toParameters = (param: unknown): ParameterObject[] => + Array.isArray(param) ? param.filter(isParameter) : []; + export const getParameters = ( spec: OpenAPI.Document, path: string, method: string ): ParameterObject[] => { - const pathObj = getOperation(spec, path, method); + const pathParams = toParameters(spec.paths[path]?.parameters); + const operationParams = toParameters(spec.paths[path]?.[method]?.parameters); + + const combinedParams = new Map( + pathParams.map((x) => [`${x.in}:${x.name}`, x]) + ); + + operationParams.forEach((x) => combinedParams.set(`${x.in}:${x.name}`, x)); - return Array.isArray(pathObj.parameters) - ? (pathObj.parameters as ParameterObject[]) - : []; + return [...combinedParams.values()]; }; export const filterLocationParams = ( diff --git a/packages/oas/tests/DefaultConverter.spec.ts b/packages/oas/tests/DefaultConverter.spec.ts index cc5bd5fd..f0bcecfb 100644 --- a/packages/oas/tests/DefaultConverter.spec.ts +++ b/packages/oas/tests/DefaultConverter.spec.ts @@ -398,5 +398,19 @@ describe('DefaultConverter', () => { // assert expect(result).toStrictEqual(expectedDoc); }); + + it('should correctly resolve path-item parameters', async () => { + // arrange + const { inputDoc, expectedDoc } = await createFixture({ + inputFile: `./fixtures/path-item.params.resolution.oas.yaml`, + expectedFile: `./fixtures/path-item.params.resolution.oas.result.json` + }); + + // act + const result: Request[] = await oas2har(inputDoc as any); + + // assert + expect(result).toStrictEqual(expectedDoc); + }); }); }); diff --git a/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json b/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json new file mode 100644 index 00000000..babb54e6 --- /dev/null +++ b/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json @@ -0,0 +1,63 @@ +[ + { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 0, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [ + { + "name": "lat", + "value": "42" + }, + { + "name": "lng", + "value": "42" + } + ], + "url": "https://brokencrystals.com/locations?lat=42&lng=42" + }, + { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 0, + "httpVersion": "HTTP/1.1", + "method": "POST", + "queryString": [ + { + "name": "lat", + "value": "lorem" + }, + { + "name": "lng", + "value": "lorem" + } + ], + "url": "https://brokencrystals.com/locations?lat=lorem&lng=lorem" + }, + { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 0, + "httpVersion": "HTTP/1.1", + "method": "PUT", + "queryString": [ + { + "name": "lat", + "value": "42" + }, + { + "name": "lng", + "value": "42" + }, + { + "name": "type", + "value": "lorem" + } + ], + "url": "https://brokencrystals.com/locations?lat=42&lng=42&type=lorem" + } +] \ No newline at end of file diff --git a/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml b/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml new file mode 100644 index 00000000..1d166024 --- /dev/null +++ b/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml @@ -0,0 +1,47 @@ +openapi: 3.0.3 +info: + title: locations + version: '1.0' +servers: + - url: https://brokencrystals.com +paths: + /locations: + parameters: + - in: query + name: lat + schema: + type: number + - in: query + name: lng + schema: + type: number + get: + responses: + '200': + description: '' + post: + parameters: + - in: query + name: lat + schema: + type: string + - in: query + name: lng + schema: + type: string + - in: path + name: lng + schema: + type: integer + responses: + '200': + description: '' + put: + parameters: + - in: query + name: type + schema: + type: string + responses: + '200': + description: '' From 8af7727ee2cbad5a51d71f9660a1f4fbcf4ea97a Mon Sep 17 00:00:00 2001 From: Dmitry Ostrikov Date: Wed, 21 Aug 2024 18:21:17 +0300 Subject: [PATCH 2/4] fix(oas): fix formatting fixes #248 --- .../tests/fixtures/path-item.params.resolution.oas.result.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json b/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json index babb54e6..32b8bec3 100644 --- a/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json +++ b/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json @@ -60,4 +60,4 @@ ], "url": "https://brokencrystals.com/locations?lat=42&lng=42&type=lorem" } -] \ No newline at end of file +] From 7d8d8d49b1aac61b73b7288a30025b274641c5c3 Mon Sep 17 00:00:00 2001 From: Dmitry Ostrikov Date: Thu, 22 Aug 2024 10:53:13 +0300 Subject: [PATCH 3/4] fix(oas): address review comments fixes #248 --- packages/oas/src/utils/params.ts | 25 +++++++---- ...ath-item.params.resolution.oas.result.json | 43 +++---------------- .../path-item.params.resolution.oas.yaml | 39 ++++++++--------- 3 files changed, 40 insertions(+), 67 deletions(-) diff --git a/packages/oas/src/utils/params.ts b/packages/oas/src/utils/params.ts index 24a6b1a5..9b2fd2b4 100644 --- a/packages/oas/src/utils/params.ts +++ b/packages/oas/src/utils/params.ts @@ -1,19 +1,28 @@ -import type { ParameterObject } from '../types'; -import type { OpenAPI } from '@har-sdk/core'; +import { ParameterObject } from '../types'; +import { getOperation } from './operation'; +import { OpenAPI } from '@har-sdk/core'; -const isParameter = (param: unknown): param is ParameterObject => - param && typeof param === 'object' && 'in' in param && 'name' in param; +const assertDereferencedParam = (param: unknown): param is ParameterObject => { + const isReference = !!param && typeof param === 'object' && '$ref' in param; -const toParameters = (param: unknown): ParameterObject[] => - Array.isArray(param) ? param.filter(isParameter) : []; + if (isReference) { + throw new Error('Specification document is expected to be dereferenced.'); + } + + return !isReference; +}; export const getParameters = ( spec: OpenAPI.Document, path: string, method: string ): ParameterObject[] => { - const pathParams = toParameters(spec.paths[path]?.parameters); - const operationParams = toParameters(spec.paths[path]?.[method]?.parameters); + const pathParams = [...(spec.paths[path]?.parameters ?? [])].filter( + assertDereferencedParam + ); + const operationParams = [ + ...(getOperation(spec, path, method)?.parameters ?? []) + ].filter(assertDereferencedParam); const combinedParams = new Map( pathParams.map((x) => [`${x.in}:${x.name}`, x]) diff --git a/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json b/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json index 32b8bec3..94d4609f 100644 --- a/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json +++ b/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json @@ -6,17 +6,8 @@ "headersSize": 0, "httpVersion": "HTTP/1.1", "method": "GET", - "queryString": [ - { - "name": "lat", - "value": "42" - }, - { - "name": "lng", - "value": "42" - } - ], - "url": "https://brokencrystals.com/locations?lat=42&lng=42" + "queryString": [], + "url": "https://brokencrystals.com/users/42" }, { "bodySize": 0, @@ -25,17 +16,8 @@ "headersSize": 0, "httpVersion": "HTTP/1.1", "method": "POST", - "queryString": [ - { - "name": "lat", - "value": "lorem" - }, - { - "name": "lng", - "value": "lorem" - } - ], - "url": "https://brokencrystals.com/locations?lat=lorem&lng=lorem" + "queryString": [], + "url": "https://brokencrystals.com/users/lorem" }, { "bodySize": 0, @@ -44,20 +26,7 @@ "headersSize": 0, "httpVersion": "HTTP/1.1", "method": "PUT", - "queryString": [ - { - "name": "lat", - "value": "42" - }, - { - "name": "lng", - "value": "42" - }, - { - "name": "type", - "value": "lorem" - } - ], - "url": "https://brokencrystals.com/locations?lat=42&lng=42&type=lorem" + "queryString": [], + "url": "https://brokencrystals.com/users/lorem" } ] diff --git a/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml b/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml index 1d166024..281a3796 100644 --- a/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml +++ b/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml @@ -1,18 +1,15 @@ openapi: 3.0.3 info: - title: locations + title: users/{id} version: '1.0' servers: - url: https://brokencrystals.com paths: - /locations: + /users/{id}: parameters: - - in: query - name: lat - schema: - type: number - - in: query - name: lng + - in: path + name: id + required: true schema: type: number get: @@ -21,27 +18,25 @@ paths: description: '' post: parameters: - - in: query - name: lat - schema: - type: string - - in: query - name: lng - schema: - type: string - in: path - name: lng + name: id + required: true schema: - type: integer + type: string responses: '200': description: '' put: parameters: - - in: query - name: type - schema: - type: string + - $ref: '#/components/parameters/userid' responses: '200': description: '' +components: + parameters: + userid: + in: path + name: id + required: true + schema: + type: string From f95f1f2152d1eb03d99057bf19a8e69a9fea6cec Mon Sep 17 00:00:00 2001 From: Dmitry Ostrikov Date: Thu, 22 Aug 2024 12:09:06 +0300 Subject: [PATCH 4/4] fix(oas): address review comments fixes #248 --- packages/oas/src/utils/params.ts | 10 ++----- ...ath-item.params.resolution.oas.result.json | 22 +------------- .../path-item.params.resolution.oas.yaml | 30 ++++++++----------- 3 files changed, 17 insertions(+), 45 deletions(-) diff --git a/packages/oas/src/utils/params.ts b/packages/oas/src/utils/params.ts index 9b2fd2b4..b53891d2 100644 --- a/packages/oas/src/utils/params.ts +++ b/packages/oas/src/utils/params.ts @@ -17,19 +17,15 @@ export const getParameters = ( path: string, method: string ): ParameterObject[] => { - const pathParams = [...(spec.paths[path]?.parameters ?? [])].filter( - assertDereferencedParam - ); - const operationParams = [ + const params = [ + ...(spec.paths[path]?.parameters ?? []), ...(getOperation(spec, path, method)?.parameters ?? []) ].filter(assertDereferencedParam); const combinedParams = new Map( - pathParams.map((x) => [`${x.in}:${x.name}`, x]) + params.map((x) => [`${x.in}:${x.name}`, x]) ); - operationParams.forEach((x) => combinedParams.set(`${x.in}:${x.name}`, x)); - return [...combinedParams.values()]; }; diff --git a/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json b/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json index 94d4609f..61bc213d 100644 --- a/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json +++ b/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json @@ -7,26 +7,6 @@ "httpVersion": "HTTP/1.1", "method": "GET", "queryString": [], - "url": "https://brokencrystals.com/users/42" - }, - { - "bodySize": 0, - "cookies": [], - "headers": [], - "headersSize": 0, - "httpVersion": "HTTP/1.1", - "method": "POST", - "queryString": [], - "url": "https://brokencrystals.com/users/lorem" - }, - { - "bodySize": 0, - "cookies": [], - "headers": [], - "headersSize": 0, - "httpVersion": "HTTP/1.1", - "method": "PUT", - "queryString": [], - "url": "https://brokencrystals.com/users/lorem" + "url": "https://brokencrystals.com/org/lorem/users/42/devices/42" } ] diff --git a/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml b/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml index 281a3796..db36e9b6 100644 --- a/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml +++ b/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml @@ -5,38 +5,34 @@ info: servers: - url: https://brokencrystals.com paths: - /users/{id}: + /org/{orgId}/users/{userId}/devices/{deviceId}: parameters: + - $ref: '#/components/parameters/orgId' - in: path - name: id + name: userId required: true schema: - type: number + type: string get: - responses: - '200': - description: '' - post: parameters: - in: path - name: id + name: userId required: true schema: - type: string - responses: - '200': - description: '' - put: - parameters: - - $ref: '#/components/parameters/userid' + type: number + - in: path + name: deviceId + required: true + schema: + type: number responses: '200': description: '' components: parameters: - userid: + orgId: in: path - name: id + name: orgId required: true schema: type: string