Skip to content

Commit

Permalink
feat: show minProperties maxProperties (#2015)
Browse files Browse the repository at this point in the history
  • Loading branch information
anastasiia-developer committed May 20, 2022
1 parent 0aafee1 commit 82712c5
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 13 deletions.
19 changes: 10 additions & 9 deletions demo/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ paths:
parameters:
- name: Accept-Language
in: header
description: "The language you prefer for messages. Supported values are en-AU, en-CA, en-GB, en-US"
description: 'The language you prefer for messages. Supported values are en-AU, en-CA, en-GB, en-US'
example: en-US
required: false
schema:
Expand Down Expand Up @@ -254,7 +254,7 @@ paths:
required: false
schema:
type: string
example: "Bearer <TOKEN>"
example: 'Bearer <TOKEN>'
- name: petId
in: path
description: Pet id to delete
Expand Down Expand Up @@ -401,6 +401,7 @@ paths:
application/json:
schema:
type: object
minProperties: 2
additionalProperties:
type: integer
format: int32
Expand Down Expand Up @@ -429,7 +430,7 @@ paths:
application/json:
example:
status: 400
message: "Invalid Order"
message: 'Invalid Order'
requestBody:
content:
application/json:
Expand Down Expand Up @@ -877,11 +878,11 @@ paths:
type: string
examples:
response:
value: <Message> OK </Message>
value: <Message> OK </Message>
text/plain:
examples:
response:
value: OK
value: OK
'400':
description: Invalid username/password supplied
/user/logout:
Expand Down Expand Up @@ -1027,8 +1028,8 @@ components:
properties:
id:
externalDocs:
description: "Find more info here"
url: "https://example.com"
description: 'Find more info here'
url: 'https://example.com'
description: Pet ID
allOf:
- $ref: '#/components/schemas/Id'
Expand Down Expand Up @@ -1201,7 +1202,7 @@ x-webhooks:
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
$ref: '#/components/schemas/Pet'
responses:
"200":
'200':
description: Return a 200 status to indicate that the data was received successfully
2 changes: 2 additions & 0 deletions src/components/Parameters/Parameters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch';
import { Schema } from '../Schema';

import { Markdown } from '../Markdown/Markdown';
import { ConstraintsView } from '../Fields/FieldContstraints';

function safePush(obj, prop, item) {
if (!obj[prop]) {
Expand Down Expand Up @@ -79,6 +80,7 @@ export function BodyContent(props: {
return (
<>
{description !== undefined && <Markdown source={description} />}
<ConstraintsView constraints={schema?.constraints || []} />
<Schema
skipReadOnly={isRequestType}
skipWriteOnly={!isRequestType}
Expand Down
8 changes: 7 additions & 1 deletion src/components/Responses/ResponseDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Schema } from '../Schema';
import { Extensions } from '../Fields/Extensions';
import { Markdown } from '../Markdown/Markdown';
import { ResponseHeaders } from './ResponseHeaders';
import { ConstraintsView } from '../Fields/FieldContstraints';

export class ResponseDetails extends React.PureComponent<{ response: ResponseModel }> {
render() {
Expand All @@ -21,7 +22,12 @@ export class ResponseDetails extends React.PureComponent<{ response: ResponseMod
<ResponseHeaders headers={headers} />
<MediaTypesSwitch content={content} renderDropdown={this.renderDropdown}>
{({ schema }) => {
return <Schema skipWriteOnly={true} key="schema" schema={schema} />;
return (
<>
<ConstraintsView constraints={schema?.constraints || []} />
<Schema skipWriteOnly={true} key="schema" schema={schema} />
</>
);
}}
</MediaTypesSwitch>
</>
Expand Down
6 changes: 5 additions & 1 deletion src/components/Schema/OneOfSchema.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '../../common-elements/schema';
import { Badge } from '../../common-elements/shelfs';
import { SchemaModel } from '../../services/models';
import { ConstraintsView } from '../Fields/FieldContstraints';
import { Schema, SchemaProps } from './Schema';

export interface OneOfButtonProps {
Expand Down Expand Up @@ -47,6 +48,8 @@ export class OneOfSchema extends React.Component<SchemaProps> {
if (oneOf === undefined) {
return null;
}
const activeSchema = oneOf[schema.activeOneOf];

return (
<div>
<OneOfLabel> {schema.oneOfType} </OneOfLabel>
Expand All @@ -58,7 +61,8 @@ export class OneOfSchema extends React.Component<SchemaProps> {
<div>
{oneOf[schema.activeOneOf].deprecated && <Badge type="warning">Deprecated</Badge>}
</div>
<Schema {...this.props} schema={oneOf[schema.activeOneOf]} />
<ConstraintsView constraints={activeSchema.constraints} />
<Schema {...this.props} schema={activeSchema} />
</div>
);
}
Expand Down
25 changes: 25 additions & 0 deletions src/components/__tests__/OneOfSchema.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,30 @@ describe('Components', () => {
expect(component.render()).toMatchSnapshot();
});
});

describe('Show minProperties/maxProperties constraints oneOf', () => {
const schema = new SchemaModel(
parser,
{
oneOf: [
{
type: 'object',
description: 'Test description',
minProperties: 1,
maxProperties: 1,
additionalProperties: {
type: 'string',
description: 'The name and value o',
},
},
],
},
'',
options,
);

const component = shallow(withTheme(<Schema schema={schema} />));
expect(component.html().includes('= 1 properties')).toBe(true);
});
});
});
67 changes: 67 additions & 0 deletions src/components/__tests__/Schema.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* tslint:disable:no-implicit-dependencies */

import { shallow } from 'enzyme';
import * as React from 'react';

import { Schema } from '../';
import { OpenAPIParser, SchemaModel } from '../../services';
import { RedocNormalizedOptions } from '../../services/RedocNormalizedOptions';
import { withTheme } from '../testProviders';

const options = new RedocNormalizedOptions({});
describe('Components', () => {
describe('SchemaView', () => {
const parser = new OpenAPIParser(
{ openapi: '3.0', info: { title: 'test', version: '0' }, paths: {} },
undefined,
options,
);

describe('Show minProperties/maxProperties constraints', () => {
const schema = new SchemaModel(
parser,
{
properties: {
name: {
type: 'object',
minProperties: 1,
properties: {
address: {
type: 'string',
},
},
},
},
},
'',
options,
);
const component = shallow(withTheme(<Schema schema={schema} />));
expect(component.html().includes('non-empty')).toBe(true);
});

describe('Show range minProperties/maxProperties constraints', () => {
const schema = new SchemaModel(
parser,
{
properties: {
name: {
type: 'object',
minProperties: 2,
maxProperties: 10,
additionalProperties: {
type: 'string',
},
},
},
},
'',
options,
);
it('should includes [ 2 .. 10 ] properties', () => {
const component = shallow(withTheme(<Schema schema={schema} />));
expect(component.html().includes('[ 2 .. 10 ] properties')).toBe(true);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,7 @@ try {
"format": "int32",
"type": "integer",
},
"minProperties": 2,
"type": "object",
},
},
Expand Down
2 changes: 1 addition & 1 deletion src/utils/__tests__/openapi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ describe('Utils', () => {
});

it('should have a humanized constraint when minItems and maxItems are the same', () => {
expect(humanizeConstraints(itemConstraintSchema(7, 7))).toContain('7 items');
expect(humanizeConstraints(itemConstraintSchema(7, 7))).toContain('= 7 items');
});

it('should have a humanized constraint when justMinItems is set, and it is equal to 1', () => {
Expand Down
11 changes: 10 additions & 1 deletion src/utils/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ function humanizeRangeConstraint(
let stringRange;
if (min !== undefined && max !== undefined) {
if (min === max) {
stringRange = `${min} ${description}`;
stringRange = `= ${min} ${description}`;
} else {
stringRange = `[ ${min} .. ${max} ] ${description}`;
}
Expand Down Expand Up @@ -476,6 +476,15 @@ export function humanizeConstraints(schema: OpenAPISchema): string[] {
res.push(arrayRange);
}

const propertiesRange = humanizeRangeConstraint(
'properties',
schema.minProperties,
schema.maxProperties,
);
if (propertiesRange !== undefined) {
res.push(propertiesRange);
}

const multipleOfConstraint = humanizeMultipleOfConstraint(schema.multipleOf);
if (multipleOfConstraint !== undefined) {
res.push(multipleOfConstraint);
Expand Down

0 comments on commit 82712c5

Please sign in to comment.