From 6c41e95aa04d4c6c786791953636e12c85e0a809 Mon Sep 17 00:00:00 2001 From: Oprysk Date: Fri, 10 Dec 2021 15:04:46 +0200 Subject: [PATCH] chore: fix broken test & components refactoring --- src/components/Responses/Response.tsx | 75 ++++++++++--------- src/components/Responses/ResponseTitle.tsx | 53 +++++++------ src/components/Responses/styled.elements.ts | 4 +- .../__tests__/models/Response.test.ts | 11 ++- src/services/models/RequestBody.ts | 3 +- src/services/models/Response.ts | 16 ++-- 6 files changed, 91 insertions(+), 71 deletions(-) diff --git a/src/components/Responses/Response.tsx b/src/components/Responses/Response.tsx index bc6ece8b..d9c11d32 100644 --- a/src/components/Responses/Response.tsx +++ b/src/components/Responses/Response.tsx @@ -1,40 +1,47 @@ -import { observer } from 'mobx-react'; import * as React from 'react'; +import { observer } from 'mobx-react'; -import { ResponseModel } from '../../services/models'; +import type { ResponseModel, MediaTypeModel } from '../../services/models'; import { ResponseDetails } from './ResponseDetails'; import { ResponseDetailsWrap, StyledResponseTitle } from './styled.elements'; -@observer -export class ResponseView extends React.Component<{ response: ResponseModel }> { - toggle = () => { - this.props.response.toggle(); - }; - - render() { - const { extensions, headers, type, summary, description, code, expanded, content } = this.props.response; - const mimes = - content === undefined ? [] : content.mediaTypes.filter(mime => mime.schema !== undefined); - - const empty = (!extensions || Object.keys(extensions).length === 0) && - headers.length === 0 && mimes.length === 0 && !description; - - return ( -
- - {expanded && !empty && ( - - - - )} -
- ); - } +export interface ResponseViewProps { + response: ResponseModel; } + +export const ResponseView = observer(({ response }: ResponseViewProps): React.ReactElement => { + const { extensions, headers, type, summary, description, code, expanded, content } = response; + + const mimes = React.useMemo( + () => + content === undefined ? [] : content.mediaTypes.filter(mime => mime.schema !== undefined), + [content], + ); + + const empty = React.useMemo( + () => + (!extensions || Object.keys(extensions).length === 0) && + headers.length === 0 && + mimes.length === 0 && + !description, + [extensions, headers, mimes, description], + ); + + return ( +
+ + {expanded && !empty && ( + + + + )} +
+ ); +}); diff --git a/src/components/Responses/ResponseTitle.tsx b/src/components/Responses/ResponseTitle.tsx index 74e07a39..812bbccd 100644 --- a/src/components/Responses/ResponseTitle.tsx +++ b/src/components/Responses/ResponseTitle.tsx @@ -14,27 +14,34 @@ export interface ResponseTitleProps { onClick?: () => void; } -export class ResponseTitle extends React.PureComponent { - render() { - const { title, type, empty, code, opened, className, onClick } = this.props; - return ( - - ); - } +function ResponseTitleComponent({ + title, + type, + empty, + code, + opened, + className, + onClick, +}: ResponseTitleProps): React.ReactElement { + return ( + + ); } + +export const ResponseTitle = React.memo(ResponseTitleComponent); diff --git a/src/components/Responses/styled.elements.ts b/src/components/Responses/styled.elements.ts index 531236dd..7e456870 100644 --- a/src/components/Responses/styled.elements.ts +++ b/src/components/Responses/styled.elements.ts @@ -11,14 +11,12 @@ export const StyledResponseTitle = styled(ResponseTitle)` border-radius: 2px; margin-bottom: 4px; line-height: 1.5em; - background-color: #f2f2f2; cursor: pointer; color: ${props => props.theme.colors.responses[props.type].color}; background-color: ${props => props.theme.colors.responses[props.type].backgroundColor}; &:focus { - outline: auto; - outline-color: ${props => props.theme.colors.responses[props.type].color}; + outline: auto ${props => props.theme.colors.responses[props.type].color}; } ${props => (props.empty && diff --git a/src/services/__tests__/models/Response.test.ts b/src/services/__tests__/models/Response.test.ts index 48633619..26ec21b7 100644 --- a/src/services/__tests__/models/Response.test.ts +++ b/src/services/__tests__/models/Response.test.ts @@ -42,9 +42,16 @@ describe('Models', () => { test('ensure extensions are shown if showExtensions is true', () => { const options = new RedocNormalizedOptions({ showExtensions: true }); - const resp = new ResponseModel(parser, 'default', true, { 'x-example': {a: 1} } as any, options); + const resp = new ResponseModel({ + parser, + code: 'default', + defaultAsError: true, + infoOrRef: { 'x-example': { a: 1 } }, + options, + isEvent: true, + }); expect(Object.keys(resp.extensions).length).toEqual(1); - expect(resp.extensions['x-example']).toEqual({a: 1}); + expect(resp.extensions['x-example']).toEqual({ a: 1 }); }); }); }); diff --git a/src/services/models/RequestBody.ts b/src/services/models/RequestBody.ts index b7f209d6..18780a58 100644 --- a/src/services/models/RequestBody.ts +++ b/src/services/models/RequestBody.ts @@ -17,8 +17,7 @@ export class RequestBodyModel { required: boolean; content?: MediaContentModel; - constructor(props: RequestBodyProps) { - const { parser, infoOrRef, options, isEvent } = props; + constructor({ parser, infoOrRef, options, isEvent }: RequestBodyProps) { const isRequest = !isEvent; const info = parser.deref(infoOrRef); this.description = info.description || ''; diff --git a/src/services/models/Response.ts b/src/services/models/Response.ts index a0878093..77159a8a 100644 --- a/src/services/models/Response.ts +++ b/src/services/models/Response.ts @@ -2,10 +2,7 @@ import { action, observable, makeObservable } from 'mobx'; import { OpenAPIResponse, Referenced } from '../../types'; -import { - getStatusCodeType, - extractExtensions -} from '../../utils'; +import { getStatusCodeType, extractExtensions } from '../../utils'; import { OpenAPIParser } from '../OpenAPIParser'; import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; import { FieldModel } from './Field'; @@ -32,9 +29,14 @@ export class ResponseModel { headers: FieldModel[] = []; extensions: Record; - constructor(props: ResponseProps) { - const { parser, code, defaultAsError, infoOrRef, options, isEvent } = props; - const isRequest = isEvent ? true : false; + constructor({ + parser, + code, + defaultAsError, + infoOrRef, + options, + isEvent: isRequest, + }: ResponseProps) { makeObservable(this); this.expanded = options.expandResponses === 'all' || options.expandResponses[code];