Skip to content

Commit 3aa8ea9

Browse files
committed
IPA-108: Add rulesets for delete method responses
1 parent eed6e18 commit 3aa8ea9

13 files changed

+477
-7
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import testRule from './__helpers__/testRule';
2+
import { DiagnosticSeverity } from '@stoplight/types';
3+
4+
testRule('xgen-IPA-108-delete-method-return-204-response', [
5+
{
6+
name: 'valid DELETE with 204',
7+
document: {
8+
paths: {
9+
'/resource/{id}': {
10+
delete: {
11+
responses: {
12+
204: {
13+
description: 'Resource deleted',
14+
},
15+
},
16+
},
17+
},
18+
},
19+
},
20+
errors: [],
21+
},
22+
{
23+
name: 'invalid DELETE missing 204',
24+
document: {
25+
paths: {
26+
'/resource/{id}': {
27+
delete: {
28+
responses: {
29+
200: {
30+
description: 'Resource deleted',
31+
},
32+
},
33+
},
34+
},
35+
},
36+
},
37+
errors: [
38+
{
39+
code: 'xgen-IPA-108-delete-method-return-204-response',
40+
message: 'DELETE method should return 204 No Content status code http://go/ipa/108',
41+
path: ['paths', '/resource/{id}', 'delete'],
42+
severity: DiagnosticSeverity.Error,
43+
},
44+
],
45+
},
46+
{
47+
name: 'valid with exception',
48+
document: {
49+
paths: {
50+
'/resource/{id}': {
51+
delete: {
52+
'x-xgen-IPA-exception': {
53+
'xgen-IPA-108-delete-method-return-204-response': 'Legacy API',
54+
},
55+
responses: {
56+
200: {
57+
description: 'Resource deleted',
58+
},
59+
},
60+
},
61+
},
62+
},
63+
},
64+
errors: [],
65+
},
66+
]);
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import testRule from './__helpers__/testRule';
2+
import { DiagnosticSeverity } from '@stoplight/types';
3+
4+
testRule('xgen-IPA-108-delete-include-404-response', [
5+
{
6+
name: 'valid DELETE with 404',
7+
document: {
8+
paths: {
9+
'/resource/{id}': {
10+
delete: {
11+
responses: {
12+
204: {},
13+
404: {
14+
description: 'Resource not found',
15+
},
16+
},
17+
},
18+
},
19+
},
20+
},
21+
errors: [],
22+
},
23+
{
24+
name: 'invalid DELETE missing 404',
25+
document: {
26+
paths: {
27+
'/resource/{id}': {
28+
delete: {
29+
responses: {
30+
204: {},
31+
},
32+
},
33+
},
34+
},
35+
},
36+
errors: [
37+
{
38+
code: 'xgen-IPA-108-delete-include-404-response',
39+
message: 'DELETE method should include 404 status code for not found resources http://go/ipa/108',
40+
path: ['paths', '/resource/{id}', 'delete'],
41+
severity: DiagnosticSeverity.Error,
42+
},
43+
],
44+
},
45+
{
46+
name: 'valid with exception',
47+
document: {
48+
paths: {
49+
'/resource/{id}': {
50+
delete: {
51+
'x-xgen-IPA-exception': {
52+
'xgen-IPA-108-delete-include-404-response': 'Idempotent delete',
53+
},
54+
responses: {
55+
204: {},
56+
},
57+
},
58+
},
59+
},
60+
},
61+
errors: [],
62+
},
63+
]);
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import testRule from './__helpers__/testRule';
2+
import { DiagnosticSeverity } from '@stoplight/types';
3+
4+
testRule('xgen-IPA-108-delete-request-no-body', [
5+
{
6+
name: 'valid DELETE without body',
7+
document: {
8+
paths: {
9+
'/resource/{id}': {
10+
delete: {
11+
responses: {
12+
204: {},
13+
},
14+
},
15+
},
16+
},
17+
},
18+
errors: [],
19+
},
20+
{
21+
name: 'invalid DELETE with body',
22+
document: {
23+
paths: {
24+
'/resource/{id}': {
25+
delete: {
26+
requestBody: {
27+
content: {
28+
'application/vnd.atlas.2024-08-05+json': {
29+
schema: { type: 'object' },
30+
},
31+
},
32+
},
33+
responses: {
34+
204: {},
35+
},
36+
},
37+
},
38+
},
39+
},
40+
errors: [
41+
{
42+
code: 'xgen-IPA-108-delete-request-no-body',
43+
message: 'DELETE method should not have a request body http://go/ipa/108',
44+
path: ['paths', '/resource/{id}', 'delete'],
45+
severity: DiagnosticSeverity.Error,
46+
},
47+
],
48+
},
49+
{
50+
name: 'valid with exception',
51+
document: {
52+
paths: {
53+
'/resource/{id}': {
54+
delete: {
55+
'x-xgen-IPA-exception': {
56+
'xgen-IPA-108-delete-request-no-body': 'Bulk delete operation',
57+
},
58+
requestBody: {
59+
content: {
60+
'application/json': {
61+
schema: { type: 'object' },
62+
},
63+
},
64+
},
65+
},
66+
},
67+
},
68+
},
69+
errors: [],
70+
},
71+
]);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import testRule from './__helpers__/testRule';
2+
import { DiagnosticSeverity } from '@stoplight/types';
3+
4+
testRule('xgen-IPA-108-delete-response-should-be-empty', [
5+
{
6+
name: 'valid DELETE with void 204',
7+
document: {
8+
paths: {
9+
'/resource/{id}': {
10+
delete: {
11+
responses: {
12+
204: {},
13+
},
14+
},
15+
},
16+
},
17+
},
18+
errors: [],
19+
},
20+
{
21+
name: 'invalid DELETE with non-void 204',
22+
document: {
23+
paths: {
24+
'/resource/{id}': {
25+
delete: {
26+
responses: {
27+
204: {
28+
content: {
29+
'application/vnd.atlas.2023-01-01+json': {
30+
schema: { type: 'object' },
31+
},
32+
},
33+
},
34+
},
35+
},
36+
},
37+
},
38+
},
39+
errors: [
40+
{
41+
code: 'xgen-IPA-108-delete-response-should-be-empty',
42+
message: 'DELETE method should return an empty response http://go/ipa/108',
43+
path: ['paths', '/resource/{id}', 'delete'],
44+
severity: DiagnosticSeverity.Error,
45+
},
46+
],
47+
},
48+
{
49+
name: 'valid with exception',
50+
document: {
51+
paths: {
52+
'/resource/{id}': {
53+
delete: {
54+
'x-xgen-IPA-exception': {
55+
'xgen-IPA-108-delete-response-should-be-empty': 'Legacy API',
56+
},
57+
responses: {
58+
204: {
59+
content: {
60+
'application/vnd.atlas.2023-01-01+json': {
61+
schema: { type: 'object' },
62+
},
63+
},
64+
},
65+
},
66+
},
67+
},
68+
},
69+
},
70+
errors: [],
71+
},
72+
]);

