diff --git a/packages/oas/src/utils/params.ts b/packages/oas/src/utils/params.ts index 2b67cb0f..b53891d2 100644 --- a/packages/oas/src/utils/params.ts +++ b/packages/oas/src/utils/params.ts @@ -1,17 +1,32 @@ -import type { ParameterObject } from '../types'; +import { ParameterObject } from '../types'; import { getOperation } from './operation'; -import type { OpenAPI } from '@har-sdk/core'; +import { OpenAPI } from '@har-sdk/core'; + +const assertDereferencedParam = (param: unknown): param is ParameterObject => { + const isReference = !!param && typeof param === 'object' && '$ref' in param; + + 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 pathObj = getOperation(spec, path, method); + const params = [ + ...(spec.paths[path]?.parameters ?? []), + ...(getOperation(spec, path, method)?.parameters ?? []) + ].filter(assertDereferencedParam); + + const combinedParams = new Map( + params.map((x) => [`${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..61bc213d --- /dev/null +++ b/packages/oas/tests/fixtures/path-item.params.resolution.oas.result.json @@ -0,0 +1,12 @@ +[ + { + "bodySize": 0, + "cookies": [], + "headers": [], + "headersSize": 0, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [], + "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 new file mode 100644 index 00000000..db36e9b6 --- /dev/null +++ b/packages/oas/tests/fixtures/path-item.params.resolution.oas.yaml @@ -0,0 +1,38 @@ +openapi: 3.0.3 +info: + title: users/{id} + version: '1.0' +servers: + - url: https://brokencrystals.com +paths: + /org/{orgId}/users/{userId}/devices/{deviceId}: + parameters: + - $ref: '#/components/parameters/orgId' + - in: path + name: userId + required: true + schema: + type: string + get: + parameters: + - in: path + name: userId + required: true + schema: + type: number + - in: path + name: deviceId + required: true + schema: + type: number + responses: + '200': + description: '' +components: + parameters: + orgId: + in: path + name: orgId + required: true + schema: + type: string