Skip to content

Commit 0a6fcb9

Browse files
CLOUDP-271999: Fix on IPA-112 rule implementation
1 parent 9884dbe commit 0a6fcb9

File tree

5 files changed

+288
-6
lines changed

5 files changed

+288
-6
lines changed

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

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,4 +177,147 @@ testRule('xgen-IPA-112-boolean-field-names-avoid-is-prefix', [
177177
},
178178
errors: [],
179179
},
180+
{
181+
name: 'schema with referenced property types',
182+
document: {
183+
components: {
184+
schemas: {
185+
BooleanProperties: {
186+
type: 'object',
187+
properties: {
188+
active: { type: 'boolean' },
189+
isEnabled: { type: 'boolean' },
190+
disabled: { type: 'boolean' },
191+
},
192+
},
193+
User: {
194+
type: 'object',
195+
properties: {
196+
userId: { type: 'string' },
197+
name: { type: 'string' },
198+
status: { $ref: '#/components/schemas/BooleanProperties' },
199+
isAdmin: { type: 'boolean' },
200+
preferences: {
201+
type: 'object',
202+
properties: {
203+
isEmailNotificationsEnabled: { type: 'boolean' },
204+
darkMode: { type: 'boolean' },
205+
},
206+
},
207+
},
208+
},
209+
},
210+
},
211+
paths: {
212+
'/users/{userId}': {
213+
get: {
214+
responses: {
215+
200: {
216+
content: {
217+
'application/vnd.atlas.2024-01-01+json': {
218+
schema: {
219+
type: 'object',
220+
properties: {
221+
user: { $ref: '#/components/schemas/User' },
222+
isCached: { type: 'boolean' },
223+
},
224+
},
225+
},
226+
},
227+
},
228+
},
229+
},
230+
},
231+
},
232+
},
233+
errors: [
234+
{
235+
code: 'xgen-IPA-112-boolean-field-names-avoid-is-prefix',
236+
message: 'Boolean field "isEnabled" should not use the "is" prefix. Use "enabled" instead.',
237+
path: ['components', 'schemas', 'BooleanProperties', 'properties', 'isEnabled'],
238+
severity: DiagnosticSeverity.Warning,
239+
},
240+
{
241+
code: 'xgen-IPA-112-boolean-field-names-avoid-is-prefix',
242+
message: 'Boolean field "isAdmin" should not use the "is" prefix. Use "admin" instead.',
243+
path: ['components', 'schemas', 'User', 'properties', 'isAdmin'],
244+
severity: DiagnosticSeverity.Warning,
245+
},
246+
{
247+
code: 'xgen-IPA-112-boolean-field-names-avoid-is-prefix',
248+
message:
249+
'Boolean field "isEmailNotificationsEnabled" should not use the "is" prefix. Use "emailNotificationsEnabled" instead.',
250+
path: [
251+
'components',
252+
'schemas',
253+
'User',
254+
'properties',
255+
'preferences',
256+
'properties',
257+
'isEmailNotificationsEnabled',
258+
],
259+
severity: DiagnosticSeverity.Warning,
260+
},
261+
{
262+
code: 'xgen-IPA-112-boolean-field-names-avoid-is-prefix',
263+
message: 'Boolean field "isCached" should not use the "is" prefix. Use "cached" instead.',
264+
path: [
265+
'paths',
266+
'/users/{userId}',
267+
'get',
268+
'responses',
269+
'200',
270+
'content',
271+
'application/vnd.atlas.2024-01-01+json',
272+
'schema',
273+
'properties',
274+
'isCached',
275+
],
276+
severity: DiagnosticSeverity.Warning,
277+
},
278+
],
279+
},
280+
{
281+
name: 'schema with referenced property and exceptions',
282+
document: {
283+
components: {
284+
schemas: {
285+
UserSettings: {
286+
type: 'object',
287+
properties: {
288+
isVerified: {
289+
type: 'boolean',
290+
'x-xgen-IPA-exception': {
291+
'xgen-IPA-112-boolean-field-names-avoid-is-prefix': 'Reason',
292+
},
293+
},
294+
isMfaEnabled: { type: 'boolean' },
295+
},
296+
},
297+
UserProfile: {
298+
type: 'object',
299+
properties: {
300+
name: { type: 'string' },
301+
email: { type: 'string' },
302+
settings: { $ref: '#/components/schemas/UserSettings' },
303+
isPremiumUser: {
304+
type: 'boolean',
305+
'x-xgen-IPA-exception': {
306+
'xgen-IPA-112-boolean-field-names-avoid-is-prefix': 'Reason',
307+
},
308+
},
309+
},
310+
},
311+
},
312+
},
313+
},
314+
errors: [
315+
{
316+
code: 'xgen-IPA-112-boolean-field-names-avoid-is-prefix',
317+
message: 'Boolean field "isMfaEnabled" should not use the "is" prefix. Use "mfaEnabled" instead.',
318+
path: ['components', 'schemas', 'UserSettings', 'properties', 'isMfaEnabled'],
319+
severity: DiagnosticSeverity.Warning,
320+
},
321+
],
322+
},
180323
]);

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

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,129 @@ testRule('xgen-IPA-112-field-names-are-camel-case', [
461461
},
462462
errors: [],
463463
},
464+
{
465+
name: 'schema with referenced property and nested objects',
466+
document: {
467+
components: {
468+
schemas: {
469+
Address: {
470+
type: 'object',
471+
properties: {
472+
State_Name: { type: 'string' },
473+
zipCode: { type: 'string' },
474+
},
475+
},
476+
User: {
477+
type: 'object',
478+
properties: {
479+
userId: { type: 'string' },
480+
firstName: { type: 'string' },
481+
Last_Name: { type: 'string' },
482+
primaryAddress: { $ref: '#/components/schemas/Address' },
483+
contactInfo: {
484+
type: 'object',
485+
properties: {
486+
email_address: { type: 'string' },
487+
phoneNumber: { type: 'string' },
488+
},
489+
},
490+
},
491+
},
492+
},
493+
},
494+
paths: {
495+
'/users/{userId}': {
496+
get: {
497+
responses: {
498+
200: {
499+
content: {
500+
'application/vnd.atlas.2024-01-01+json': {
501+
schema: {
502+
type: 'object',
503+
properties: {
504+
user: { $ref: '#/components/schemas/User' },
505+
REQUEST_ID: { type: 'string' },
506+
},
507+
},
508+
},
509+
},
510+
},
511+
},
512+
},
513+
},
514+
},
515+
},
516+
errors: [
517+
{
518+
code: 'xgen-IPA-112-field-names-are-camel-case',
519+
message: 'Property "State_Name" must use camelCase format.',
520+
path: ['components', 'schemas', 'Address', 'properties', 'State_Name'],
521+
severity: DiagnosticSeverity.Warning,
522+
},
523+
{
524+
code: 'xgen-IPA-112-field-names-are-camel-case',
525+
message: 'Property "Last_Name" must use camelCase format.',
526+
path: ['components', 'schemas', 'User', 'properties', 'Last_Name'],
527+
severity: DiagnosticSeverity.Warning,
528+
},
529+
{
530+
code: 'xgen-IPA-112-field-names-are-camel-case',
531+
message: 'Property "email_address" must use camelCase format.',
532+
path: ['components', 'schemas', 'User', 'properties', 'contactInfo', 'properties', 'email_address'],
533+
severity: DiagnosticSeverity.Warning,
534+
},
535+
{
536+
code: 'xgen-IPA-112-field-names-are-camel-case',
537+
message: 'Property "REQUEST_ID" must use camelCase format.',
538+
path: [
539+
'paths',
540+
'/users/{userId}',
541+
'get',
542+
'responses',
543+
'200',
544+
'content',
545+
'application/vnd.atlas.2024-01-01+json',
546+
'schema',
547+
'properties',
548+
'REQUEST_ID',
549+
],
550+
severity: DiagnosticSeverity.Warning,
551+
},
552+
],
553+
},
554+
{
555+
name: 'schema with referenced property and exceptions',
556+
document: {
557+
components: {
558+
schemas: {
559+
ApiSettings: {
560+
type: 'object',
561+
properties: {
562+
API_KEY: {
563+
type: 'string',
564+
'x-xgen-IPA-exception': {
565+
'xgen-IPA-112-field-names-are-camel-case': 'Reason',
566+
},
567+
},
568+
},
569+
},
570+
UserProfile: {
571+
type: 'object',
572+
properties: {
573+
name: { type: 'string' },
574+
email: { type: 'string' },
575+
apiSettings: { $ref: '#/components/schemas/ApiSettings' },
576+
User_Status: {
577+
type: 'string',
578+
'x-xgen-IPA-exception': {
579+
'xgen-IPA-112-field-names-are-camel-case': 'Reason',
580+
},
581+
},
582+
},
583+
},
584+
},
585+
},
586+
},
587+
errors: [],
588+
},
464589
]);

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@ import { splitCamelCase } from './utils/schemaUtils.js';
1111
const RULE_NAME = 'xgen-IPA-112-avoid-project-field-names';
1212

