diff --git a/packages/fury-adapter-oas3-parser/CHANGELOG.md b/packages/fury-adapter-oas3-parser/CHANGELOG.md index 1110fd1ec..c9bab9b86 100644 --- a/packages/fury-adapter-oas3-parser/CHANGELOG.md +++ b/packages/fury-adapter-oas3-parser/CHANGELOG.md @@ -1,5 +1,13 @@ # Fury OAS3 Parser Changelog +## Master + +### Bug Fixes + +- Prevents an exception being raised when using `freeze()` on the parse result + returned by the parser when you reference a parameter component multiple + times in an OpenAPI Document. + ## 0.7.4 (2019-04-12) ### Enhancements diff --git a/packages/fury-adapter-oas3-parser/lib/parser/oas/parseOperationObject.js b/packages/fury-adapter-oas3-parser/lib/parser/oas/parseOperationObject.js index 08240ef74..0dca766c3 100644 --- a/packages/fury-adapter-oas3-parser/lib/parser/oas/parseOperationObject.js +++ b/packages/fury-adapter-oas3-parser/lib/parser/oas/parseOperationObject.js @@ -156,7 +156,7 @@ function parseOperationObject(context, path, member) { R.reject(member => !headers.include(member.key.toValue()).isEmpty, headerParameters.content) ); - request.headers = headers; + request.headers = headers.clone(); }); } } diff --git a/packages/fury-adapter-oas3-parser/lib/parser/oas/parseParameterObjects.js b/packages/fury-adapter-oas3-parser/lib/parser/oas/parseParameterObjects.js index 2e7665266..069af55c5 100644 --- a/packages/fury-adapter-oas3-parser/lib/parser/oas/parseParameterObjects.js +++ b/packages/fury-adapter-oas3-parser/lib/parser/oas/parseParameterObjects.js @@ -29,9 +29,9 @@ function parseParameterObjects(context, name, array) { // Convert an array of parameters into the correct types const convertParameters = R.cond([ - [isPathOrQuery, member => new namespace.elements.HrefVariables(member.value.content)], + [isPathOrQuery, member => new namespace.elements.HrefVariables(member.value.clone().content)], // FIXME when headers and cookies are supported these should be converted - [R.T, member => member], + [R.T, member => member.clone()], ]); const parseParameters = pipeParseResult(namespace, diff --git a/packages/fury-adapter-oas3-parser/test/integration/components-test.js b/packages/fury-adapter-oas3-parser/test/integration/components-test.js index deebb03f0..269ca4948 100644 --- a/packages/fury-adapter-oas3-parser/test/integration/components-test.js +++ b/packages/fury-adapter-oas3-parser/test/integration/components-test.js @@ -4,44 +4,72 @@ const testParseFixture = require('./testParseFixture'); const fixtures = path.join(__dirname, 'fixtures', 'components'); describe('components', () => { - it("'Path Item Object' parameter references", () => { - const file = path.join(fixtures, 'path-item-object-parameters'); - return testParseFixture(file); - }); + describe('Path Item Object', () => { + it('handles parameter references', () => { + const file = path.join(fixtures, 'path-item-object-parameters'); + return testParseFixture(file); + }); - it("'Path Item Object' parameter referencing unsupported parameter", () => { - const file = path.join(fixtures, 'path-item-object-parameters-unsupported-parameter'); - return testParseFixture(file); - }); + it('handles multiple references to same parameter', () => { + const file = path.join(fixtures, 'path-item-object-parameters-multiple'); + return testParseFixture(file); + }); - it("'Media Type Object' schema references", () => { - const file = path.join(fixtures, 'media-type-object-schema'); - return testParseFixture(file); + it('handles parameter referencing unsupported parameter', () => { + const file = path.join(fixtures, 'path-item-object-parameters-unsupported-parameter'); + return testParseFixture(file); + }); }); - it("'Media Type Object' examples references", () => { - const file = path.join(fixtures, 'media-type-object-examples'); - return testParseFixture(file); - }); + describe('Media Type Object', () => { + it('handles schema references', () => { + const file = path.join(fixtures, 'media-type-object-schema'); + return testParseFixture(file); + }); - it("'Responses Object' response references", () => { - const file = path.join(fixtures, 'responses-object-response'); - return testParseFixture(file); - }); + it('handles multiple references to same schema', () => { + const file = path.join(fixtures, 'media-type-object-schema-multiple'); + return testParseFixture(file); + }); - it("'Responses Object' response references with schema", () => { - const file = path.join(fixtures, 'responses-object-response-with-schema'); - return testParseFixture(file); + it('handles examples references', () => { + const file = path.join(fixtures, 'media-type-object-examples'); + return testParseFixture(file); + }); }); - it("'Responses Object' respomnse references with headers", () => { - const file = path.join(fixtures, 'responses-object-response-with-headers'); - return testParseFixture(file); + describe('Responses Object', () => { + it('handles response references', () => { + const file = path.join(fixtures, 'responses-object-response'); + return testParseFixture(file); + }); + + it('handles multiple references to same response', () => { + const file = path.join(fixtures, 'responses-object-response-multiple'); + return testParseFixture(file); + }); + + it('handles response references with schema', () => { + const file = path.join(fixtures, 'responses-object-response-with-schema'); + return testParseFixture(file); + }); + + it('handles responses references with headers', () => { + const file = path.join(fixtures, 'responses-object-response-with-headers'); + return testParseFixture(file); + }); }); - it("'Response Object' headers references", () => { - const file = path.join(fixtures, 'response-object-headers'); - return testParseFixture(file); + describe('Response Object', () => { + it('handles headers references', () => { + const file = path.join(fixtures, 'response-object-headers'); + return testParseFixture(file); + }); + + it('handles multiple references to same header', () => { + const file = path.join(fixtures, 'response-object-headers-multiple'); + return testParseFixture(file); + }); }); it("'Schema Object' circular references", () => { diff --git a/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/media-type-object-schema-multiple.json b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/media-type-object-schema-multiple.json new file mode 100644 index 000000000..6f693ab71 --- /dev/null +++ b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/media-type-object-schema-multiple.json @@ -0,0 +1,272 @@ +{ + "element": "parseResult", + "content": [ + { + "element": "category", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "api" + } + ] + }, + "title": { + "element": "string", + "content": "Schemas Components" + } + }, + "attributes": { + "version": { + "element": "string", + "content": "1.0.0" + } + }, + "content": [ + { + "element": "resource", + "attributes": { + "href": { + "element": "string", + "content": "/user" + } + }, + "content": [ + { + "element": "transition", + "meta": { + "title": { + "element": "string", + "content": "View the current User" + } + }, + "content": [ + { + "element": "httpTransaction", + "content": [ + { + "element": "httpRequest", + "attributes": { + "method": { + "element": "string", + "content": "GET" + } + } + }, + { + "element": "httpResponse", + "attributes": { + "headers": { + "element": "httpHeaders", + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "Content-Type" + }, + "value": { + "element": "string", + "content": "application/json" + } + } + } + ] + }, + "statusCode": { + "element": "string", + "content": "200" + } + }, + "content": [ + { + "element": "asset", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "messageBody" + } + ] + } + }, + "attributes": { + "contentType": { + "element": "string", + "content": "application/json" + } + }, + "content": "{\"name\":\"\",\"company\":{\"name\":\"\"}}" + }, + { + "element": "dataStructure", + "content": { + "element": "User" + } + }, + { + "element": "copy", + "content": "A user" + } + ] + } + ] + }, + { + "element": "httpTransaction", + "content": [ + { + "element": "httpRequest", + "attributes": { + "method": { + "element": "string", + "content": "GET" + } + } + }, + { + "element": "httpResponse", + "attributes": { + "headers": { + "element": "httpHeaders", + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "Content-Type" + }, + "value": { + "element": "string", + "content": "application/yaml" + } + } + } + ] + }, + "statusCode": { + "element": "string", + "content": "200" + } + }, + "content": [ + { + "element": "dataStructure", + "content": { + "element": "User" + } + }, + { + "element": "copy", + "content": "A user" + } + ] + } + ] + } + ] + } + ] + }, + { + "element": "category", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "dataStructures" + } + ] + } + }, + "content": [ + { + "element": "dataStructure", + "content": { + "element": "object", + "meta": { + "id": { + "element": "string", + "content": "User" + } + }, + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "name" + }, + "value": { + "element": "name" + } + } + }, + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "company" + }, + "value": { + "element": "Company" + } + } + } + ] + } + }, + { + "element": "dataStructure", + "content": { + "element": "object", + "meta": { + "id": { + "element": "string", + "content": "Company" + } + }, + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "name" + }, + "value": { + "element": "name" + } + } + } + ] + } + }, + { + "element": "dataStructure", + "content": { + "element": "string", + "meta": { + "id": { + "element": "string", + "content": "name" + } + } + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/media-type-object-schema-multiple.yaml b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/media-type-object-schema-multiple.yaml new file mode 100644 index 000000000..a6804f238 --- /dev/null +++ b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/media-type-object-schema-multiple.yaml @@ -0,0 +1,34 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Schemas Components +paths: + /user: + get: + summary: View the current User + responses: + '200': + description: A user + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/yaml: + schema: + $ref: '#/components/schemas/User' +components: + schemas: + User: + type: object + properties: + name: + $ref: '#/components/schemas/name' + company: + $ref: '#/components/schemas/Company' + Company: + type: object + properties: + name: + $ref: '#/components/schemas/name' + name: + type: string diff --git a/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/path-item-object-parameters-multiple.json b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/path-item-object-parameters-multiple.json new file mode 100644 index 000000000..18b37e317 --- /dev/null +++ b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/path-item-object-parameters-multiple.json @@ -0,0 +1,247 @@ +{ + "element": "parseResult", + "content": [ + { + "element": "category", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "api" + } + ] + }, + "title": { + "element": "string", + "content": "Parameter Components" + } + }, + "attributes": { + "version": { + "element": "string", + "content": "1.0.0" + } + }, + "content": [ + { + "element": "resource", + "attributes": { + "href": { + "element": "string", + "content": "/1{?skip,limit}" + }, + "hrefVariables": { + "element": "hrefVariables", + "content": [ + { + "element": "member", + "meta": { + "description": { + "element": "string", + "content": "number of items to skip" + } + }, + "attributes": { + "typeAttributes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "required" + } + ] + } + }, + "content": { + "key": { + "element": "string", + "content": "skip" + } + } + }, + { + "element": "member", + "meta": { + "description": { + "element": "string", + "content": "max records to return" + } + }, + "attributes": { + "typeAttributes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "required" + } + ] + } + }, + "content": { + "key": { + "element": "string", + "content": "limit" + } + } + } + ] + } + }, + "content": [ + { + "element": "transition", + "meta": { + "title": { + "element": "string", + "content": "List all pets" + } + }, + "content": [ + { + "element": "httpTransaction", + "content": [ + { + "element": "httpRequest", + "attributes": { + "method": { + "element": "string", + "content": "GET" + } + } + }, + { + "element": "httpResponse", + "attributes": { + "statusCode": { + "element": "string", + "content": "204" + } + }, + "content": [ + { + "element": "copy", + "content": "no content" + } + ] + } + ] + } + ] + } + ] + }, + { + "element": "resource", + "attributes": { + "href": { + "element": "string", + "content": "/2{?skip,limit}" + }, + "hrefVariables": { + "element": "hrefVariables", + "content": [ + { + "element": "member", + "meta": { + "description": { + "element": "string", + "content": "number of items to skip" + } + }, + "attributes": { + "typeAttributes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "required" + } + ] + } + }, + "content": { + "key": { + "element": "string", + "content": "skip" + } + } + }, + { + "element": "member", + "meta": { + "description": { + "element": "string", + "content": "max records to return" + } + }, + "attributes": { + "typeAttributes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "required" + } + ] + } + }, + "content": { + "key": { + "element": "string", + "content": "limit" + } + } + } + ] + } + }, + "content": [ + { + "element": "transition", + "meta": { + "title": { + "element": "string", + "content": "retrieve" + } + }, + "content": [ + { + "element": "httpTransaction", + "content": [ + { + "element": "httpRequest", + "attributes": { + "method": { + "element": "string", + "content": "GET" + } + } + }, + { + "element": "httpResponse", + "attributes": { + "statusCode": { + "element": "string", + "content": "204" + } + }, + "content": [ + { + "element": "copy", + "content": "no content" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/path-item-object-parameters-multiple.yaml b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/path-item-object-parameters-multiple.yaml new file mode 100644 index 000000000..1ff225211 --- /dev/null +++ b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/path-item-object-parameters-multiple.yaml @@ -0,0 +1,35 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Parameter Components +paths: + /1: + parameters: + - $ref: '#/components/parameters/skipParam' + - $ref: '#/components/parameters/limitParam' + get: + summary: List all pets + responses: + '204': + description: no content + /2: + parameters: + - $ref: '#/components/parameters/skipParam' + - $ref: '#/components/parameters/limitParam' + get: + summary: retrieve + responses: + '204': + description: no content +components: + parameters: + skipParam: + name: skip + in: query + description: number of items to skip + required: true + limitParam: + name: limit + in: query + description: max records to return + required: true diff --git a/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/response-object-headers-multiple.json b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/response-object-headers-multiple.json new file mode 100644 index 000000000..6db5bfc87 --- /dev/null +++ b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/response-object-headers-multiple.json @@ -0,0 +1,227 @@ +{ + "element": "parseResult", + "content": [ + { + "element": "category", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "api" + } + ] + }, + "title": { + "element": "string", + "content": "Headers Components" + } + }, + "attributes": { + "version": { + "element": "string", + "content": "1.0.0" + } + }, + "content": [ + { + "element": "resource", + "attributes": { + "href": { + "element": "string", + "content": "/user" + } + }, + "content": [ + { + "element": "transition", + "meta": { + "title": { + "element": "string", + "content": "View the current User" + } + }, + "content": [ + { + "element": "httpTransaction", + "content": [ + { + "element": "httpRequest", + "attributes": { + "method": { + "element": "string", + "content": "GET" + } + } + }, + { + "element": "httpResponse", + "attributes": { + "headers": { + "element": "httpHeaders", + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "X-Rate-Limit-Limit" + }, + "value": { + "element": "string" + } + } + } + ] + }, + "statusCode": { + "element": "string", + "content": "200" + } + }, + "content": [ + { + "element": "copy", + "content": "hi" + } + ] + } + ] + } + ] + } + ] + }, + { + "element": "resource", + "attributes": { + "href": { + "element": "string", + "content": "/users" + } + }, + "content": [ + { + "element": "transition", + "meta": { + "title": { + "element": "string", + "content": "View all users" + } + }, + "content": [ + { + "element": "httpTransaction", + "content": [ + { + "element": "httpRequest", + "attributes": { + "method": { + "element": "string", + "content": "GET" + } + } + }, + { + "element": "httpResponse", + "attributes": { + "headers": { + "element": "httpHeaders", + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "X-Rate-Limit-Limit" + }, + "value": { + "element": "string" + } + } + } + ] + }, + "statusCode": { + "element": "string", + "content": "200" + } + }, + "content": [ + { + "element": "copy", + "content": "hi" + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "element": "annotation", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "warning" + } + ] + } + }, + "attributes": { + "sourceMap": { + "element": "array", + "content": [ + { + "element": "sourceMap", + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "attributes": { + "line": { + "element": "number", + "content": 27 + }, + "column": { + "element": "number", + "content": 7 + } + }, + "content": 572 + }, + { + "element": "number", + "attributes": { + "line": { + "element": "number", + "content": 27 + }, + "column": { + "element": "number", + "content": 18 + } + }, + "content": 11 + } + ] + } + ] + } + ] + } + }, + "content": "'Header Object' contains unsupported key 'description'" + } + ] +} \ No newline at end of file diff --git a/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/response-object-headers-multiple.yaml b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/response-object-headers-multiple.yaml new file mode 100644 index 000000000..fb06b3987 --- /dev/null +++ b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/response-object-headers-multiple.yaml @@ -0,0 +1,27 @@ +openapi: 3.0.0 +info: + version: 1.0.0 + title: Headers Components +paths: + /user: + get: + summary: View the current User + responses: + '200': + description: hi + headers: + X-Rate-Limit-Limit: + $ref: '#/components/headers/X-Rate-Limit-Limit' + /users: + get: + summary: View all users + responses: + '200': + description: hi + headers: + X-Rate-Limit-Limit: + $ref: '#/components/headers/X-Rate-Limit-Limit' +components: + headers: + X-Rate-Limit-Limit: + description: The number of allowed requests in the current period diff --git a/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/responses-object-response-multiple.json b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/responses-object-response-multiple.json new file mode 100644 index 000000000..26a9e2a42 --- /dev/null +++ b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/responses-object-response-multiple.json @@ -0,0 +1,205 @@ +{ + "element": "parseResult", + "content": [ + { + "element": "category", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "api" + } + ] + }, + "title": { + "element": "string", + "content": "Response Components with Headers" + } + }, + "attributes": { + "version": { + "element": "string", + "content": "1.0.0" + } + }, + "content": [ + { + "element": "resource", + "attributes": { + "href": { + "element": "string", + "content": "/user" + } + }, + "content": [ + { + "element": "transition", + "meta": { + "title": { + "element": "string", + "content": "View the current User" + } + }, + "content": [ + { + "element": "httpTransaction", + "content": [ + { + "element": "httpRequest", + "attributes": { + "method": { + "element": "string", + "content": "GET" + } + } + }, + { + "element": "httpResponse", + "attributes": { + "headers": { + "element": "httpHeaders", + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "X-Rate-Limit-Limit" + }, + "value": { + "element": "string" + } + } + } + ] + }, + "statusCode": { + "element": "string", + "content": "226" + } + }, + "content": [ + { + "element": "copy", + "content": "A user" + } + ] + } + ] + }, + { + "element": "httpTransaction", + "content": [ + { + "element": "httpRequest", + "attributes": { + "method": { + "element": "string", + "content": "GET" + } + } + }, + { + "element": "httpResponse", + "attributes": { + "headers": { + "element": "httpHeaders", + "content": [ + { + "element": "member", + "content": { + "key": { + "element": "string", + "content": "X-Rate-Limit-Limit" + }, + "value": { + "element": "string" + } + } + } + ] + }, + "statusCode": { + "element": "string", + "content": "226" + } + }, + "content": [ + { + "element": "copy", + "content": "A user" + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "element": "annotation", + "meta": { + "classes": { + "element": "array", + "content": [ + { + "element": "string", + "content": "warning" + } + ] + } + }, + "attributes": { + "sourceMap": { + "element": "array", + "content": [ + { + "element": "sourceMap", + "content": [ + { + "element": "array", + "content": [ + { + "element": "number", + "attributes": { + "line": { + "element": "number", + "content": 23 + }, + "column": { + "element": "number", + "content": 7 + } + }, + "content": 508 + }, + { + "element": "number", + "attributes": { + "line": { + "element": "number", + "content": 23 + }, + "column": { + "element": "number", + "content": 18 + } + }, + "content": 11 + } + ] + } + ] + } + ] + } + }, + "content": "'Header Object' contains unsupported key 'description'" + } + ] +} \ No newline at end of file diff --git a/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/responses-object-response-multiple.yaml b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/responses-object-response-multiple.yaml new file mode 100644 index 000000000..b7e4424d3 --- /dev/null +++ b/packages/fury-adapter-oas3-parser/test/integration/fixtures/components/responses-object-response-multiple.yaml @@ -0,0 +1,23 @@ +openapi: 3.0.0 +info: + version: 1.0.0 + title: Response Components with Headers +paths: + /user: + get: + summary: View the current User + responses: + '200': + $ref: '#/components/responses/UserResponse' + '226': + $ref: '#/components/responses/UserResponse' +components: + responses: + UserResponse: + description: A user + headers: + X-Rate-Limit-Limit: + $ref: '#/components/headers/X-Rate-Limit-Limit' + headers: + X-Rate-Limit-Limit: + description: The number of allowed requests in the current period