mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-10 19:06:34 +03:00
fix: enum duplication values when schema uses a specific combination of oneOf and allOf(#2088)
This commit is contained in:
parent
b1afd08bcf
commit
e4118479f6
|
@ -240,7 +240,7 @@ export class OpenAPIParser {
|
|||
|
||||
if (enumProperty !== undefined) {
|
||||
if (Array.isArray(enumProperty) && Array.isArray(receiver.enum)) {
|
||||
receiver.enum = [...enumProperty, ...receiver.enum];
|
||||
receiver.enum = Array.from(new Set([...enumProperty, ...receiver.enum]));
|
||||
} else {
|
||||
receiver.enum = enumProperty;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { outdent } from 'outdent';
|
|||
import { SchemaModel } from '../../models/Schema';
|
||||
import { OpenAPIParser } from '../../OpenAPIParser';
|
||||
import { RedocNormalizedOptions } from '../../RedocNormalizedOptions';
|
||||
import { printSchema } from './helpers';
|
||||
import { enumDetailsPrinter, printSchema } from './helpers';
|
||||
|
||||
const opts = new RedocNormalizedOptions({});
|
||||
|
||||
|
@ -283,5 +283,188 @@ describe('Models', () => {
|
|||
allOf: <any>"
|
||||
`);
|
||||
});
|
||||
describe('enum values', () => {
|
||||
test('should get correct fields enum fields without duplication', () => {
|
||||
const spec = parseYaml(outdent`
|
||||
openapi: 3.0.0
|
||||
components:
|
||||
schemas:
|
||||
StringField: { type: string, title: StringField, enum: [A, B, C] }
|
||||
FieldA: { type: string, title: FieldA, enum: [A1, A2, A3] }
|
||||
FieldB: { type: string, title: FieldB, enum: [B1, B2, B3] }
|
||||
FieldC: { type: string, title: FieldC, enum: [C1, C2, C3] }
|
||||
ObjectWithAllOf:
|
||||
title: StringFilter
|
||||
type: object
|
||||
allOf:
|
||||
- properties:
|
||||
type: { type: string, enum: [STRING] }
|
||||
field: { $ref: '#/components/schemas/StringField' }
|
||||
required: [type, field, values]
|
||||
- oneOf:
|
||||
- properties:
|
||||
field: { type: string, enum: [A] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldA' } }
|
||||
- properties:
|
||||
field: { type: string, enum: [B] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldB' } }
|
||||
- properties:
|
||||
field: { type: string, enum: [C] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldC' } }
|
||||
ObjectWithOneOf:
|
||||
title: StringFilter
|
||||
type: object
|
||||
properties:
|
||||
type: { type: string, enum: [STRING] }
|
||||
field: { $ref: '#/components/schemas/StringField' }
|
||||
required: [type, field, values]
|
||||
oneOf:
|
||||
- properties:
|
||||
field: { type: string, enum: [A] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldA' } }
|
||||
- properties:
|
||||
field: { type: string, enum: [B] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldB' } }
|
||||
- properties:
|
||||
field: { type: string, enum: [C] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldC' } }
|
||||
`) as any;
|
||||
|
||||
parser = new OpenAPIParser(spec, undefined, opts);
|
||||
const schemaWithOneOf = new SchemaModel(
|
||||
parser,
|
||||
spec.components.schemas.ObjectWithOneOf,
|
||||
'#/components/schemas/ObjectWithOneOf',
|
||||
opts,
|
||||
);
|
||||
expect(printSchema(schemaWithOneOf, enumDetailsPrinter)).toMatchInlineSnapshot(`
|
||||
"oneOf
|
||||
StringFilter ->
|
||||
field*: <string>enum: [A,B,C]
|
||||
values*: [<string>enum: [A1,A2,A3]]
|
||||
type*: <string>enum: [STRING]
|
||||
StringFilter ->
|
||||
field*: <string>enum: [A,B,C]
|
||||
values*: [<string>enum: [B1,B2,B3]]
|
||||
type*: <string>enum: [STRING]
|
||||
StringFilter ->
|
||||
field*: <string>enum: [A,B,C]
|
||||
values*: [<string>enum: [C1,C2,C3]]
|
||||
type*: <string>enum: [STRING]"
|
||||
`);
|
||||
|
||||
const schemaWithAllOf = new SchemaModel(
|
||||
parser,
|
||||
spec.components.schemas.ObjectWithAllOf,
|
||||
'#/components/schemas/ObjectWithAllOf',
|
||||
opts,
|
||||
);
|
||||
expect(printSchema(schemaWithAllOf, enumDetailsPrinter)).toMatchInlineSnapshot(`
|
||||
"oneOf
|
||||
object ->
|
||||
type*: <string>enum: [STRING]
|
||||
field*: <string>enum: [A,B,C]
|
||||
values*: [<string>enum: [A1,A2,A3]]
|
||||
object ->
|
||||
type*: <string>enum: [STRING]
|
||||
field*: <string>enum: [B,A,C]
|
||||
values*: [<string>enum: [B1,B2,B3]]
|
||||
object ->
|
||||
type*: <string>enum: [STRING]
|
||||
field*: <string>enum: [C,A,B]
|
||||
values*: [<string>enum: [C1,C2,C3]]"
|
||||
`);
|
||||
});
|
||||
|
||||
test('should get correct fields enum limits', () => {
|
||||
const spec = parseYaml(outdent`
|
||||
openapi: 3.0.0
|
||||
components:
|
||||
schemas:
|
||||
StringField: { type: string, title: StringField, enum: [A, B, C] }
|
||||
FieldA: { type: string, title: FieldA, enum: [A1, A2, A3] }
|
||||
FieldB: { type: string, title: FieldB, enum: [B1, B2, B3] }
|
||||
FieldC: { type: string, title: FieldC, enum: [C1, C2, C3] }
|
||||
ObjectWithAllOf:
|
||||
title: StringFilter
|
||||
type: object
|
||||
allOf:
|
||||
- properties:
|
||||
type: { type: string, enum: [STRING] }
|
||||
required: [type, field, values]
|
||||
- oneOf:
|
||||
- properties:
|
||||
field: { type: string, enum: [A] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldA' } }
|
||||
- properties:
|
||||
field: { type: string, enum: [B] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldB' } }
|
||||
- properties:
|
||||
field: { type: string, enum: [C] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldC' } }
|
||||
ObjectWithOneOf:
|
||||
title: StringFilter
|
||||
type: object
|
||||
properties:
|
||||
type: { type: string, enum: [STRING] }
|
||||
required: [type, field, values]
|
||||
oneOf:
|
||||
- properties:
|
||||
field: { type: string, enum: [A] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldA' } }
|
||||
- properties:
|
||||
field: { type: string, enum: [B] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldB' } }
|
||||
- properties:
|
||||
field: { type: string, enum: [C] }
|
||||
values: { type: array, items: { $ref: '#/components/schemas/FieldC' } }
|
||||
`) as any;
|
||||
|
||||
parser = new OpenAPIParser(spec, undefined, opts);
|
||||
const schemaWithOneOf = new SchemaModel(
|
||||
parser,
|
||||
spec.components.schemas.ObjectWithOneOf,
|
||||
'#/components/schemas/ObjectWithOneOf',
|
||||
opts,
|
||||
);
|
||||
expect(printSchema(schemaWithOneOf, enumDetailsPrinter)).toMatchInlineSnapshot(`
|
||||
"oneOf
|
||||
StringFilter ->
|
||||
field*: <string>enum: [A]
|
||||
values*: [<string>enum: [A1,A2,A3]]
|
||||
type*: <string>enum: [STRING]
|
||||
StringFilter ->
|
||||
field*: <string>enum: [B]
|
||||
values*: [<string>enum: [B1,B2,B3]]
|
||||
type*: <string>enum: [STRING]
|
||||
StringFilter ->
|
||||
field*: <string>enum: [C]
|
||||
values*: [<string>enum: [C1,C2,C3]]
|
||||
type*: <string>enum: [STRING]"
|
||||
`);
|
||||
|
||||
const schemaWithAllOf = new SchemaModel(
|
||||
parser,
|
||||
spec.components.schemas.ObjectWithAllOf,
|
||||
'#/components/schemas/ObjectWithAllOf',
|
||||
opts,
|
||||
);
|
||||
expect(printSchema(schemaWithAllOf, enumDetailsPrinter)).toMatchInlineSnapshot(`
|
||||
"oneOf
|
||||
object ->
|
||||
type*: <string>enum: [STRING]
|
||||
field*: <string>enum: [A]
|
||||
values*: [<string>enum: [A1,A2,A3]]
|
||||
object ->
|
||||
type*: <string>enum: [STRING]
|
||||
field*: <string>enum: [B]
|
||||
values*: [<string>enum: [B1,B2,B3]]
|
||||
object ->
|
||||
type*: <string>enum: [STRING]
|
||||
field*: <string>enum: [C]
|
||||
values*: [<string>enum: [C1,C2,C3]]"
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,6 +12,10 @@ export function circularDetailsPrinter(schema: SchemaModel): string {
|
|||
return schema.isCircular ? ' !circular' : '';
|
||||
}
|
||||
|
||||
export function enumDetailsPrinter(schema: SchemaModel): string {
|
||||
return schema.enum ? `enum: [${schema.enum.toString()}]` : '';
|
||||
}
|
||||
|
||||
export function printSchema(
|
||||
schema: SchemaModel,
|
||||
detailsPrinter: (schema: SchemaModel) => string = () => '',
|
||||
|
|
Loading…
Reference in New Issue
Block a user