1313
export default (input, options, { path, documentInventory }) => {
14-
const oas = documentInventory.resolved;
14+
const oas = documentInventory.unresolved;
1515
const property = resolveObject(oas, path);
1616

17+
// Skip schema references ($ref):
18+
// Referenced schemas are validated separately to prevent duplicate violations
19+
if (!property) {
20+
return;
21+
}
22+
1723
const ignoreList = options?.ignore || [];
1824
if (ignoreList.some((ignoreTerm) => input.toLowerCase().includes(ignoreTerm))) {
1925
return;

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ const RULE_NAME = 'xgen-IPA-112-boolean-field-names-avoid-is-prefix';
66
const IS_PREFIX_REGEX = /^is[A-Z]/;
77

88
export default (input, options, { path, documentInventory }) => {
9-
const oas = documentInventory.resolved;
9+
const oas = documentInventory.unresolved;
1010
const property = resolveObject(oas, path);
1111

12-
if (hasException(property, RULE_NAME)) {
13-
collectException(property, RULE_NAME, path);
12+
// Skip schema references ($ref) and non-boolean fields:
13+
// Referenced schemas are validated separately to prevent duplicate violations
14+
if (!property || property.type !== 'boolean') {
1415
return;
1516
}
1617

17-
if (property.type !== 'boolean') {
18+
if (hasException(property, RULE_NAME)) {
19+
collectException(property, RULE_NAME, path);
1820
return;
1921
}
2022

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@ import { resolveObject } from './utils/componentUtils.js';
66
const RULE_NAME = 'xgen-IPA-112-field-names-are-camel-case';
77

88
export default (input, options, { path, documentInventory }) => {
9-
const oas = documentInventory.resolved;
9+
const oas = documentInventory.unresolved;
1010
const property = resolveObject(oas, path);
1111

12+
// Skip schema references ($ref):
13+
// Referenced schemas are validated separately to prevent duplicate violations
14+
if (!property) {
15+
return;
16+
}
17+
1218
if (hasException(property, RULE_NAME)) {
1319
collectException(property, RULE_NAME, path);
1420
return;

0 commit comments

Comments
 (0)