Skip to content

Commit ad52670

Browse files
fix(ipa): exception reason formatting
1 parent fc7d470 commit ad52670

File tree

3 files changed

+45
-18
lines changed

3 files changed

+45
-18
lines changed

tools/spectral/ipa/__tests__/IPA005ExceptionExtensionFormat.test.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ testRule('xgen-IPA-005-exception-extension-format', [
88
paths: {
99
'/path': {
1010
'x-xgen-IPA-exception': {
11-
'xgen-IPA-100-rule-name': 'Exception',
11+
'xgen-IPA-100-rule-name': 'Exception.',
1212
},
1313
},
1414
'/nested': {
1515
post: {
1616
'x-xgen-IPA-exception': {
17-
'xgen-IPA-100-rule-name': 'Exception',
17+
'xgen-IPA-100-rule-name': 'Exception.',
1818
},
1919
},
2020
},
@@ -51,26 +51,26 @@ testRule('xgen-IPA-005-exception-extension-format', [
5151
errors: [
5252
{
5353
code: 'xgen-IPA-005-exception-extension-format',
54-
message: 'IPA exceptions must have a valid rule name and a reason.',
54+
message: 'IPA exceptions must have a valid key with xgen-IPA- prefix.',
5555
path: ['paths', '/path1', 'x-xgen-IPA-exception'],
5656
severity: DiagnosticSeverity.Error,
5757
},
5858
{
5959
code: 'xgen-IPA-005-exception-extension-format',
60-
message: 'IPA exceptions must have a valid rule name and a reason.',
61-
path: ['paths', '/path2', 'x-xgen-IPA-exception', 'xgen-IPA-100-rule-name'],
60+
message: 'IPA exceptions must have a non-empty reason that starts with uppercase and ends with a full stop.',
61+
path: ['paths', '/path2', 'x-xgen-IPA-exception'],
6262
severity: DiagnosticSeverity.Error,
6363
},
6464
{
6565
code: 'xgen-IPA-005-exception-extension-format',
66-
message: 'IPA exceptions must have a valid rule name and a reason.',
67-
path: ['paths', '/path3', 'x-xgen-IPA-exception', 'invalid-rule-name'],
66+
message: 'IPA exceptions must have a valid key with xgen-IPA- prefix.',
67+
path: ['paths', '/path3', 'x-xgen-IPA-exception'],
6868
severity: DiagnosticSeverity.Error,
6969
},
7070
{
7171
code: 'xgen-IPA-005-exception-extension-format',
72-
message: 'IPA exceptions must have a valid rule name and a reason.',
73-
path: ['paths', '/path4', 'x-xgen-IPA-exception', 'xgen-IPA-100-rule-name'],
72+
message: 'IPA exceptions must have a non-empty reason that starts with uppercase and ends with a full stop.',
73+
path: ['paths', '/path4', 'x-xgen-IPA-exception'],
7474
severity: DiagnosticSeverity.Error,
7575
},
7676
],

tools/spectral/ipa/rulesets/IPA-005.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ rules:
1212
##### Implementation details
1313
Rule checks for the following conditions:
1414
- Exception rule names must start with 'xgen-IPA-' prefix
15-
- Each exception must include a non-empty reason as a string
15+
- Each exception must include a non-empty reason as a string that starts with uppercase and ends with a full stop
1616
- This rule itself does not allow exceptions
1717
message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-005-exception-extension-format'
1818
severity: error

tools/spectral/ipa/rulesets/functions/IPA005ExceptionExtensionFormat.js

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
import { evaluateAndCollectAdoptionStatusWithoutExceptions, handleInternalError } from './utils/collectionUtils.js';
1+
import {
2+
evaluateAndCollectAdoptionStatusWithoutExceptions,
3+
handleInternalError,
4+
} from './utils/collectionUtils.js';
25

3-
const ERROR_MESSAGE = 'IPA exceptions must have a valid rule name and a reason.';
6+
const ERROR_MESSAGE_RULENAME_FORMAT = 'IPA exceptions must have a valid key with xgen-IPA- prefix.';
7+
const ERROR_MESSAGE_REASON_FORMAT = 'IPA exceptions must have a non-empty reason that starts with uppercase and ends with a full stop.';
48
const RULE_NAME_PREFIX = 'xgen-IPA-';
59

610
// Note: This rule does not allow exceptions
@@ -10,21 +14,44 @@ export default (input, _, { path, rule }) => {
1014
return evaluateAndCollectAdoptionStatusWithoutExceptions(errors, ruleName, path);
1115
};
1216

13-
function isValidException(ruleName, reason) {
14-
return ruleName.startsWith(RULE_NAME_PREFIX) && typeof reason === 'string' && reason !== '';
17+
function isRuleNameValid(ruleName) {
18+
return ruleName.startsWith(RULE_NAME_PREFIX);
19+
}
20+
21+
function isReasonFormatValid(reason) {
22+
if (reason === null || reason === undefined || typeof reason !== 'string' || reason === '') {
23+
return false;
24+
}
25+
// Check if reason starts with uppercase letter
26+
if (!/^[A-Z]/.test(reason)) {
27+
return false;
28+
}
29+
30+
// Check if reason ends with a full stop
31+
if (!reason.endsWith('.')) {
32+
return false;
33+
}
34+
return true;
1535
}
1636

1737
function checkViolationsAndReturnErrors(input, path, ruleName) {
1838
const errors = [];
1939
try {
2040
const exemptedRules = Object.keys(input);
21-
exemptedRules.forEach((ruleName) => {
22-
const reason = input[ruleName];
23-
if (!isValidException(ruleName, reason)) {
41+
exemptedRules.forEach((key) => {
42+
const reason = input[key];
43+
if (!isRuleNameValid(key)) {
2444
errors.push({
2545
path: path.concat([ruleName]),
26-
message: ERROR_MESSAGE,
46+
message: ERROR_MESSAGE_RULENAME_FORMAT,
2747
});
48+
} else {
49+
if (!isReasonFormatValid(reason)) {
50+
errors.push({
51+
path: path.concat([ruleName]),
52+
message: ERROR_MESSAGE_REASON_FORMAT,
53+
});
54+
}
2855
}
2956
});
3057
return errors;

0 commit comments

Comments
 (0)