diff --git a/tools/spectral/ipa/__tests__/eachEnumValueMustBeUpperSnakeCase.test.js b/tools/spectral/ipa/__tests__/eachEnumValueMustBeUpperSnakeCase.test.js index 14854718a2..290efd35a7 100644 --- a/tools/spectral/ipa/__tests__/eachEnumValueMustBeUpperSnakeCase.test.js +++ b/tools/spectral/ipa/__tests__/eachEnumValueMustBeUpperSnakeCase.test.js @@ -3,7 +3,7 @@ import { DiagnosticSeverity } from '@stoplight/types'; testRule('xgen-IPA-123-enum-values-must-be-upper-snake-case', [ { - name: 'valid schema - components.schemas', + name: 'valid schema - components.schemas.property', document: { components: { schemas: { @@ -21,18 +21,18 @@ testRule('xgen-IPA-123-enum-values-must-be-upper-snake-case', [ errors: [], }, { - name: 'invalid schema with exception - components.schemas', + name: 'invalid schema with exception - components.schemas.property', document: { components: { schemas: { SchemaName: { - 'x-xgen-IPA-exception': { - 'xgen-IPA-123-enum-values-must-be-upper-snake-case': 'reason', - }, properties: { exampleProperty: { enum: ['exampleA', 'exampleB'], type: 'string', + 'x-xgen-IPA-exception': { + 'xgen-IPA-123-enum-values-must-be-upper-snake-case': 'reason', + }, }, }, }, @@ -42,7 +42,7 @@ testRule('xgen-IPA-123-enum-values-must-be-upper-snake-case', [ errors: [], }, { - name: 'invalid schema - components.schemas', + name: 'invalid schema - components.schemas.property', document: { components: { schemas: { @@ -60,14 +60,72 @@ testRule('xgen-IPA-123-enum-values-must-be-upper-snake-case', [ errors: [ { code: 'xgen-IPA-123-enum-values-must-be-upper-snake-case', - message: 'exampleA enum value must be UPPER_SNAKE_CASE. http://go/ipa/123', - path: ['components', 'schemas', 'SchemaName', 'properties', 'exampleProperty', 'enum', '0'], + message: 'enum[0]:exampleA enum value must be UPPER_SNAKE_CASE. http://go/ipa/123', + path: ['components', 'schemas', 'SchemaName', 'properties', 'exampleProperty'], + severity: DiagnosticSeverity.Warning, + }, + { + code: 'xgen-IPA-123-enum-values-must-be-upper-snake-case', + message: 'enum[1]:exampleB enum value must be UPPER_SNAKE_CASE. http://go/ipa/123', + path: ['components', 'schemas', 'SchemaName', 'properties', 'exampleProperty'], + severity: DiagnosticSeverity.Warning, + }, + ], + }, + { + name: 'valid schema - components.schemas', + document: { + components: { + schemas: { + SchemaName: { + enum: ['EXAMPLE_A', 'EXAMPLE_B'], + type: 'string', + }, + }, + }, + }, + errors: [], + }, + { + name: 'invalid schema with exception - components.schemas', + document: { + components: { + schemas: { + SchemaName: { + 'x-xgen-IPA-exception': { + 'xgen-IPA-123-enum-values-must-be-upper-snake-case': 'reason', + }, + enum: ['exampleA', 'exampleB'], + type: 'string', + }, + }, + }, + }, + errors: [], + }, + { + name: 'invalid schema - components.schemas', + document: { + components: { + schemas: { + SchemaName: { + enum: ['exampleA', 'exampleB'], + type: 'string', + }, + }, + }, + }, + errors: [ + { + code: 'xgen-IPA-123-enum-values-must-be-upper-snake-case', + message: 'enum[0]:exampleA enum value must be UPPER_SNAKE_CASE. http://go/ipa/123', + path: ['components', 'schemas', 'SchemaName'], severity: DiagnosticSeverity.Warning, }, { code: 'xgen-IPA-123-enum-values-must-be-upper-snake-case', - message: 'exampleB enum value must be UPPER_SNAKE_CASE. http://go/ipa/123', - path: ['components', 'schemas', 'SchemaName', 'properties', 'exampleProperty', 'enum', '1'], + message: 'enum[1]:exampleB enum value must be UPPER_SNAKE_CASE. http://go/ipa/123', + path: ['components', 'schemas', 'SchemaName'], severity: DiagnosticSeverity.Warning, }, ], @@ -136,14 +194,14 @@ testRule('xgen-IPA-123-enum-values-must-be-upper-snake-case', [ errors: [ { code: 'xgen-IPA-123-enum-values-must-be-upper-snake-case', - message: 'exampleA enum value must be UPPER_SNAKE_CASE. http://go/ipa/123', - path: ['paths', '/a/{exampleId}', 'get', 'parameters', '0', 'schema', 'enum', '0'], + message: 'enum[0]:exampleA enum value must be UPPER_SNAKE_CASE. http://go/ipa/123', + path: ['paths', '/a/{exampleId}', 'get', 'parameters', '0', 'schema'], severity: DiagnosticSeverity.Warning, }, { code: 'xgen-IPA-123-enum-values-must-be-upper-snake-case', - message: 'exampleB enum value must be UPPER_SNAKE_CASE. http://go/ipa/123', - path: ['paths', '/a/{exampleId}', 'get', 'parameters', '0', 'schema', 'enum', '1'], + message: 'enum[1]:exampleB enum value must be UPPER_SNAKE_CASE. http://go/ipa/123', + path: ['paths', '/a/{exampleId}', 'get', 'parameters', '0', 'schema'], severity: DiagnosticSeverity.Warning, }, ], diff --git a/tools/spectral/ipa/rulesets/functions/eachEnumValueMustBeUpperSnakeCase.js b/tools/spectral/ipa/rulesets/functions/eachEnumValueMustBeUpperSnakeCase.js index 1850a44ca2..ece14ffb3f 100644 --- a/tools/spectral/ipa/rulesets/functions/eachEnumValueMustBeUpperSnakeCase.js +++ b/tools/spectral/ipa/rulesets/functions/eachEnumValueMustBeUpperSnakeCase.js @@ -1,13 +1,17 @@ import { hasException } from './utils/exceptions.js'; -import { getSchemaPath, resolveObject } from './utils/componentUtils.js'; +import { resolveObject } from './utils/componentUtils.js'; import { casing } from '@stoplight/spectral-functions'; const RULE_NAME = 'xgen-IPA-123-enum-values-must-be-upper-snake-case'; const ERROR_MESSAGE = 'enum value must be UPPER_SNAKE_CASE.'; +export function getSchemaPathFromEnumPath(path) { + return path.slice(0, path.length - 1); +} + export default (input, _, { path, documentInventory }) => { const oas = documentInventory.resolved; - const schemaPath = getSchemaPath(path); + const schemaPath = getSchemaPathFromEnumPath(path); const schemaObject = resolveObject(oas, schemaPath); if (hasException(schemaObject, RULE_NAME)) { return; @@ -19,8 +23,8 @@ export default (input, _, { path, documentInventory }) => { if (isUpperSnakeCase) { errors.push({ - path: [...path, index], - message: `${enumValue} ${ERROR_MESSAGE} `, + path: schemaPath, + message: `enum[${index}]:${enumValue} ${ERROR_MESSAGE} `, }); } }); diff --git a/tools/spectral/ipa/rulesets/functions/utils/componentUtils.js b/tools/spectral/ipa/rulesets/functions/utils/componentUtils.js index 2eb2f86d9e..494537218a 100644 --- a/tools/spectral/ipa/rulesets/functions/utils/componentUtils.js +++ b/tools/spectral/ipa/rulesets/functions/utils/componentUtils.js @@ -13,33 +13,6 @@ export function isPathParam(str) { return pathParamRegEx.test(str) || pathParamWithCustomMethodRegEx.test(str); } -/** - * Extracts the schema path from the given JSONPath array. - * - * This function is designed to handle two types of paths commonly encountered in OpenAPI definitions: - * - * 1. **Component Schema Paths**: - * - Represented as: `components.schemas.schemaName.*.enum` - * - This path indicates that the enum is defined within a schema under `components.schemas`. - * - The function returns the first three elements (`["components", "schemas", "schemaName"]`). - * - * 2. **Parameter Schema Paths**: - * - Represented as: `paths.*.method.parameters[*].schema.enum` - * - This path indicates that the enum is part of a parameter's schema in an operation. - * - The function identifies the location of `schema` in the path and returns everything up to (and including) it. - * - * @param {string[]} path - An array representing the JSONPath structure of the OpenAPI definition. - * @returns {string[]} The truncated path pointing to the schema object. - */ -export function getSchemaPath(path) { - if (path.includes('components')) { - return path.slice(0, 3); - } else if (path.includes('paths')) { - const index = path.findIndex((item) => item === 'schema'); - return path.slice(0, index + 1); - } -} - /** * Resolves the value of a nested property within an OpenAPI structure using a given path. *