From 01a68355ee46d4ede0d50fd40cb333e2e5dc9dc7 Mon Sep 17 00:00:00 2001 From: Kanad Gupta Date: Tue, 23 May 2023 16:57:21 -0500 Subject: [PATCH 1/2] fix: ensure summaries + descriptions are strings --- .../callbacks-weird-summary-description.json | 190 ++++++++++++++++++ __tests__/operation.test.ts | 22 ++ src/operation.ts | 16 +- 3 files changed, 220 insertions(+), 8 deletions(-) create mode 100644 __tests__/__datasets__/callbacks-weird-summary-description.json diff --git a/__tests__/__datasets__/callbacks-weird-summary-description.json b/__tests__/__datasets__/callbacks-weird-summary-description.json new file mode 100644 index 000000000..44df6d058 --- /dev/null +++ b/__tests__/__datasets__/callbacks-weird-summary-description.json @@ -0,0 +1,190 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Support for callbacks", + "description": "https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operationObject\n\nhttps://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#parameter-object\n\nhttps://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#schema-object", + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://httpbin.org" + } + ], + "paths": { + "/callbacks": { + "get": { + "summary": { + "$ref": "foo-summary.md" + }, + "description": { + "$ref": "foo-desc.md" + }, + "responses": { + "200": { + "description": "OK" + } + }, + "callbacks": { + "myCallback": { + "{$request.query.queryUrl}": { + "post": { + "summary": { + "$ref": "foo-summary.md" + }, + "description": { + "$ref": "foo-desc.md" + }, + "requestBody": { + "description": "Callback payload", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/dog" + } + } + } + }, + "responses": { + "200": { + "description": "callback successfully processed", + "content": { + "application/json": { + "example": { + "id": 1, + "name": "Pug", + "is_a_good_dog": true + } + } + } + } + } + } + } + }, + "multipleCallback": { + "{$request.multipleExpression.queryUrl}": { + "post": { + "requestBody": { + "description": "Callback payload", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/dog" + } + } + } + }, + "responses": { + "200": { + "description": "callback successfully processed", + "content": { + "application/json": { + "example": { + "id": 1, + "name": "Pug", + "is_a_good_dog": true + } + } + } + } + } + } + }, + "{$request.multipleMethod.queryUrl}": { + "summary": "[common] callback summary", + "description": "[common] callback description", + "parameters": [ + { + "in": "query", + "name": "queryParam", + "schema": { + "type": "string" + }, + "required": true + } + ], + "post": { + "summary": "[post] callback summary", + "description": "[post] callback description", + "requestBody": { + "description": "Callback payload", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/dog" + } + } + } + }, + "responses": { + "200": { + "description": "callback successfully processed" + } + } + }, + "get": { + "summary": "[get] callback summary", + "description": "[get] callback description", + "parameters": [ + { + "in": "query", + "name": "queryParam", + "schema": { + "type": "string" + }, + "required": true + }, + { + "in": "query", + "name": "anotherQueryParam", + "schema": { + "type": "string" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "callback successfully processed", + "content": { + "application/json": { + "example": { + "id": 1, + "name": "Pug", + "is_a_good_dog": true + } + } + } + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "dog": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "is_a_good_dog": { + "type": "boolean" + } + }, + "example": { + "id": 1, + "name": "Pug", + "is_a_good_dog": true + } + } + } + } +} diff --git a/__tests__/operation.test.ts b/__tests__/operation.test.ts index f6ebb4ea0..7d87f06bc 100644 --- a/__tests__/operation.test.ts +++ b/__tests__/operation.test.ts @@ -15,6 +15,7 @@ let parametersCommon: Oas; let petstoreNondereferenced: Oas; let oas31NoResponses: Oas; let readme: Oas; +let callbacksWeirdSummaryDescription: Oas; beforeAll(async () => { petstore = await import('@readme/oas-examples/3.0/json/petstore.json').then(r => r.default).then(Oas.init); @@ -35,6 +36,11 @@ beforeAll(async () => { deprecatedSchema = await import('./__datasets__/schema-deprecated.json').then(r => r.default).then(Oas.init); await deprecatedSchema.dereference(); + callbacksWeirdSummaryDescription = await import('./__datasets__/callbacks-weird-summary-description.json') + .then(r => r.default) + .then(Oas.init); + await callbacksWeirdSummaryDescription.dereference(); + parametersCommon = await import('@readme/oas-examples/3.0/json/parameters-common.json') .then(r => r.default) .then(Oas.init); @@ -83,6 +89,13 @@ describe('#getSummary() + #getDescription()', () => { expect(operation.getDescription()).toBe('[get] Description'); }); + it('should account for non-string summaries and descriptions', () => { + const operation = callbacksWeirdSummaryDescription.operation('/callbacks', 'get'); + + expect(operation.getSummary()).toBeUndefined(); + expect(operation.getDescription()).toBeUndefined(); + }); + describe('callbacks', () => { it('should return a summary if present', () => { const operation = callbackSchema.operation('/callbacks', 'get'); @@ -115,6 +128,15 @@ describe('#getSummary() + #getDescription()', () => { expect(callback.getSummary()).toBe('[post] callback summary'); expect(callback.getDescription()).toBe('[post] callback description'); }); + + it('should account for non-string summaries and descriptions', () => { + const operation = callbacksWeirdSummaryDescription.operation('/callbacks', 'get'); + + const callback = operation.getCallback('myCallback', '{$request.query.queryUrl}', 'post') as Callback; + + expect(callback.getSummary()).toBeUndefined(); + expect(callback.getDescription()).toBeUndefined(); + }); }); }); diff --git a/src/operation.ts b/src/operation.ts index 48f5efceb..2355a7adb 100644 --- a/src/operation.ts +++ b/src/operation.ts @@ -78,8 +78,8 @@ export default class Operation { } getSummary(): string { - if (this.schema?.summary) { - return this.schema.summary.trim(); + if (this.schema?.summary && typeof this.schema.summary === 'string') { + return this.schema.summary; } else if (this.api.paths[this.path].summary) { return this.api.paths[this.path].summary; } @@ -88,8 +88,8 @@ export default class Operation { } getDescription(): string { - if (this.schema?.description) { - return this.schema.description.trim(); + if (this.schema?.description && typeof this.schema.description === 'string') { + return this.schema.description; } else if (this.api.paths[this.path].description) { return this.api.paths[this.path].description; } @@ -854,8 +854,8 @@ export class Callback extends Operation { } getSummary(): string { - if (this.schema?.summary) { - return this.schema.summary.trim(); + if (this.schema?.summary && typeof this.schema.summary === 'string') { + return this.schema.summary; } else if (this.parentSchema.summary) { return this.parentSchema.summary; } @@ -864,8 +864,8 @@ export class Callback extends Operation { } getDescription(): string { - if (this.schema?.description) { - return this.schema.description.trim(); + if (this.schema?.description && typeof this.schema.description === 'string') { + return this.schema.description; } else if (this.parentSchema.description) { return this.parentSchema.description; } From fa90f62a6a0e0d249d7a420f359fcb999583ed40 Mon Sep 17 00:00:00 2001 From: Kanad Gupta Date: Tue, 23 May 2023 17:17:11 -0500 Subject: [PATCH 2/2] fix: also extending this check to common fields feedback: https://github.com/readmeio/oas/pull/764#discussion_r1203069976 --- .../callbacks-weird-summary-description.json | 23 +++++++++++++++---- __tests__/operation.test.ts | 19 +++++++++++++++ src/operation.ts | 8 +++---- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/__tests__/__datasets__/callbacks-weird-summary-description.json b/__tests__/__datasets__/callbacks-weird-summary-description.json index 44df6d058..c2c73be6c 100644 --- a/__tests__/__datasets__/callbacks-weird-summary-description.json +++ b/__tests__/__datasets__/callbacks-weird-summary-description.json @@ -12,6 +12,12 @@ ], "paths": { "/callbacks": { + "summary": { + "$ref": "foo-summary.md" + }, + "description": { + "$ref": "foo-desc.md" + }, "get": { "summary": { "$ref": "foo-summary.md" @@ -91,8 +97,12 @@ } }, "{$request.multipleMethod.queryUrl}": { - "summary": "[common] callback summary", - "description": "[common] callback description", + "summary": { + "$ref": "foo-summary.md" + }, + "description": { + "$ref": "foo-desc.md" + }, "parameters": [ { "in": "query", @@ -104,8 +114,6 @@ } ], "post": { - "summary": "[post] callback summary", - "description": "[post] callback description", "requestBody": { "description": "Callback payload", "content": { @@ -161,6 +169,13 @@ } } } + }, + "post": { + "responses": { + "200": { + "description": "OK" + } + } } } }, diff --git a/__tests__/operation.test.ts b/__tests__/operation.test.ts index 7d87f06bc..b96afeec1 100644 --- a/__tests__/operation.test.ts +++ b/__tests__/operation.test.ts @@ -96,6 +96,13 @@ describe('#getSummary() + #getDescription()', () => { expect(operation.getDescription()).toBeUndefined(); }); + it('should account for non-string common summaries and descriptions', () => { + const operation = callbacksWeirdSummaryDescription.operation('/callbacks', 'post'); + + expect(operation.getSummary()).toBeUndefined(); + expect(operation.getDescription()).toBeUndefined(); + }); + describe('callbacks', () => { it('should return a summary if present', () => { const operation = callbackSchema.operation('/callbacks', 'get'); @@ -137,6 +144,18 @@ describe('#getSummary() + #getDescription()', () => { expect(callback.getSummary()).toBeUndefined(); expect(callback.getDescription()).toBeUndefined(); }); + + it('should account for non-string common callback summary + descriptions', () => { + const operation = callbacksWeirdSummaryDescription.operation('/callbacks', 'get'); + const callback = operation.getCallback( + 'multipleCallback', + '{$request.multipleMethod.queryUrl}', + 'post' + ) as Callback; + + expect(callback.getSummary()).toBeUndefined(); + expect(callback.getDescription()).toBeUndefined(); + }); }); }); diff --git a/src/operation.ts b/src/operation.ts index 2355a7adb..9f99281c0 100644 --- a/src/operation.ts +++ b/src/operation.ts @@ -80,7 +80,7 @@ export default class Operation { getSummary(): string { if (this.schema?.summary && typeof this.schema.summary === 'string') { return this.schema.summary; - } else if (this.api.paths[this.path].summary) { + } else if (this.api.paths[this.path].summary && typeof this.api.paths[this.path].summary === 'string') { return this.api.paths[this.path].summary; } @@ -90,7 +90,7 @@ export default class Operation { getDescription(): string { if (this.schema?.description && typeof this.schema.description === 'string') { return this.schema.description; - } else if (this.api.paths[this.path].description) { + } else if (this.api.paths[this.path].description && typeof this.api.paths[this.path].description === 'string') { return this.api.paths[this.path].description; } @@ -856,7 +856,7 @@ export class Callback extends Operation { getSummary(): string { if (this.schema?.summary && typeof this.schema.summary === 'string') { return this.schema.summary; - } else if (this.parentSchema.summary) { + } else if (this.parentSchema.summary && typeof this.parentSchema.summary === 'string') { return this.parentSchema.summary; } @@ -866,7 +866,7 @@ export class Callback extends Operation { getDescription(): string { if (this.schema?.description && typeof this.schema.description === 'string') { return this.schema.description; - } else if (this.parentSchema.description) { + } else if (this.parentSchema.description && typeof this.parentSchema.description === 'string') { return this.parentSchema.description; }