diff --git a/demo/openapi.yaml b/demo/openapi.yaml index 1a06f4f6d6..fc3ce0731c 100644 --- a/demo/openapi.yaml +++ b/demo/openapi.yaml @@ -296,6 +296,8 @@ paths: style: form schema: type: array + minItems: 1 + maxItems: 3 items: type: string enum: @@ -784,6 +786,7 @@ components: photoUrls: description: The list of URL to a cute photos featuring pet type: array + maxItems: 20 xml: name: photoUrl wrapped: true @@ -796,6 +799,7 @@ components: tags: description: Tags attached to the pet type: array + minItems: 1 xml: name: tag wrapped: true diff --git a/src/utils/__tests__/openapi.test.ts b/src/utils/__tests__/openapi.test.ts index 34e847d213..c6ce7838be 100644 --- a/src/utils/__tests__/openapi.test.ts +++ b/src/utils/__tests__/openapi.test.ts @@ -2,6 +2,7 @@ import { detectType, getOperationSummary, getStatusCodeType, + humanizeConstraints, isOperationName, isPrimitiveType, mergeParams, @@ -321,4 +322,35 @@ describe('Utils', () => { expect(servers[2].url).toEqual('http://127.0.0.3'); }); }); + + describe('openapi humanizeConstraints', () => { + const itemConstraintSchema = ( + min: number | undefined = undefined, + max: number | undefined = undefined, + ) => ({ type: 'array', minItems: min, maxItems: max }); + + it('should not have a humanized constraint without schema constraints', () => { + expect(humanizeConstraints(itemConstraintSchema())).toHaveLength(0); + }); + + it('should have a humanized constraint when minItems is set', () => { + expect(humanizeConstraints(itemConstraintSchema(2))).toContain('>= 2 items'); + }); + + it('should have a humanized constraint when maxItems is set', () => { + expect(humanizeConstraints(itemConstraintSchema(undefined, 8))).toContain('<= 8 items'); + }); + + it('should have a humanized constraint when minItems and maxItems are both set', () => { + expect(humanizeConstraints(itemConstraintSchema(2, 8))).toContain('[ 2 .. 8 ] items'); + }); + + it('should have a humanized constraint when minItems and maxItems are the same', () => { + expect(humanizeConstraints(itemConstraintSchema(7, 7))).toContain('7 items'); + }); + + it('should have a humazined constraint when justMinItems is set, and it is equal to 1', () => { + expect(humanizeConstraints(itemConstraintSchema(1))).toContain('non-empty'); + }); + }); }); diff --git a/src/utils/openapi.ts b/src/utils/openapi.ts index 7e1721323f..a9bd35e2b0 100644 --- a/src/utils/openapi.ts +++ b/src/utils/openapi.ts @@ -141,29 +141,44 @@ export function isNamedDefinition(pointer?: string): boolean { return /^#\/components\/schemas\/[^\/]+$/.test(pointer || ''); } -export function humanizeConstraints(schema: OpenAPISchema): string[] { - const res: string[] = []; - +function humanizeRangeConstraint( + description: string, + min: number | undefined, + max: number | undefined, +): string | undefined { let stringRange; - if (schema.minLength !== undefined && schema.maxLength !== undefined) { - if (schema.minLength === schema.maxLength) { - stringRange = `${schema.minLength} characters`; + if (min !== undefined && max !== undefined) { + if (min === max) { + stringRange = `${min} ${description}`; } else { - stringRange = `[ ${schema.minLength} .. ${schema.maxLength} ] characters`; + stringRange = `[ ${min} .. ${max} ] ${description}`; } - } else if (schema.maxLength !== undefined) { - stringRange = `<= ${schema.maxLength} characters`; - } else if (schema.minLength !== undefined) { - if (schema.minLength === 1) { + } else if (max !== undefined) { + stringRange = `<= ${max} ${description}`; + } else if (min !== undefined) { + if (min === 1) { stringRange = 'non-empty'; } else { - stringRange = `>= ${schema.minLength} characters`; + stringRange = `>= ${min} ${description}`; } } + + return stringRange; +} + +export function humanizeConstraints(schema: OpenAPISchema): string[] { + const res: string[] = []; + + const stringRange = humanizeRangeConstraint('characters', schema.minLength, schema.maxLength); if (stringRange !== undefined) { res.push(stringRange); } + const arrayRange = humanizeRangeConstraint('items', schema.minItems, schema.maxItems); + if (arrayRange !== undefined) { + res.push(arrayRange); + } + let numberRange; if (schema.minimum !== undefined && schema.maximum !== undefined) { numberRange = schema.exclusiveMinimum ? '( ' : '[ ';