From 7cc0500f3c1ddd1da17ee31278468207093f9281 Mon Sep 17 00:00:00 2001 From: Alex Varchuk Date: Tue, 19 Jul 2022 09:57:43 +0300 Subject: [PATCH] fix: property with nested allOf (#2083) --- .../DiscriminatorDropdown.test.tsx.snap | 9 ++++ src/services/OpenAPIParser.ts | 6 +++ .../__tests__/models/RequestBody.test.ts | 52 +++++++++++++++++++ src/services/__tests__/models/Schema.test.ts | 43 +++++++++++++++ .../models/__snapshots__/Schema.test.ts.snap | 23 ++++++++ 5 files changed, 133 insertions(+) diff --git a/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap b/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap index 7695ff5275..5f865af57e 100644 --- a/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap @@ -843,6 +843,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView ], "schema": Object { "allOf": undefined, + "description": undefined, "discriminator": Object { "propertyName": "type", }, @@ -858,11 +859,13 @@ exports[`Components SchemaView discriminator should correctly render SchemaView ], }, }, + "readOnly": undefined, "required": Array [ "type", ], "title": "Dog", "type": "object", + "writeOnly": undefined, "x-circular-ref": undefined, "x-parentRefs": Array [ "#/components/schemas/Pet", @@ -1699,6 +1702,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView ], "schema": Object { "allOf": undefined, + "description": undefined, "discriminator": Object { "propertyName": "type", }, @@ -1717,11 +1721,13 @@ exports[`Components SchemaView discriminator should correctly render SchemaView ], }, }, + "readOnly": undefined, "required": Array [ "type", ], "title": "Cat", "type": "object", + "writeOnly": undefined, "x-circular-ref": undefined, "x-parentRefs": Array [ "#/components/schemas/Pet", @@ -2811,6 +2817,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView ], "schema": Object { "allOf": undefined, + "description": undefined, "discriminator": Object { "propertyName": "type", }, @@ -2826,11 +2833,13 @@ exports[`Components SchemaView discriminator should correctly render SchemaView ], }, }, + "readOnly": undefined, "required": Array [ "type", ], "title": "Dog", "type": "object", + "writeOnly": undefined, "x-circular-ref": undefined, "x-parentRefs": Array [ "#/components/schemas/Pet", diff --git a/src/services/OpenAPIParser.ts b/src/services/OpenAPIParser.ts index 303ae17201..ef8930e85f 100644 --- a/src/services/OpenAPIParser.ts +++ b/src/services/OpenAPIParser.ts @@ -217,6 +217,9 @@ export class OpenAPIParser { items, required, title, + description, + readOnly, + writeOnly, oneOf, anyOf, 'x-circular-ref': isCircular, @@ -305,6 +308,9 @@ export class OpenAPIParser { receiver = { ...receiver, title: receiver.title || title, + description: receiver.description || description, + readOnly: receiver.readOnly !== undefined ? receiver.readOnly : readOnly, + writeOnly: receiver.writeOnly !== undefined ? receiver.writeOnly : writeOnly, 'x-circular-ref': receiver['x-circular-ref'] || isCircular, ...otherConstraints, }; diff --git a/src/services/__tests__/models/RequestBody.test.ts b/src/services/__tests__/models/RequestBody.test.ts index 554a1222a6..e8720c9b1c 100644 --- a/src/services/__tests__/models/RequestBody.test.ts +++ b/src/services/__tests__/models/RequestBody.test.ts @@ -1,3 +1,5 @@ +import { parseYaml } from '@redocly/openapi-core'; +import { outdent } from 'outdent'; import { RequestBodyModel } from '../../models/RequestBody'; import { OpenAPIParser } from '../../OpenAPIParser'; import { RedocNormalizedOptions } from '../../RedocNormalizedOptions'; @@ -23,5 +25,55 @@ describe('Models', () => { expect(consoleError).not.toHaveBeenCalled(); expect(req).toEqual({ description: '', required: false }); }); + + test('should have correct field data when it includes allOf', () => { + const spec = parseYaml(outdent` + openapi: 3.0.0 + paths: + /user: + post: + tags: + - user + summary: Create user + description: This can only be done by the logged in user. + operationId: createUser + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Created user object + required: true + components: + schemas: + User: + allOf: + - type: object + properties: + name: + type: string + description: correct description name + readOnly: false + writeOnly: false + allOf: + - $ref: '#/components/schemas/NameField' + NameField: + description: name description + readOnly: true + writeOnly: true + `) as any; + + parser = new OpenAPIParser(spec, undefined, opts); + const req = new RequestBodyModel({ + parser, + infoOrRef: spec.paths['/user'].post.requestBody, + options: opts, + isEvent: false, + }); + const nameField = req.content?.mediaTypes[0].schema?.fields?.[0]; + expect(nameField?.schema.readOnly).toBe(false); + expect(nameField?.schema.writeOnly).toBe(false); + expect(nameField?.description).toMatchInlineSnapshot(`"correct description name"`); + }); }); }); diff --git a/src/services/__tests__/models/Schema.test.ts b/src/services/__tests__/models/Schema.test.ts index 8e73879a2c..85f72a4f7f 100644 --- a/src/services/__tests__/models/Schema.test.ts +++ b/src/services/__tests__/models/Schema.test.ts @@ -1,7 +1,10 @@ /* eslint-disable @typescript-eslint/no-var-requires */ +import { parseYaml } from '@redocly/openapi-core'; +import { outdent } from 'outdent'; import { SchemaModel } from '../../models/Schema'; import { OpenAPIParser } from '../../OpenAPIParser'; import { RedocNormalizedOptions } from '../../RedocNormalizedOptions'; +import { printSchema } from './helpers'; const opts = new RedocNormalizedOptions({}); @@ -240,5 +243,45 @@ describe('Models', () => { }, ); }); + + test('should get correct fields data if it includes allOf', () => { + const spec = parseYaml(outdent` + openapi: 3.0.0 + components: + schemas: + User: + allOf: + - type: object + properties: + name: + type: string + description: correct description name + readOnly: false + writeOnly: false + allOf: + - '#/components/schemas/NameField' + NameField: + type: object + description: name description + readOnly: true + writeOnly: false + + `) as any; + + parser = new OpenAPIParser(spec, undefined, opts); + const schema = new SchemaModel( + parser, + spec.components.schemas.User, + '#/components/schemas/User', + opts, + ); + const fieldSchema = schema.fields?.[0].schema; + expect(fieldSchema?.readOnly).toBe(false); + expect(fieldSchema?.writeOnly).toBe(false); + expect(printSchema(schema)).toMatchInlineSnapshot(` + "name: (correct description name) + allOf: " + `); + }); }); }); diff --git a/src/services/__tests__/models/__snapshots__/Schema.test.ts.snap b/src/services/__tests__/models/__snapshots__/Schema.test.ts.snap index 63396ec6c3..b28bc664fd 100644 --- a/src/services/__tests__/models/__snapshots__/Schema.test.ts.snap +++ b/src/services/__tests__/models/__snapshots__/Schema.test.ts.snap @@ -4,18 +4,24 @@ exports[`Models Schema schemaDefinition should resolve field with conditional op Object { "allOf": undefined, "default": undefined, + "description": undefined, "items": Object { "allOf": undefined, + "description": undefined, "format": "url", + "readOnly": undefined, "title": undefined, "type": "string", + "writeOnly": undefined, "x-circular-ref": undefined, "x-parentRefs": Array [], }, "maxItems": 20, "minItems": 1, + "readOnly": undefined, "title": "isString", "type": "string", + "writeOnly": undefined, "x-circular-ref": undefined, "x-displayName": "isString", "x-parentRefs": Array [], @@ -26,23 +32,29 @@ exports[`Models Schema schemaDefinition should resolve field with conditional op Object { "allOf": undefined, "default": undefined, + "description": undefined, "items": Object { "allOf": undefined, + "description": undefined, "format": "url", + "readOnly": undefined, "title": undefined, "type": "string", + "writeOnly": undefined, "x-circular-ref": undefined, "x-parentRefs": Array [], }, "maxItems": 10, "minItems": 1, "pattern": "\\\\d+", + "readOnly": undefined, "title": "notString", "type": Array [ "string", "integer", "null", ], + "writeOnly": undefined, "x-circular-ref": undefined, "x-displayName": "notString", "x-parentRefs": Array [], @@ -52,6 +64,7 @@ Object { exports[`Models Schema schemaDefinition should resolve schema with conditional operators 1`] = ` Object { "allOf": undefined, + "description": undefined, "maxItems": 2, "properties": Object { "test": Object { @@ -62,20 +75,25 @@ Object { ], "items": Object { "allOf": undefined, + "description": undefined, "format": "url", + "readOnly": undefined, "title": undefined, "type": "string", + "writeOnly": undefined, "x-circular-ref": undefined, "x-parentRefs": Array [], }, "maxItems": 20, "minItems": 1, + "readOnly": undefined, "title": undefined, "type": Array [ "string", "integer", "null", ], + "writeOnly": undefined, "x-circular-ref": undefined, "x-parentRefs": Array [], "x-refsStack": Array [ @@ -83,8 +101,10 @@ Object { ], }, }, + "readOnly": undefined, "title": "=== 10", "type": "object", + "writeOnly": undefined, "x-circular-ref": undefined, "x-parentRefs": Array [], } @@ -93,6 +113,7 @@ Object { exports[`Models Schema schemaDefinition should resolve schema with conditional operators 2`] = ` Object { "allOf": undefined, + "description": undefined, "maxItems": 20, "properties": Object { "test": Object { @@ -113,8 +134,10 @@ Object { ], }, }, + "readOnly": undefined, "title": "case 2", "type": "object", + "writeOnly": undefined, "x-circular-ref": undefined, "x-parentRefs": Array [], }