mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-25 10:03:45 +03:00
This commit is contained in:
parent
683eabbbf0
commit
a8e0c29685
|
@ -1193,7 +1193,7 @@ x-webhooks:
|
||||||
summary: New pet
|
summary: New pet
|
||||||
description: Information about a new pet in the systems
|
description: Information about a new pet in the systems
|
||||||
operationId: newPet
|
operationId: newPet
|
||||||
tags:
|
tags:
|
||||||
- pet
|
- pet
|
||||||
requestBody:
|
requestBody:
|
||||||
content:
|
content:
|
||||||
|
@ -1202,4 +1202,4 @@ x-webhooks:
|
||||||
$ref: "#/components/schemas/Pet"
|
$ref: "#/components/schemas/Pet"
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: Return a 200 status to indicate that the data was received successfully
|
description: Return a 200 status to indicate that the data was received successfully
|
||||||
|
|
|
@ -69,13 +69,14 @@ function DropdownWithinHeader(props) {
|
||||||
|
|
||||||
export function BodyContent(props: { content: MediaContentModel; description?: string }): JSX.Element {
|
export function BodyContent(props: { content: MediaContentModel; description?: string }): JSX.Element {
|
||||||
const { content, description } = props;
|
const { content, description } = props;
|
||||||
|
const { isRequestType } = content;
|
||||||
return (
|
return (
|
||||||
<MediaTypesSwitch content={content} renderDropdown={DropdownWithinHeader}>
|
<MediaTypesSwitch content={content} renderDropdown={DropdownWithinHeader}>
|
||||||
{({ schema }) => {
|
{({ schema }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{description !== undefined && <Markdown source={description} />}
|
{description !== undefined && <Markdown source={description} />}
|
||||||
<Schema skipReadOnly={true} key="schema" schema={schema} />
|
<Schema skipReadOnly={isRequestType} key="schema" schema={schema} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -49,7 +49,7 @@ export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean
|
||||||
return defaultValue || false;
|
return defaultValue || false;
|
||||||
}
|
}
|
||||||
if (typeof val === 'string') {
|
if (typeof val === 'string') {
|
||||||
return val === 'false' ? false : true;
|
return val !== 'false';
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
27
src/services/__tests__/models/RequestBody.test.ts
Normal file
27
src/services/__tests__/models/RequestBody.test.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { RequestBodyModel } from '../../models/RequestBody';
|
||||||
|
import { OpenAPIParser } from '../../OpenAPIParser';
|
||||||
|
import { RedocNormalizedOptions } from '../../RedocNormalizedOptions';
|
||||||
|
|
||||||
|
const opts = new RedocNormalizedOptions({});
|
||||||
|
describe('Models', () => {
|
||||||
|
describe('RequestBodyModel', () => {
|
||||||
|
let parser, props;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
parser = new OpenAPIParser({ openapi: '3.0.0' } as any, undefined, opts);
|
||||||
|
props = {
|
||||||
|
parser,
|
||||||
|
infoOrRef: {},
|
||||||
|
options: opts,
|
||||||
|
isEvent: false,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should work with default props', () => {
|
||||||
|
const consoleError = jest.spyOn(global.console, 'error');
|
||||||
|
const req = new RequestBodyModel(props);
|
||||||
|
expect(consoleError).not.toHaveBeenCalled();
|
||||||
|
expect(req).toEqual({ description: '', required: false });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,30 +5,38 @@ import { RedocNormalizedOptions } from '../../RedocNormalizedOptions';
|
||||||
const opts = new RedocNormalizedOptions({});
|
const opts = new RedocNormalizedOptions({});
|
||||||
describe('Models', () => {
|
describe('Models', () => {
|
||||||
describe('ResponseModel', () => {
|
describe('ResponseModel', () => {
|
||||||
let parser;
|
let parser, props;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
parser = new OpenAPIParser({ openapi: '3.0.0' } as any, undefined, opts);
|
parser = new OpenAPIParser({ openapi: '3.0.0' } as any, undefined, opts);
|
||||||
|
props = {
|
||||||
|
parser,
|
||||||
|
defaultAsError: false,
|
||||||
|
infoOrRef: {},
|
||||||
|
options: opts,
|
||||||
|
isEvent: false,
|
||||||
|
code: 'default',
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should calculate response type based on code', () => {
|
test('should calculate response type based on code', () => {
|
||||||
let resp = new ResponseModel(parser, '200', false, {}, opts);
|
let resp = new ResponseModel({...props, code: '200' });
|
||||||
expect(resp.type).toEqual('success');
|
expect(resp.type).toEqual('success');
|
||||||
resp = new ResponseModel(parser, '120', false, {}, opts);
|
resp = new ResponseModel({...props, code: '120' });
|
||||||
expect(resp.type).toEqual('info');
|
expect(resp.type).toEqual('info');
|
||||||
resp = new ResponseModel(parser, '301', false, {}, opts);
|
resp = new ResponseModel({...props, code: '301' });
|
||||||
expect(resp.type).toEqual('redirect');
|
expect(resp.type).toEqual('redirect');
|
||||||
resp = new ResponseModel(parser, '400', false, {}, opts);
|
resp = new ResponseModel({...props, code: '400' });
|
||||||
expect(resp.type).toEqual('error');
|
expect(resp.type).toEqual('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('default should be successful by default', () => {
|
test('default should be successful by default', () => {
|
||||||
const resp = new ResponseModel(parser, 'default', false, {}, opts);
|
const resp = new ResponseModel({...props, code: 'default' });
|
||||||
expect(resp.type).toEqual('success');
|
expect(resp.type).toEqual('success');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('default should be error if defaultAsError is true', () => {
|
test('default should be error if defaultAsError is true', () => {
|
||||||
const resp = new ResponseModel(parser, 'default', true, {}, opts);
|
const resp = new ResponseModel({...props, code: 'default', defaultAsError: true });
|
||||||
expect(resp.type).toEqual('error');
|
expect(resp.type).toEqual('error');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -51,8 +51,8 @@ export class MediaTypeModel {
|
||||||
generateExample(parser: OpenAPIParser, info: OpenAPIMediaType) {
|
generateExample(parser: OpenAPIParser, info: OpenAPIMediaType) {
|
||||||
const samplerOptions = {
|
const samplerOptions = {
|
||||||
skipReadOnly: this.isRequestType,
|
skipReadOnly: this.isRequestType,
|
||||||
skipNonRequired: this.isRequestType && this.onlyRequiredInSamples,
|
|
||||||
skipWriteOnly: !this.isRequestType,
|
skipWriteOnly: !this.isRequestType,
|
||||||
|
skipNonRequired: this.isRequestType && this.onlyRequiredInSamples,
|
||||||
maxSampleDepth: 10,
|
maxSampleDepth: 10,
|
||||||
};
|
};
|
||||||
if (this.schema && this.schema.oneOf) {
|
if (this.schema && this.schema.oneOf) {
|
||||||
|
|
|
@ -76,6 +76,7 @@ export class OperationModel implements IMenuItem {
|
||||||
extensions: Record<string, any>;
|
extensions: Record<string, any>;
|
||||||
isCallback: boolean;
|
isCallback: boolean;
|
||||||
isWebhook: boolean;
|
isWebhook: boolean;
|
||||||
|
isEvent: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private parser: OpenAPIParser,
|
private parser: OpenAPIParser,
|
||||||
|
@ -98,7 +99,8 @@ export class OperationModel implements IMenuItem {
|
||||||
this.operationId = operationSpec.operationId;
|
this.operationId = operationSpec.operationId;
|
||||||
this.path = operationSpec.pathName;
|
this.path = operationSpec.pathName;
|
||||||
this.isCallback = isCallback;
|
this.isCallback = isCallback;
|
||||||
this.isWebhook = !!operationSpec.isWebhook;
|
this.isWebhook = operationSpec.isWebhook;
|
||||||
|
this.isEvent = this.isCallback || this.isWebhook;
|
||||||
|
|
||||||
this.name = getOperationSummary(operationSpec);
|
this.name = getOperationSummary(operationSpec);
|
||||||
|
|
||||||
|
@ -171,8 +173,12 @@ export class OperationModel implements IMenuItem {
|
||||||
@memoize
|
@memoize
|
||||||
get requestBody() {
|
get requestBody() {
|
||||||
return (
|
return (
|
||||||
this.operationSpec.requestBody &&
|
this.operationSpec.requestBody && new RequestBodyModel({
|
||||||
new RequestBodyModel(this.parser, this.operationSpec.requestBody, this.options)
|
parser: this.parser,
|
||||||
|
infoOrRef: this.operationSpec.requestBody,
|
||||||
|
options: this.options,
|
||||||
|
isEvent: this.isEvent,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,13 +246,14 @@ export class OperationModel implements IMenuItem {
|
||||||
return isStatusCode(code);
|
return isStatusCode(code);
|
||||||
}) // filter out other props (e.g. x-props)
|
}) // filter out other props (e.g. x-props)
|
||||||
.map((code) => {
|
.map((code) => {
|
||||||
return new ResponseModel(
|
return new ResponseModel({
|
||||||
this.parser,
|
parser: this.parser,
|
||||||
code,
|
code,
|
||||||
hasSuccessResponses,
|
defaultAsError: hasSuccessResponses,
|
||||||
this.operationSpec.responses[code],
|
infoOrRef: this.operationSpec.responses[code],
|
||||||
this.options,
|
options: this.options,
|
||||||
);
|
isEvent: this.isEvent,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,22 +4,27 @@ import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
import { MediaContentModel } from './MediaContent';
|
import { MediaContentModel } from './MediaContent';
|
||||||
|
|
||||||
|
type RequestBodyProps = {
|
||||||
|
parser: OpenAPIParser;
|
||||||
|
infoOrRef: Referenced<OpenAPIRequestBody>;
|
||||||
|
options: RedocNormalizedOptions;
|
||||||
|
isEvent: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export class RequestBodyModel {
|
export class RequestBodyModel {
|
||||||
description: string;
|
description: string;
|
||||||
required: boolean;
|
required: boolean;
|
||||||
content?: MediaContentModel;
|
content?: MediaContentModel;
|
||||||
|
|
||||||
constructor(
|
constructor(props: RequestBodyProps) {
|
||||||
parser: OpenAPIParser,
|
const { parser, infoOrRef, options, isEvent } = props;
|
||||||
infoOrRef: Referenced<OpenAPIRequestBody>,
|
const isRequest = isEvent ? false : true;
|
||||||
options: RedocNormalizedOptions,
|
|
||||||
) {
|
|
||||||
const info = parser.deref(infoOrRef);
|
const info = parser.deref(infoOrRef);
|
||||||
this.description = info.description || '';
|
this.description = info.description || '';
|
||||||
this.required = !!info.required;
|
this.required = !!info.required;
|
||||||
parser.exitRef(infoOrRef);
|
parser.exitRef(infoOrRef);
|
||||||
if (info.content !== undefined) {
|
if (info.content !== undefined) {
|
||||||
this.content = new MediaContentModel(parser, info.content, true, options);
|
this.content = new MediaContentModel(parser, info.content, isRequest, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,15 @@ import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
import { FieldModel } from './Field';
|
import { FieldModel } from './Field';
|
||||||
import { MediaContentModel } from './MediaContent';
|
import { MediaContentModel } from './MediaContent';
|
||||||
|
|
||||||
|
type ResponseProps = {
|
||||||
|
parser: OpenAPIParser,
|
||||||
|
code: string,
|
||||||
|
defaultAsError: boolean,
|
||||||
|
infoOrRef: Referenced<OpenAPIResponse>,
|
||||||
|
options: RedocNormalizedOptions,
|
||||||
|
isEvent: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
export class ResponseModel {
|
export class ResponseModel {
|
||||||
@observable
|
@observable
|
||||||
expanded: boolean = false;
|
expanded: boolean = false;
|
||||||
|
@ -19,13 +28,9 @@ export class ResponseModel {
|
||||||
type: string;
|
type: string;
|
||||||
headers: FieldModel[] = [];
|
headers: FieldModel[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(props: ResponseProps) {
|
||||||
parser: OpenAPIParser,
|
const { parser, code, defaultAsError, infoOrRef, options, isEvent } = props;
|
||||||
code: string,
|
const isRequest = isEvent ? true : false;
|
||||||
defaultAsError: boolean,
|
|
||||||
infoOrRef: Referenced<OpenAPIResponse>,
|
|
||||||
options: RedocNormalizedOptions,
|
|
||||||
) {
|
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
|
|
||||||
this.expanded = options.expandResponses === 'all' || options.expandResponses[code];
|
this.expanded = options.expandResponses === 'all' || options.expandResponses[code];
|
||||||
|
@ -34,7 +39,7 @@ export class ResponseModel {
|
||||||
parser.exitRef(infoOrRef);
|
parser.exitRef(infoOrRef);
|
||||||
this.code = code;
|
this.code = code;
|
||||||
if (info.content !== undefined) {
|
if (info.content !== undefined) {
|
||||||
this.content = new MediaContentModel(parser, info.content, false, options);
|
this.content = new MediaContentModel(parser, info.content, isRequest, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info['x-summary'] !== undefined) {
|
if (info['x-summary'] !== undefined) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user