-
Notifications
You must be signed in to change notification settings - Fork 14
CLOUDP-302982: IPA-104 - Get object should have suffix "Response" #465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
7779268
4982da0
a2e127c
95ec622
c0f679d
53b04b8
b8bb4ea
f814fa6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,263 @@ | ||||||
| import testRule from './__helpers__/testRule'; | ||||||
| import { DiagnosticSeverity } from '@stoplight/types'; | ||||||
|
|
||||||
| const componentSchemas = { | ||||||
| schemas: { | ||||||
| SchemaResponse: { | ||||||
| type: 'object', | ||||||
| }, | ||||||
| Schema: { | ||||||
| type: 'object', | ||||||
| }, | ||||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| testRule('xgen-IPA-104-get-method-returns-response-suffixed-object', [ | ||||||
| { | ||||||
| name: 'valid schema names names', | ||||||
| document: { | ||||||
| paths: { | ||||||
| '/resource/{id}': { | ||||||
| get: { | ||||||
| responses: { | ||||||
| 200: { | ||||||
| content: { | ||||||
| 'application/vnd.atlas.2023-01-01+json': { | ||||||
| schema: { | ||||||
| $ref: '#/components/schemas/SchemaResponse', | ||||||
| }, | ||||||
| }, | ||||||
| 'application/vnd.atlas.2024-01-01+json': { | ||||||
| schema: { | ||||||
| $ref: '#/components/schemas/SchemaResponse', | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would be our approach for inline schemas (properties defined here). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently the rule will fail and tell the API producer to implement a schema ref, same approach as we did in #473 |
||||||
| }, | ||||||
| }, | ||||||
| 'application/vnd.atlas.2025-01-01+json': { | ||||||
| schema: { | ||||||
| type: 'array', | ||||||
| items: { | ||||||
| $ref: '#/components/schemas/SchemaResponse', | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| 400: { | ||||||
| content: { | ||||||
| 'application/vnd.atlas.2023-01-01+json': { | ||||||
| schema: { | ||||||
| $ref: '#/components/schemas/Schema', | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| '/resourceTwo/{id}': { | ||||||
| get: { | ||||||
| responses: { | ||||||
| 200: { | ||||||
| content: { | ||||||
| 'application/vnd.atlas.2024-08-05+json': { | ||||||
| type: 'string', | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| '/resource/{id}/singleton': { | ||||||
| get: { | ||||||
| responses: { | ||||||
| 200: { | ||||||
| content: { | ||||||
| 'application/vnd.atlas.2024-08-05+json': { | ||||||
| schema: { | ||||||
| $ref: '#/components/schemas/SchemaResponse', | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| components: componentSchemas, | ||||||
| }, | ||||||
| errors: [], | ||||||
| }, | ||||||
| { | ||||||
| name: 'invalid resources', | ||||||
| document: { | ||||||
| paths: { | ||||||
| '/resource/{id}': { | ||||||
| get: { | ||||||
| responses: { | ||||||
| 200: { | ||||||
| content: { | ||||||
| 'application/vnd.atlas.2023-01-01+json': { | ||||||
| schema: { | ||||||
| $ref: '#/components/schemas/Schema', | ||||||
| }, | ||||||
| }, | ||||||
| 'application/vnd.atlas.2024-01-01+json': { | ||||||
| schema: { | ||||||
| $ref: '#/components/schemas/Schema', | ||||||
| }, | ||||||
| }, | ||||||
| 'application/vnd.atlas.2025-01-01+json': { | ||||||
| schema: { | ||||||
| type: 'array', | ||||||
| items: { | ||||||
| $ref: '#/components/schemas/Schema', | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. example to ignore
Suggested change
|
||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| '/resource/{id}/singleton': { | ||||||
| get: { | ||||||
| responses: { | ||||||
| 200: { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional: Test for two 2xx response codes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be an invalid json since we cannot have two keys of the same value |
||||||
| content: { | ||||||
| 'application/vnd.atlas.2024-08-05+json': { | ||||||
| schema: { | ||||||
| $ref: '#/components/schemas/Schema', | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| components: componentSchemas, | ||||||
| }, | ||||||
| errors: [ | ||||||
| { | ||||||
| code: 'xgen-IPA-104-get-method-returns-response-suffixed-object', | ||||||
| message: 'The request schema must reference a schema with a Response suffix. http://go/ipa/104', | ||||||
| path: [ | ||||||
| 'paths', | ||||||
| '/resource/{id}', | ||||||
| 'get', | ||||||
| 'responses', | ||||||
| '200', | ||||||
| 'content', | ||||||
| 'application/vnd.atlas.2023-01-01+json', | ||||||
| ], | ||||||
| severity: DiagnosticSeverity.Warning, | ||||||
| }, | ||||||
| { | ||||||
| code: 'xgen-IPA-104-get-method-returns-response-suffixed-object', | ||||||
| message: 'The request schema must reference a schema with a Response suffix. http://go/ipa/104', | ||||||
| path: [ | ||||||
| 'paths', | ||||||
| '/resource/{id}', | ||||||
| 'get', | ||||||
| 'responses', | ||||||
| '200', | ||||||
| 'content', | ||||||
| 'application/vnd.atlas.2024-01-01+json', | ||||||
| ], | ||||||
| severity: DiagnosticSeverity.Warning, | ||||||
| }, | ||||||
| { | ||||||
| code: 'xgen-IPA-104-get-method-returns-response-suffixed-object', | ||||||
| message: 'The request schema must reference a schema with a Response suffix. http://go/ipa/104', | ||||||
| path: [ | ||||||
| 'paths', | ||||||
| '/resource/{id}', | ||||||
| 'get', | ||||||
| 'responses', | ||||||
| '200', | ||||||
| 'content', | ||||||
| 'application/vnd.atlas.2025-01-01+json', | ||||||
| ], | ||||||
| severity: DiagnosticSeverity.Warning, | ||||||
| }, | ||||||
| { | ||||||
| code: 'xgen-IPA-104-get-method-returns-response-suffixed-object', | ||||||
| message: 'The request schema must reference a schema with a Response suffix. http://go/ipa/104', | ||||||
| path: [ | ||||||
| 'paths', | ||||||
| '/resource/{id}/singleton', | ||||||
| 'get', | ||||||
| 'responses', | ||||||
| '200', | ||||||
| 'content', | ||||||
| 'application/vnd.atlas.2024-08-05+json', | ||||||
| ], | ||||||
| severity: DiagnosticSeverity.Warning, | ||||||
| }, | ||||||
| ], | ||||||
| }, | ||||||
| { | ||||||
| name: 'invalid resources with exceptions', | ||||||
| document: { | ||||||
| paths: { | ||||||
| '/resource/{id}': { | ||||||
| get: { | ||||||
| responses: { | ||||||
| 200: { | ||||||
| content: { | ||||||
| 'application/vnd.atlas.2023-01-01+json': { | ||||||
| 'x-xgen-IPA-exception': { | ||||||
| 'xgen-IPA-104-get-method-returns-response-suffixed-object': 'reason', | ||||||
| }, | ||||||
| schema: { | ||||||
| $ref: '#/components/schemas/Schema', | ||||||
| }, | ||||||
| }, | ||||||
| 'application/vnd.atlas.2024-01-01+json': { | ||||||
| 'x-xgen-IPA-exception': { | ||||||
| 'xgen-IPA-104-get-method-returns-response-suffixed-object': 'reason', | ||||||
| }, | ||||||
| schema: { | ||||||
| $ref: '#/components/schemas/Schema', | ||||||
| }, | ||||||
| }, | ||||||
| 'application/vnd.atlas.2025-01-01+json': { | ||||||
| 'x-xgen-IPA-exception': { | ||||||
| 'xgen-IPA-104-get-method-returns-response-suffixed-object': 'reason', | ||||||
| }, | ||||||
| schema: { | ||||||
| type: 'array', | ||||||
| items: { | ||||||
| $ref: '#/components/schemas/Schema', | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| '/resource/{id}/singleton': { | ||||||
| get: { | ||||||
| responses: { | ||||||
| 200: { | ||||||
| content: { | ||||||
| 'application/vnd.atlas.2024-08-05+json': { | ||||||
| 'x-xgen-IPA-exception': { | ||||||
| 'xgen-IPA-104-get-method-returns-response-suffixed-object': 'reason', | ||||||
| }, | ||||||
| schema: { | ||||||
| $ref: '#/components/schemas/Schema', | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| }, | ||||||
| components: componentSchemas, | ||||||
| }, | ||||||
| errors: [], | ||||||
| }, | ||||||
| ]); | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ import { hasException } from './utils/exceptions.js'; | |
| import { collectAdoption, collectAndReturnViolation, collectException } from './utils/collectionUtils.js'; | ||
| import { isCustomMethodIdentifier } from './utils/resourceEvaluation.js'; | ||
| import { resolveObject } from './utils/componentUtils.js'; | ||
| import { getSchemaRef } from './utils/methodUtils.js'; | ||
|
|
||
| const RULE_NAME = 'xgen-IPA-106-create-method-request-body-is-request-suffixed-object'; | ||
| const ERROR_MESSAGE_SCHEMA_NAME = 'The response body schema must reference a schema with a Request suffix.'; | ||
|
|
@@ -10,8 +11,9 @@ const ERROR_MESSAGE_SCHEMA_REF = 'The response body schema is defined inline and | |
| export default (input, _, { path, documentInventory }) => { | ||
| const oas = documentInventory.unresolved; | ||
| const resourcePath = path[1]; | ||
| const contentMediaType = path[path.length - 1]; | ||
|
|
||
| if (isCustomMethodIdentifier(resourcePath)) { | ||
| if (isCustomMethodIdentifier(resourcePath) || !contentMediaType.endsWith('json')) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added check to only apply rule to json content types, since csv and gzip don't really have a schema, it's alright if they don't reference one There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call as this might cause failures for new content types. Good to have short spec for it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure! I'll add to the spec tab |
||
| return; | ||
| } | ||
|
|
||
|
|
@@ -24,24 +26,13 @@ export default (input, _, { path, documentInventory }) => { | |
|
|
||
| if (contentPerMediaType.schema) { | ||
| const schema = contentPerMediaType.schema; | ||
| if (schema.type === 'array' && schema.items) { | ||
| let schemaItems = schema.items; | ||
| if (!schemaItems.$ref) { | ||
| return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE_SCHEMA_REF); | ||
| } | ||
| if (!schemaItems.$ref.endsWith('Request')) { | ||
| return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE_SCHEMA_NAME); | ||
| } | ||
| } else { | ||
| if (!schema.$ref) { | ||
| return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE_SCHEMA_REF); | ||
| } | ||
|
|
||
| if (!schema.$ref.endsWith('Request')) { | ||
| return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE_SCHEMA_NAME); | ||
| } | ||
| const schemaRef = getSchemaRef(schema); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Created a shared function since this logic is pretty much the same for the new rule as well There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was looking for that function as well :) |
||
| if (!schemaRef) { | ||
| return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE_SCHEMA_REF); | ||
| } | ||
| if (!schemaRef.endsWith('Request')) { | ||
| return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE_SCHEMA_NAME); | ||
| } | ||
|
|
||
| collectAdoption(path, RULE_NAME); | ||
| } | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technical note to add:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, I'm good with that, can document when merged