#573 fix discriminator handling when referencing classes which only have a superclass, but no subclasses (and add description to ObjectSchema.tsx)

This commit is contained in:
Fabian Vollmann 2020-04-15 15:22:33 +02:00
parent 57e93ec435
commit 26a8cff142
8 changed files with 153 additions and 156 deletions

View File

@ -1,9 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import styled from '../../styled-components';
import { DropdownProps } from '../../common-elements'; import { DropdownProps } from '../../common-elements';
import { MediaTypeModel } from '../../services/models'; import { MediaTypeModel } from '../../services/models';
import styled from '../../styled-components';
import { Markdown } from '../Markdown/Markdown'; import { Markdown } from '../Markdown/Markdown';
import { Example } from './Example'; import { Example } from './Example';
import { DropdownLabel, DropdownWrapper, NoSampleLabel } from './styled.elements'; import { DropdownLabel, DropdownWrapper, NoSampleLabel } from './styled.elements';
@ -28,6 +26,7 @@ export class MediaTypeSamples extends React.Component<PayloadSamplesProps, Media
}; };
render() { render() {
const { activeIdx } = this.state; const { activeIdx } = this.state;
console.log(this.props);
const examples = this.props.mediaType.examples || {}; const examples = this.props.mediaType.examples || {};
const mimeType = this.props.mediaType.name; const mimeType = this.props.mediaType.name;

View File

@ -1,16 +1,14 @@
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import * as React from 'react'; import * as React from 'react';
import { SchemaModel } from '../../services/models';
import { PropertiesTable, PropertiesTableCaption } from '../../common-elements/fields-layout'; import { PropertiesTable, PropertiesTableCaption } from '../../common-elements/fields-layout';
import { SchemaModel } from '../../services/models';
import { mapWithLast } from '../../utils';
import { Field } from '../Fields/Field'; import { Field } from '../Fields/Field';
import { Markdown } from '../Markdown/Markdown';
import { OptionsContext } from '../OptionsProvider';
import { DiscriminatorDropdown } from './DiscriminatorDropdown'; import { DiscriminatorDropdown } from './DiscriminatorDropdown';
import { SchemaProps } from './Schema'; import { SchemaProps } from './Schema';
import { mapWithLast } from '../../utils';
import { OptionsContext } from '../OptionsProvider';
export interface ObjectSchemaProps extends SchemaProps { export interface ObjectSchemaProps extends SchemaProps {
discriminator?: { discriminator?: {
fieldName: string; fieldName: string;
@ -47,6 +45,8 @@ export class ObjectSchema extends React.Component<ObjectSchemaProps> {
const expandByDefault = this.context.expandSingleSchemaField && filteredFields.length === 1; const expandByDefault = this.context.expandSingleSchemaField && filteredFields.length === 1;
return ( return (
<div>
<Markdown compact={true} inline={true} source={this.props.schema.description} />
<PropertiesTable> <PropertiesTable>
{showTitle && <PropertiesTableCaption>{this.props.schema.title}</PropertiesTableCaption>} {showTitle && <PropertiesTableCaption>{this.props.schema.title}</PropertiesTableCaption>}
<tbody> <tbody>
@ -78,6 +78,7 @@ export class ObjectSchema extends React.Component<ObjectSchemaProps> {
})} })}
</tbody> </tbody>
</PropertiesTable> </PropertiesTable>
</div>
); );
} }
} }

View File

