-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(new-rule): ibm-operation-summary-length (#663)
Adds a rule that verifies operation summaries are 80 characters or less in length, based on the summary writing guidance in the API Handbook. Signed-off-by: Dustin Popp <dpopp07@gmail.com>
- Loading branch information
Showing
8 changed files
with
171 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
packages/ruleset/src/functions/operation-summary-length.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* Copyright 2024 IBM Corporation. | ||
* SPDX-License-Identifier: Apache2.0 | ||
*/ | ||
|
||
const { LoggerFactory } = require('../utils'); | ||
|
||
let ruleId; | ||
let logger; | ||
|
||
/** | ||
* The implementation for this rule makes assumptions that are dependent on the | ||
* presence of the following other rules: | ||
* | ||
* - operation-summary: all operations define a non-empty summary | ||
*/ | ||
|
||
module.exports = function (summary, _opts, context) { | ||
if (!logger) { | ||
ruleId = context.rule.name; | ||
logger = LoggerFactory.getInstance().getLogger(ruleId); | ||
} | ||
return checkSummaryLength(summary, context.path); | ||
}; | ||
|
||
function checkSummaryLength(summary, path) { | ||
logger.debug( | ||
`${ruleId}: checking operation summary at location: ${path.join('.')}` | ||
); | ||
|
||
if (summary && summary.length > 80) { | ||
return [ | ||
{ | ||
message: 'Operation summaries must be 80 characters or less in length', | ||
path, | ||
}, | ||
]; | ||
} | ||
|
||
return []; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* Copyright 2024 IBM Corporation. | ||
* SPDX-License-Identifier: Apache2.0 | ||
*/ | ||
|
||
const { | ||
operations, | ||
} = require('@ibm-cloud/openapi-ruleset-utilities/src/collections'); | ||
const { oas3 } = require('@stoplight/spectral-formats'); | ||
const { operationSummaryLength } = require('../functions'); | ||
|
||
module.exports = { | ||
description: 'Operation summaries must be 80 characters or less in length', | ||
given: operations.map(op => `${op}.summary`), | ||
severity: 'error', | ||
formats: [oas3], | ||
resolved: true, | ||
then: { | ||
function: operationSummaryLength, | ||
}, | ||
}; |
2 changes: 1 addition & 1 deletion
2
...es/ruleset/test/operation-summary.test.js → ...set/test/operation-summary-exists.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* Copyright 2024 IBM Corporation. | ||
* SPDX-License-Identifier: Apache2.0 | ||
*/ | ||
|
||
const { operationSummaryLength } = require('../src/rules'); | ||
const { makeCopy, rootDocument, testRule, severityCodes } = require('./utils'); | ||
|
||
const rule = operationSummaryLength; | ||
const ruleId = 'ibm-operation-summary'; | ||
const expectedSeverity = severityCodes.error; | ||
const expectedMsg = | ||
'Operation summaries must be 80 characters or less in length'; | ||
|
||
describe(`Spectral rule: ${ruleId}`, () => { | ||
describe('Should not yield errors', () => { | ||
it('Clean spec', async () => { | ||
const results = await testRule(ruleId, rule, rootDocument); | ||
expect(results).toHaveLength(0); | ||
}); | ||
|
||
it('Operation has no summary - handled by separate rule', async () => { | ||
const testDocument = makeCopy(rootDocument); | ||
|
||
delete testDocument.paths['/v1/drinks'].post.summary; | ||
|
||
const results = await testRule(ruleId, rule, testDocument); | ||
expect(results).toHaveLength(0); | ||
}); | ||
}); | ||
|
||
describe('Should yield errors', () => { | ||
it('Operation summary is greater than 80 characters', async () => { | ||
const testDocument = makeCopy(rootDocument); | ||
|
||
testDocument.paths['/v1/drinks'].post.summary = | ||
'This operation summary for the operation to create a new drink is simply too long'; | ||
|
||
const results = await testRule(ruleId, rule, testDocument); | ||
expect(results).toHaveLength(1); | ||
for (const r of results) { | ||
expect(r.code).toBe(ruleId); | ||
expect(r.message).toBe(expectedMsg); | ||
expect(r.severity).toBe(expectedSeverity); | ||
expect(r.path.join('.')).toBe('paths./v1/drinks.post.summary'); | ||
} | ||
}); | ||
}); | ||
}); |