swagger-api / swagger-ui

Swagger UI is a collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.
https://swagger.io
Apache License 2.0
26.59k stars 8.96k forks source link

Models using allOf break when deeply nested by $ref #7437

Open plutalov opened 3 years ago

plutalov commented 3 years ago

Q&A (please complete the following information)

Content & configuration

Example Swagger/OpenAPI definition:

openapi: 3.0.0
info:
  title: Test REST API
  version: 1.0.0
components:
  schemas:
    TheOneWhichBreaks:
      allOf:
        - type: object
          properties:
            id:
              type: string
        - type: object
          properties:
            position:
              type: integer
    ReferringA:
      type: object
      properties:
        theOneWhichBreaks:
          $ref: "#/components/schemas/TheOneWhichBreaks"
    ReferringB:
      type: object
      properties:
        referringA:
          $ref: "#/components/schemas/ReferringA"
    HereBreaksToo:
      type: object
      properties:
        referringB:
          $ref: "#/components/schemas/ReferringB"
paths:
  /works:
    get:
      tags:
        - Test
      summary: Shown as intended
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  referringA:
                    $ref: "#/components/schemas/ReferringA"
  /breaks:
    get:
      tags:
        - Test
      summary: Isn't shown as intended
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  referringB:
                    $ref: "#/components/schemas/ReferringB"

Describe the bug you're encountering

A model combining other models with allOf doesn't show properly if there are 3 or more $ref usages on higher levels. In this case it usually has a value "string" or empty object.

To reproduce...

Steps to reproduce the behavior:

  1. Go to editor.swagger.io
  2. Paste the definition I left above
  3. Compare responses of two paths. Notice how TheOneWhichBrakes model shows
  4. You also can check a model called "HereBreaksToo"

Expected behavior

Referenced models should render their type despite of referencing depth.

Screenshots

Screenshot from 2021-07-28 09-06-33 Screenshot from 2021-07-28 09-06-41 Screenshot from 2021-07-28 09-06-20

Additional context or thoughts

I've managed to reproduce the bug using different environments:

swagger-ui-express

swagger-ui-express@4.1.6 swagger-ui-dist@3.51.1

WebStorm

Plugin OpenAPI Specifications 202.7319.8

editor.swagger.io

There is a feature here. It reproduces during the first render. But there is an algorithm which makes it display properly:

  1. Expand the /works path. It always shows TheOneWhichBrakes model properly. You also can just expand TheOneWhichBrakes model itself
  2. Expand the /breaks path. It will show you the broken view
  3. Make a meaningless change in the editor. You can add an extra line in the end of the definition
  4. See how /breaks is rendered as intended now
hkosova commented 3 years ago

This is probably the same issue as #5972 and https://github.com/swagger-api/swagger-js/issues/1425.

The workaround suggested in those issues is to move paths before components in the OpenAPI file.

el-peregrino commented 2 years ago

I am facing the same issue, using open api 3.0.1, paths are before the components. My models are nested using mainly allOf refs. I validated the schema. It's ok, I can see all the data in there.

Updated to the latest version today (using dist), the issue is still there. No errors in the console. The schema tree simply stops at the third level and makes the rest as strings.

Tried the online swagger editor, and it produces the same issue.

FeepingCreature commented 2 years ago

I don't really know JS, but I've had a cursory look. sampleFromSchemaGeneric in fn.js doesn't seem to recognize or handle allOf at all? Meaning it falls back to type recovery, and from there "string".

Considering a grep for allOf turns up nothing in src/, I'm not sure how this works at all.