tools/spectral/ipa/ipa-spectral.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extends:
66
- ./rulesets/IPA-113.yaml
77
- ./rulesets/IPA-123.yaml
88
- ./rulesets/IPA-106.yaml
9+
- ./rulesets/IPA-108.yaml
910

1011
overrides:
1112
- files:
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# IPA-108: Delete
2+
# http://go/ipa/108
3+
4+
rules:
5+
xgen-IPA-108-delete-response-should-be-empty:
6+
description: Delete method response must be empty http://go/ipa/108
7+
message: '{{error}} http://go/ipa/108'
8+
severity: warn
9+
given: '$.paths[*].delete'
10+
then:
11+
function: deleteMethodResponseShouldBeVoid
12+
13+
xgen-IPA-108-delete-method-return-204-response:
14+
description: DELETE method must return 204 No Content
15+
message: '{{error}} http://go/ipa/108'
16+
severity: warn
17+
given: '$.paths[*].delete'
18+
then:
19+
function: deleteMethod204Response
20+
21+
xgen-IPA-108-delete-request-no-body:
22+
description: DELETE method must not have request body
23+
message: '{{error}} http://go/ipa/108'
24+
severity: warn
25+
given: '$.paths[*].delete'
26+
then:
27+
function: deleteMethodNoRequestBody
28+
29+
xgen-IPA-108-delete-include-404-response:
30+
description: DELETE method must include 404 response
31+
message: '{{error}} http://go/ipa/108'
32+
severity: warn
33+
given: '$.paths[*].delete'
34+
then:
35+
function: deleteMethod404Response
36+
37+
functions:
38+
- deleteMethodResponseShouldBeVoid
39+
- deleteMethod204Response
40+
- deleteMethodNoRequestBody
41+
- deleteMethod404Response

