Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import testRule from './__helpers__/testRule';
import { DiagnosticSeverity } from '@stoplight/types';

testRule('xgen-IPA-117-operation-summary-single-item-wording', [
{
name: 'valid summary',
document: {
paths: {
'/resource/{id}': {
get: {
summary: 'Return One Resource by ID',
},
},
},
},
errors: [],
},
{
name: 'invalid summaries',
document: {
paths: {
'/resource1/{id}': {
get: {
summary: 'Return One Resource for the Provided Group',
},
},
'/resource2/{id}': {
get: {
summary: 'Return the Specified Resource by ID',
},
},
'/resource3/{id}': {
get: {
summary: 'Return a Resource by ID',
},
},
'/resource4/{id}': {
get: {
summary: 'Return a Resource for the Provided Group',
},
},
},
},
errors: [
{
code: 'xgen-IPA-117-operation-summary-single-item-wording',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For multiple forbidden words, we would have multiple errors. Is it correct?
Such as Return a resource for the specified project

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! I added a test case as example

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty!

message: 'Operation summary referring to a single item must use "one" instead of "provided".',
path: ['paths', '/resource1/{id}', 'get'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-117-operation-summary-single-item-wording',
message: 'Operation summary referring to a single item must use "one" instead of "specified".',
path: ['paths', '/resource2/{id}', 'get'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-117-operation-summary-single-item-wording',
message: 'Operation summary referring to a single item must use "one" instead of "a".',
path: ['paths', '/resource3/{id}', 'get'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-117-operation-summary-single-item-wording',
message: 'Operation summary referring to a single item must use "one" instead of "a".',
path: ['paths', '/resource4/{id}', 'get'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-117-operation-summary-single-item-wording',
message: 'Operation summary referring to a single item must use "one" instead of "provided".',
path: ['paths', '/resource4/{id}', 'get'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'invalid summary with exceptions',
document: {
paths: {
'/resource1/{id}': {
get: {
summary: 'Return One Resource for the Provided Group',
'x-xgen-IPA-exception': {
'xgen-IPA-117-operation-summary-single-item-wording': 'reason',
},
},
},
'/resource2/{id}': {
get: {
summary: 'Return the Specified Resource by ID',
'x-xgen-IPA-exception': {
'xgen-IPA-117-operation-summary-single-item-wording': 'reason',
},
},
},
'/resource3/{id}': {
get: {
summary: 'Return a Resource by ID',
'x-xgen-IPA-exception': {
'xgen-IPA-117-operation-summary-single-item-wording': 'reason',
},
},
},
},
},
errors: [],
},
]);
25 changes: 25 additions & 0 deletions tools/spectral/ipa/rulesets/IPA-117.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ functions:
- IPA117ParameterHasExamplesOrSchema
- IPA117OperationSummaryFormat
- IPA117OperationSummaryStartsWith
- IPA117OperationSummarySingleItemWording

aliases:
OperationObject:
Expand Down Expand Up @@ -361,3 +362,27 @@ rules:
allowedStartVerbs:
- Delete
- Remove
xgen-IPA-117-operation-summary-single-item-wording:
description: |
API Producers must use "One" when referring to a single item instead of "a" or "specified".

##### Implementation details
- The rule checks that the `summary` property of operations does not use the words "a", "specified" or "provided"
- This rule applies to all operations, including custom methods
##### Configuration
This rule includes a configuration option:
- `preferredWords`: List of words that the operation summary should use for single items, defaults to `['one']`. Only used for error messages
- `forbiddenWords`: List of words (lowercase) that the operation summary should not use, defaults to `['a', 'specified']`
message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-117-operation-summary-single-item-wording'
severity: warn
given:
- '#OperationObject.summary'
then:
function: 'IPA117OperationSummarySingleItemWording'
functionOptions:
preferredWords:
- one
forbiddenWords:
- a
- specified
- provided
13 changes: 13 additions & 0 deletions tools/spectral/ipa/rulesets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,19 @@ In operation summaries, use 'Delete' when the operation is destroying a resource
This rule includes a configuration option:
- `allowedStartVerbs`: Allow list of verb that the operation summary can start with, defaults to `['Delete', 'Remove']`

#### xgen-IPA-117-operation-summary-single-item-wording

![warn](https://img.shields.io/badge/warning-yellow)
API Producers must use "One" when referring to a single item instead of "a" or "specified".

##### Implementation details
- The rule checks that the `summary` property of operations does not use the words "a", "specified" or "provided"
- This rule applies to all operations, including custom methods
##### Configuration
This rule includes a configuration option:
- `preferredWords`: List of words that the operation summary should use for single items, defaults to `['one']`. Only used for error messages
- `forbiddenWords`: List of words (lowercase) that the operation summary should not use, defaults to `['a', 'specified']`



### IPA-118
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { evaluateAndCollectAdoptionStatus, handleInternalError } from './utils/collectionUtils.js';
import { resolveObject } from './utils/componentUtils.js';

export default (input, { preferredWords, forbiddenWords }, { path, rule, documentInventory }) => {
const operationObjectPath = path.slice(0, -1);
const operationObject = resolveObject(documentInventory.resolved, operationObjectPath);

const errors = checkViolationsAndReturnErrors(input, preferredWords, forbiddenWords, operationObjectPath, rule.name);
return evaluateAndCollectAdoptionStatus(errors, rule.name, operationObject, operationObjectPath);
};

function checkViolationsAndReturnErrors(summary, preferredWords, forbiddenWords, path, ruleName) {
try {
const errors = [];
const words = summary.toLowerCase().split(' ');

forbiddenWords.forEach((forbiddenWord) => {
words.forEach((word) => {
if (word === forbiddenWord) {
if (preferredWords.length === 1) {
errors.push({
path,
message: `Operation summary referring to a single item must use "${preferredWords[0]}" instead of "${forbiddenWord}".`,
});
} else {
errors.push({
path,
message: `Operation summary referring to a single item must use one of the words [${preferredWords}] instead of ${forbiddenWords}.`,
});
}
}
});
});

return errors;
} catch (e) {
return handleInternalError(ruleName, path, e);
}
}
Loading