From c952002f87beb15cbfb6e544c5d36ce6ce5ade2a Mon Sep 17 00:00:00 2001 From: coliu19 Date: Wed, 8 Mar 2023 11:59:45 +0800 Subject: [PATCH] check example for array and nested object --- functions/ensureExamples.js | 48 +++++++++------ test/examples-for-every-schema.spec.js | 52 +++++++++++++++- .../examples-for-every-schema/negative.json | 59 ++++++++++++++++++ .../examples-for-every-schema/positive.json | 60 +++++++++++++++++++ 4 files changed, 199 insertions(+), 20 deletions(-) diff --git a/functions/ensureExamples.js b/functions/ensureExamples.js index 4f0025c..0173697 100644 --- a/functions/ensureExamples.js +++ b/functions/ensureExamples.js @@ -28,26 +28,16 @@ module.exports = function (targetVal) { return; } - if (targetVal.schema) { - if (targetVal.examples || targetVal.example || targetVal.schema.example) { - return; - } - - if (targetVal.schema.properties) { - const props = targetVal.schema.properties; - let missing = false; + if (!targetVal.schema) { + return; + } - for (const key in props) { - if (props[key] && !props[key].example) { - missing = true; - break; - } - } + if (targetVal.examples || targetVal.example || targetVal.schema.example) { + return; + } - if (!missing) { - return; - } - } + if (hasExample(targetVal.schema)) { + return; } return [ @@ -56,3 +46,25 @@ module.exports = function (targetVal) { }, ]; }; + +function hasExample(target) { + if (target == null || target.examples || target.example) { + return true; + } + + if (target.type === 'array') { + return hasExample(target.items); + } + + if (!target.type || target.type === 'object') { + for (const key in target.properties) { + if (!hasExample(target.properties[key])) { + return false; + } + } + + return true; + } + + return false; +} diff --git a/test/examples-for-every-schema.spec.js b/test/examples-for-every-schema.spec.js index b80f052..13497b5 100644 --- a/test/examples-for-every-schema.spec.js +++ b/test/examples-for-every-schema.spec.js @@ -82,6 +82,54 @@ describe(ruleName, () => { }, severity: 1, }, + { + code: ruleName, + message: 'For every schema provided in the OAS document, at least one example must be present; example or examples is missing in the object', + path: [ + 'paths', + '/test', + 'get', + 'responses', + '400', + 'content', + 'application/json', + ], + range: { + end: { + character: 61, + line: 79, + }, + start: { + character: 33, + line: 77, + }, + }, + severity: 1, + }, + { + code: ruleName, + message: 'For every schema provided in the OAS document, at least one example must be present; example or examples is missing in the object', + path: [ + 'paths', + '/test', + 'get', + 'responses', + '401', + 'content', + 'application/json', + ], + range: { + end: { + character: 63, + line: 91, + }, + start: { + character: 33, + line: 87, + }, + }, + severity: 1, + }, { code: ruleName, message: 'For every schema provided in the OAS document, at least one example must be present; example or examples is missing in the object', @@ -97,11 +145,11 @@ describe(ruleName, () => { range: { end: { character: 38, - line: 137, + line: 160, }, start: { character: 33, - line: 124, + line: 147, }, }, severity: 1, diff --git a/test/resources/examples-for-every-schema/negative.json b/test/resources/examples-for-every-schema/negative.json index e73e6f7..255a6a3 100644 --- a/test/resources/examples-for-every-schema/negative.json +++ b/test/resources/examples-for-every-schema/negative.json @@ -72,6 +72,29 @@ } } }, + "400": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AnotherError" + } + } + } + }, + "401": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AnotherError" + } + } + } + } + }, "500": { "description": "unexpected error", "content": { @@ -202,6 +225,42 @@ "code": 2, "message": "m" } + }, + "AnotherError": { + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "format": "int32", + "example": 3 + }, + "message": { + "type": "string", + "example": "mm" + }, + "errors": { + "type": "object", + "example": { + "a": 1 + } + }, + "details": { + "type": "object", + "properties": { + "a": { + "type": "integer", + "format": "int32", + "example": 3 + }, + "b": { + "type": "string" + } + } + } + } } }, "securitySchemes": { diff --git a/test/resources/examples-for-every-schema/positive.json b/test/resources/examples-for-every-schema/positive.json index b168e74..b0bd423 100644 --- a/test/resources/examples-for-every-schema/positive.json +++ b/test/resources/examples-for-every-schema/positive.json @@ -79,6 +79,29 @@ } } }, + "400": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AnotherError" + } + } + } + }, + "401": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AnotherError" + } + } + } + } + }, "500": { "description": "unexpected error", "content": { @@ -248,6 +271,43 @@ "code": 2, "message": "m" } + }, + "AnotherError": { + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "format": "int32", + "example": 3 + }, + "message": { + "type": "string", + "example": "mm" + }, + "errors": { + "type": "object", + "example": { + "a": 1 + } + }, + "details": { + "type": "object", + "properties": { + "a": { + "type": "integer", + "format": "int32", + "example": 3 + }, + "b": { + "type": "string", + "example": "s" + } + } + } + } } }, "securitySchemes": {