tools/spectral/ipa/rulesets/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@ For rule definitions, see [IPA-106.yaml](https://github.com/mongodb/openapi/blob
4242
| ------------------------------------------------------------------ | -------------------------------------------------------------------------------- | -------- |
4343
| xgen-IPA-106-create-method-request-body-is-request-suffixed-object | The Create method request should be a Request suffixed object. http://go/ipa/106 | warn |
4444

45+
### IPA-108
46+
47+
For rule definitions, see [IPA-108.yaml](https://github.com/mongodb/openapi/blob/main/tools/spectral/ipa/rulesets/IPA-108.yaml).
48+
49+
| Rule Name | Description | Severity |
50+
| ---------------------------------------------- | ------------------------------------------------------ | -------- |
51+
| xgen-IPA-108-delete-response-should-be-empty | Delete method response must be empty http://go/ipa/108 | warn |
52+
| xgen-IPA-108-delete-method-return-204-response | DELETE method must return 204 No Content | warn |
53+
| xgen-IPA-108-delete-request-no-body | DELETE method must not have request body | warn |
54+
| xgen-IPA-108-delete-include-404-response | DELETE method must include 404 response | warn |
55+
4556
### IPA-109
4657

4758
For rule definitions, see [IPA-109.yaml](https://github.com/mongodb/openapi/blob/main/tools/spectral/ipa/rulesets/IPA-109.yaml).

tools/spectral/ipa/rulesets/functions/__tests__/deleteMethodResponseShouldBeVoid.test.js

Whitespace-only changes.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { collectAdoption, collectAndReturnViolation, collectException } from './utils/collectionUtils.js';
2+
import { hasException } from './utils/exceptions.js';
3+
4+
const RULE_NAME = 'xgen-IPA-108-delete-method-return-204-response';
5+
const ERROR_MESSAGE = 'DELETE method should return 204 No Content status code';
6+
7+
/**
8+
* Delete method should return 204 No Content status code
9+
*
10+
* @param {object} input - The delete operation object
11+
* @param {object} _ - Unused
12+
* @param {object} context - The context object containing the path
13+
*/
14+
export default (input, _, { path }) => {
15+
const deleteOp = input;
16+
if (!deleteOp) return;
17+
18+
const errors = [];
19+
const jsonPath = `paths.${path}.delete`;
20+
21+
if (hasException(deleteOp, RULE_NAME)) {
22+
errors.push(collectException(deleteOp, RULE_NAME, jsonPath));
23+
return errors;
24+
}
25+
26+
const responses = deleteOp.responses || {};
27+
if (!responses['204']) {
28+
errors.push(collectAndReturnViolation(jsonPath, RULE_NAME, ERROR_MESSAGE));
29+
return errors;
30+
}
31+
32+
collectAdoption(jsonPath, RULE_NAME);
33+
34+
return errors;
35+
};

0 commit comments

Comments
 (0)