Skip to content

Commit f22d157

Browse files
feat: display numeric constraints for parameters
Add formatNumericConstraints function to display minimum, maximum, exclusiveMinimum, and exclusiveMaximum constraints for path and query parameters in the documentation. - Add constraint formatting with proper mathematical symbols (, , >, <) - Support range notation for combined constraints [min, max], (min, max) - Display constraints in parameter description area - Add comprehensive unit tests for all constraint types - Work in both documentation view and Try it out mode
1 parent 443c011 commit f22d157

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

src/core/components/parameter-row.jsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,48 @@ import win from "core/window"
66
import { getExtensions, getCommonExtensions, numberToString, stringify, isEmptyValue } from "core/utils"
77
import getParameterSchema from "core/utils/get-parameter-schema.js"
88

9+
// Helper function to format numeric constraints
10+
const formatNumericConstraints = (schema) => {
11+
if (!schema) return null
12+
13+
const minimum = schema.get ? schema.get("minimum") : schema.minimum
14+
const maximum = schema.get ? schema.get("maximum") : schema.maximum
15+
const exclusiveMinimum = schema.get ? schema.get("exclusiveMinimum") : schema.exclusiveMinimum
16+
const exclusiveMaximum = schema.get ? schema.get("exclusiveMaximum") : schema.exclusiveMaximum
17+
18+
const hasMinimum = typeof minimum === "number"
19+
const hasMaximum = typeof maximum === "number"
20+
const hasExclusiveMinimum = typeof exclusiveMinimum === "number"
21+
const hasExclusiveMaximum = typeof exclusiveMaximum === "number"
22+
23+
if (!hasMinimum && !hasMaximum && !hasExclusiveMinimum && !hasExclusiveMaximum) {
24+
return null
25+
}
26+
27+
const isMinExclusive = hasExclusiveMinimum && (!hasMinimum || minimum < exclusiveMinimum)
28+
const isMaxExclusive = hasExclusiveMaximum && (!hasMaximum || maximum > exclusiveMaximum)
29+
30+
if ((hasMinimum || hasExclusiveMinimum) && (hasMaximum || hasExclusiveMaximum)) {
31+
const minSymbol = isMinExclusive ? "(" : "["
32+
const maxSymbol = isMaxExclusive ? ")" : "]"
33+
const minValue = isMinExclusive ? exclusiveMinimum : minimum
34+
const maxValue = isMaxExclusive ? exclusiveMaximum : maximum
35+
return `${minSymbol}${minValue}, ${maxValue}${maxSymbol}`
36+
}
37+
if (hasMinimum || hasExclusiveMinimum) {
38+
const minSymbol = isMinExclusive ? ">" : "≥"
39+
const minValue = isMinExclusive ? exclusiveMinimum : minimum
40+
return `${minSymbol} ${minValue}`
41+
}
42+
if (hasMaximum || hasExclusiveMaximum) {
43+
const maxSymbol = isMaxExclusive ? "<" : "≤"
44+
const maxValue = isMaxExclusive ? exclusiveMaximum : maximum
45+
return `${maxSymbol} ${maxValue}`
46+
}
47+
48+
return null
49+
}
50+
951
export default class ParameterRow extends Component {
1052
static propTypes = {
1153
onChange: PropTypes.func.isRequired,
@@ -352,6 +394,13 @@ export default class ParameterRow extends Component {
352394
: null
353395
}
354396

397+
{(() => {
398+
const numericConstraint = formatNumericConstraints(schema)
399+
return numericConstraint ? (
400+
<Markdown className="parameter__constraint" source={`<i>Constraints</i> : ${numericConstraint}`}/>
401+
) : null
402+
})()}
403+
355404
{(isFormData && !isFormDataSupported) && <div>Error: your browser does not support FormData</div>}
356405

357406
{

test/unit/components/parameter-row.jsx

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,118 @@ describe("bug #5573: zero default and example values", function () {
364364
expect(props.onChange).toHaveBeenCalledWith(paramValue, "0", false)
365365
})
366366
})
367+
368+
describe("parameter constraints display", () => {
369+
const createProps = ({ param, isOAS3 }) => {
370+
const getSystem = () => ({
371+
getComponent: () => "div",
372+
specSelectors: {
373+
parameterWithMetaByIdentity: () => param,
374+
isOAS3: () => isOAS3,
375+
isSwagger2: () => !isOAS3,
376+
},
377+
fn: {
378+
memoizedSampleFromSchema,
379+
memoizedCreateXMLExample,
380+
getSchemaObjectTypeLabel,
381+
getSchemaObjectType,
382+
getJsonSampleSchema: makeGetJsonSampleSchema(getSystem),
383+
getYamlSampleSchema: makeGetYamlSampleSchema(getSystem),
384+
getXmlSampleSchema: makeGetXmlSampleSchema(getSystem),
385+
getSampleSchema: makeGetSampleSchema(getSystem),
386+
mergeJsonSchema,
387+
},
388+
oas3Selectors: { activeExamplesMember: () => {} },
389+
getConfigs: () => ({}),
390+
})
391+
392+
return {
393+
...getSystem(),
394+
param,
395+
rawParam: param,
396+
pathMethod: [],
397+
}
398+
}
399+
400+
it("should display minimum constraint", () => {
401+
const param = fromJS({
402+
name: "id",
403+
in: "path",
404+
required: true,
405+
schema: {
406+
type: "integer",
407+
minimum: 1
408+
}
409+
})
410+
411+
const props = createProps({ param, isOAS3: true })
412+
const wrapper = render(<ParameterRow {...props} />)
413+
414+
// Check if constraint text is rendered somewhere in the component
415+
expect(wrapper.html()).toContain("≥ 1")
416+
})
417+
418+
it("should display maximum constraint", () => {
419+
const param = fromJS({
420+
name: "limit",
421+
in: "query",
422+
schema: {
423+
type: "integer",
424+
maximum: 100
425+
}
426+
})
427+
428+
const props = createProps({ param, isOAS3: true })
429+
const wrapper = render(<ParameterRow {...props} />)
430+
431+
expect(wrapper.html()).toContain("≤ 100")
432+
})
433+
434+
it("should display exclusive minimum constraint", () => {
435+
const param = fromJS({
436+
name: "price",
437+
in: "query",
438+
schema: {
439+
type: "number",
440+
exclusiveMinimum: 0
441+
}
442+
})
443+
444+
const props = createProps({ param, isOAS3: true })
445+
const wrapper = render(<ParameterRow {...props} />)
446+
447+
expect(wrapper.html()).toContain("> 0")
448+
})
449+
450+
it("should display range constraints", () => {
451+
const param = fromJS({
452+
name: "range",
453+
in: "query",
454+
schema: {
455+
type: "integer",
456+
minimum: 1,
457+
maximum: 100
458+
}
459+
})
460+
461+
const props = createProps({ param, isOAS3: true })
462+
const wrapper = render(<ParameterRow {...props} />)
463+
464+
expect(wrapper.html()).toContain("[1, 100]")
465+
})
466+
467+
it("should not display constraints when none are present", () => {
468+
const param = fromJS({
469+
name: "name",
470+
in: "query",
471+
schema: {
472+
type: "string"
473+
}
474+
})
475+
476+
const props = createProps({ param, isOAS3: true })
477+
const wrapper = render(<ParameterRow {...props} />)
478+
479+
expect(wrapper.html()).not.toContain("Constraints")
480+
})
481+
})

0 commit comments

Comments
 (0)