diff --git a/linting/config/.spectral-r4.yaml b/linting/config/.spectral-r4.yaml index 7b46c75..cb3989e 100644 --- a/linting/config/.spectral-r4.yaml +++ b/linting/config/.spectral-r4.yaml @@ -318,14 +318,17 @@ rules: recommended: true # Set to true/false to enable/disable this rule camara-parameter-name-casing-convention: - description: Parameter names (path and query) must be lowerCamelCase. + description: > + Parameter names (path and query) must be lowerCamelCase. The Design Guide's + filtering-operation suffixes (.gte, .gt, .lte, .lt) are allowed as an exact + tail on an otherwise lowerCamelCase name. message: "{{property}} is not lowerCamelCase: {{error}}" severity: warn given: $.paths[*][*].parameters[?(@.in != 'header')].name then: function: pattern functionOptions: - match: "^[a-z][a-zA-Z0-9]*$" + match: "^[a-z][a-zA-Z0-9]*(\\.(gte|gt|lte|lt))?$" recommended: true camara-schema-type-check: diff --git a/validation/tests/test_spectral_gap_rules.py b/validation/tests/test_spectral_gap_rules.py index 8526067..fc35e68 100644 --- a/validation/tests/test_spectral_gap_rules.py +++ b/validation/tests/test_spectral_gap_rules.py @@ -292,6 +292,52 @@ def test_parameter_name_header_excluded(self): findings = _run_spectral(spec) assert "camara-parameter-name-casing-convention" not in _codes(findings) + @pytest.mark.parametrize("suffix", ["gte", "gt", "lte", "lt"]) + def test_parameter_name_filter_suffix_passes(self, suffix): + # Design Guide ยง4.3.2 filtering-operation suffixes must not be flagged. + spec = _VALID_SPEC.replace( + " summary: Get test", + " parameters:\n" + f" - name: creationDate.{suffix}\n" + " in: query\n" + " required: false\n" + " schema:\n" + " type: string\n" + " summary: Get test", + ) + findings = _run_spectral(spec) + assert "camara-parameter-name-casing-convention" not in _codes(findings) + + def test_parameter_name_unrecognized_suffix_fails(self): + # Only the four documented filter suffixes are exempted. + spec = _VALID_SPEC.replace( + " summary: Get test", + " parameters:\n" + " - name: creationDate.foo\n" + " in: query\n" + " required: false\n" + " schema:\n" + " type: string\n" + " summary: Get test", + ) + findings = _run_spectral(spec) + assert "camara-parameter-name-casing-convention" in _codes(findings) + + def test_parameter_name_bad_base_with_valid_suffix_fails(self): + # A valid filter suffix does not excuse a badly-cased base name. + spec = _VALID_SPEC.replace( + " summary: Get test", + " parameters:\n" + " - name: CreationDate.gte\n" + " in: query\n" + " required: false\n" + " schema:\n" + " type: string\n" + " summary: Get test", + ) + findings = _run_spectral(spec) + assert "camara-parameter-name-casing-convention" in _codes(findings) + class TestGroupB: """Group B: Error code checks."""