@ -1,17 +1,13 @@
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import * as React from 'react'; import * as React from 'react';
import { RecursiveLabel, TypeName, TypeTitle } from '../../common-elements/fields'; import { RecursiveLabel, TypeName, TypeTitle } from '../../common-elements/fields';
import { FieldDetails } from '../Fields/FieldDetails'; import { l } from '../../services/Labels';
import { FieldModel, SchemaModel } from '../../services/models'; import { FieldModel, SchemaModel } from '../../services/models';
import { FieldDetails } from '../Fields/FieldDetails';
import { ArraySchema } from './ArraySchema'; import { ArraySchema } from './ArraySchema';
import { ObjectSchema } from './ObjectSchema'; import { ObjectSchema } from './ObjectSchema';
import { OneOfSchema } from './OneOfSchema'; import { OneOfSchema } from './OneOfSchema';
import { l } from '../../services/Labels';
export interface SchemaOptions { export interface SchemaOptions {
showTitle?: boolean; showTitle?: boolean;
skipReadOnly?: boolean; skipReadOnly?: boolean;
@ -43,10 +39,9 @@ export class Schema extends React.Component<Partial<SchemaProps>> {
if (discriminatorProp !== undefined) { if (discriminatorProp !== undefined) {
if (!oneOf || !oneOf.length) { if (!oneOf || !oneOf.length) {
throw new Error( return <ObjectSchema {...(this.props as any)} />;
`Looks like you are using discriminator wrong: you don't have any definition inherited from the ${schema.title}`,
);
} }
return ( return (
<ObjectSchema <ObjectSchema
{...{ ...this.props, schema: oneOf![schema.activeOneOf] }} {...{ ...this.props, schema: oneOf![schema.activeOneOf] }}

View File

@ -1,5 +1,4 @@
import * as React from 'react'; import * as React from 'react';
import { DarkRightPanel, MiddlePanel, MimeLabel, Row, Section } from '../../common-elements'; import { DarkRightPanel, MiddlePanel, MimeLabel, Row, Section } from '../../common-elements';
import { MediaTypeModel, OpenAPIParser, RedocNormalizedOptions } from '../../services'; import { MediaTypeModel, OpenAPIParser, RedocNormalizedOptions } from '../../services';
import styled from '../../styled-components'; import styled from '../../styled-components';

View File

@ -1,6 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Components SchemaView discriminator should correctly render discriminator dropdown 1`] = ` exports[`Components SchemaView discriminator should correctly render discriminator dropdown 1`] = `
<div>
<Markdown
compact={true}
inline={true}
source=""
/>
<styled.table> <styled.table>
<tbody> <tbody>
<Field <Field
@ -106,4 +112,5 @@ exports[`Components SchemaView discriminator should correctly render discriminat
/> />
</tbody> </tbody>
</styled.table> </styled.table>
</div>
`; `;

View File

@ -13,7 +13,7 @@ describe('Models', () => {
const spec = require('../fixtures/discriminator.json'); const spec = require('../fixtures/discriminator.json');
parser = new OpenAPIParser(spec, undefined, opts); parser = new OpenAPIParser(spec, undefined, opts);
const schema = new SchemaModel(parser, spec.components.schemas.Foo, '', opts); const schema = new SchemaModel(parser, spec.components.schemas.Foo, '', opts);
expect(schema.oneOf).toHaveLength(1); expect(schema.oneOf).toHaveLength(0);
expect(schema.discriminatorProp).toEqual('type'); expect(schema.discriminatorProp).toEqual('type');
}); });

View File

@ -1,12 +1,10 @@
import * as Sampler from 'openapi-sampler'; import * as Sampler from 'openapi-sampler';
import { OpenAPIMediaType } from '../../types'; import { OpenAPIMediaType } from '../../types';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import { SchemaModel } from './Schema';
import { isJsonLike, mapValues } from '../../utils'; import { isJsonLike, mapValues } from '../../utils';
import { OpenAPIParser } from '../OpenAPIParser'; import { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import { ExampleModel } from './Example'; import { ExampleModel } from './Example';
import { SchemaModel } from './Schema';
export class MediaTypeModel { export class MediaTypeModel {
examples?: { [name: string]: ExampleModel }; examples?: { [name: string]: ExampleModel };
@ -54,7 +52,7 @@ export class MediaTypeModel {
skipNonRequired: this.isRequestType && this.onlyRequiredInSamples, skipNonRequired: this.isRequestType && this.onlyRequiredInSamples,
skipWriteOnly: !this.isRequestType, skipWriteOnly: !this.isRequestType,
}; };
if (this.schema && this.schema.oneOf) { if (this.schema && this.schema.oneOf && this.schema.oneOf.length > 0) {
this.examples = {}; this.examples = {};
for (const subSchema of this.schema.oneOf) { for (const subSchema of this.schema.oneOf) {
const sample = Sampler.sample(subSchema.rawSchema, samplerOptions, parser.spec); const sample = Sampler.sample(subSchema.rawSchema, samplerOptions, parser.spec);

View File

@ -1,12 +1,6 @@
import { action, observable } from 'mobx'; import { action, observable } from 'mobx';
import { OpenAPIExternalDocumentation, OpenAPISchema, Referenced } from '../../types';
import { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import { FieldModel } from './Field';
import { MergedOpenAPISchema } from '../'; import { MergedOpenAPISchema } from '../';
import { OpenAPIExternalDocumentation, OpenAPISchema, Referenced } from '../../types';
import { import {
detectType, detectType,
extractExtensions, extractExtensions,
@ -18,8 +12,10 @@ import {
sortByField, sortByField,
sortByRequired, sortByRequired,
} from '../../utils/'; } from '../../utils/';
import { l } from '../Labels'; import { l } from '../Labels';
import { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import { FieldModel } from './Field';
// TODO: refactor this model, maybe use getters instead of copying all the values // TODO: refactor this model, maybe use getters instead of copying all the values
export class SchemaModel { export class SchemaModel {
@ -225,7 +221,7 @@ export class SchemaModel {
const discriminator = getDiscriminator(schema)!; const discriminator = getDiscriminator(schema)!;
this.discriminatorProp = discriminator.propertyName; this.discriminatorProp = discriminator.propertyName;
const implicitInversedMapping = parser.findDerived([ const implicitInversedMapping = parser.findDerived([
...(schema.parentRefs || []), ...[], //...(schema.parentRefs || []), // including parentRefs in all cases is wrong (it is correct for a class with subclasses, but not for one, which only has a superclass)
this.pointer, this.pointer,
]); ]);
@ -312,6 +308,8 @@ export class SchemaModel {
innerSchema.title = name; innerSchema.title = name;
return innerSchema; return innerSchema;
}); });
this.fields = buildFields(parser, schema, this.pointer, this.options);
} }
} }