Skip to content

Commit

Permalink
fix: Schema for events incorrectly omits readOnly and includes writeO…
Browse files Browse the repository at this point in the history
…nly (#1720 #1540)
  • Loading branch information
zalesky authored Aug 31, 2021
1 parent 683eabb commit a8e0c29
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 35 deletions.
4 changes: 2 additions & 2 deletions demo/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,7 @@ x-webhooks:
summary: New pet
description: Information about a new pet in the systems
operationId: newPet
tags:
tags:
- pet
requestBody:
content:
Expand All @@ -1202,4 +1202,4 @@ x-webhooks:
$ref: "#/components/schemas/Pet"
responses:
"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
3 changes: 2 additions & 1 deletion src/components/Parameters/Parameters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,14 @@ function DropdownWithinHeader(props) {

export function BodyContent(props: { content: MediaContentModel; description?: string }): JSX.Element {
const { content, description } = props;
const { isRequestType } = content;
return (
<MediaTypesSwitch content={content} renderDropdown={DropdownWithinHeader}>
{({ schema }) => {
return (
<>
{description !== undefined && <Markdown source={description} />}
<Schema skipReadOnly={true} key="schema" schema={schema} />
<Schema skipReadOnly={isRequestType} key="schema" schema={schema} />
</>
);
}}
Expand Down
2 changes: 1 addition & 1 deletion src/services/RedocNormalizedOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean
return defaultValue || false;
}
if (typeof val === 'string') {
return val === 'false' ? false : true;
return val !== 'false';
}
return val;
}
Expand Down
27 changes: 27 additions & 0 deletions src/services/__tests__/models/RequestBody.test.ts
Original file line number Diff line number Diff line change
@@ -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 });
});
});
});
22 changes: 15 additions & 7 deletions src/services/__tests__/models/Response.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,38 @@ import { RedocNormalizedOptions } from '../../RedocNormalizedOptions';
const opts = new RedocNormalizedOptions({});
describe('Models', () => {
describe('ResponseModel', () => {
let parser;
let parser, props;

beforeEach(() => {
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', () => {
let resp = new ResponseModel(parser, '200', false, {}, opts);
let resp = new ResponseModel({...props, code: '200' });
expect(resp.type).toEqual('success');
resp = new ResponseModel(parser, '120', false, {}, opts);
resp = new ResponseModel({...props, code: '120' });
expect(resp.type).toEqual('info');
resp = new ResponseModel(parser, '301', false, {}, opts);
resp = new ResponseModel({...props, code: '301' });
expect(resp.type).toEqual('redirect');
resp = new ResponseModel(parser, '400', false, {}, opts);
resp = new ResponseModel({...props, code: '400' });
expect(resp.type).toEqual('error');
});

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');
});

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');
});
});
Expand Down
2 changes: 1 addition & 1 deletion src/services/models/MediaType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ export class MediaTypeModel {
generateExample(parser: OpenAPIParser, info: OpenAPIMediaType) {
const samplerOptions = {
skipReadOnly: this.isRequestType,
skipNonRequired: this.isRequestType && this.onlyRequiredInSamples,
skipWriteOnly: !this.isRequestType,
skipNonRequired: this.isRequestType && this.onlyRequiredInSamples,
maxSampleDepth: 10,
};
if (this.schema && this.schema.oneOf) {
Expand Down
25 changes: 16 additions & 9 deletions src/services/models/Operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export class OperationModel implements IMenuItem {
extensions: Record<string, any>;
isCallback: boolean;
isWebhook: boolean;
isEvent: boolean;

constructor(
private parser: OpenAPIParser,
Expand All @@ -98,7 +99,8 @@ export class OperationModel implements IMenuItem {
this.operationId = operationSpec.operationId;
this.path = operationSpec.pathName;
this.isCallback = isCallback;
this.isWebhook = !!operationSpec.isWebhook;
this.isWebhook = operationSpec.isWebhook;
this.isEvent = this.isCallback || this.isWebhook;

this.name = getOperationSummary(operationSpec);

Expand Down Expand Up @@ -171,8 +173,12 @@ export class OperationModel implements IMenuItem {
@memoize
get requestBody() {
return (
this.operationSpec.requestBody &&
new RequestBodyModel(this.parser, this.operationSpec.requestBody, this.options)
this.operationSpec.requestBody && new RequestBodyModel({
parser: this.parser,
infoOrRef: this.operationSpec.requestBody,
options: this.options,
isEvent: this.isEvent,
})
);
}

Expand Down Expand Up @@ -240,13 +246,14 @@ export class OperationModel implements IMenuItem {
return isStatusCode(code);
}) // filter out other props (e.g. x-props)
.map((code) => {
return new ResponseModel(
this.parser,
return new ResponseModel({
parser: this.parser,
code,
hasSuccessResponses,
this.operationSpec.responses[code],
this.options,
);
defaultAsError: hasSuccessResponses,
infoOrRef: this.operationSpec.responses[code],
options: this.options,
isEvent: this.isEvent,
});
});
}

Expand Down
17 changes: 11 additions & 6 deletions src/services/models/RequestBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,27 @@ import { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import { MediaContentModel } from './MediaContent';

type RequestBodyProps = {
parser: OpenAPIParser;
infoOrRef: Referenced<OpenAPIRequestBody>;
options: RedocNormalizedOptions;
isEvent: boolean;
}

export class RequestBodyModel {
description: string;
required: boolean;
content?: MediaContentModel;

constructor(
parser: OpenAPIParser,
infoOrRef: Referenced<OpenAPIRequestBody>,
options: RedocNormalizedOptions,
) {
constructor(props: RequestBodyProps) {
const { parser, infoOrRef, options, isEvent } = props;
const isRequest = isEvent ? false : true;
const info = parser.deref(infoOrRef);
this.description = info.description || '';
this.required = !!info.required;
parser.exitRef(infoOrRef);
if (info.content !== undefined) {
this.content = new MediaContentModel(parser, info.content, true, options);
this.content = new MediaContentModel(parser, info.content, isRequest, options);
}
}
}
21 changes: 13 additions & 8 deletions src/services/models/Response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import { FieldModel } from './Field';
import { MediaContentModel } from './MediaContent';

type ResponseProps = {
parser: OpenAPIParser,
code: string,
defaultAsError: boolean,
infoOrRef: Referenced<OpenAPIResponse>,
options: RedocNormalizedOptions,
isEvent: boolean,
}

export class ResponseModel {
@observable
expanded: boolean = false;
Expand All @@ -19,13 +28,9 @@ export class ResponseModel {
type: string;
headers: FieldModel[] = [];

constructor(
parser: OpenAPIParser,
code: string,
defaultAsError: boolean,
infoOrRef: Referenced<OpenAPIResponse>,
options: RedocNormalizedOptions,
) {
constructor(props: ResponseProps) {
const { parser, code, defaultAsError, infoOrRef, options, isEvent } = props;
const isRequest = isEvent ? true : false;
makeObservable(this);

this.expanded = options.expandResponses === 'all' || options.expandResponses[code];
Expand All @@ -34,7 +39,7 @@ export class ResponseModel {
parser.exitRef(infoOrRef);
this.code = code;
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) {
Expand Down

0 comments on commit a8e0c29

Please sign in to comment.