ruby-on-rails - rspec_api_documentation - 如何有多个例子

标签 ruby-on-rails swagger openapi rswag rspec-api-documentation

我的目标是使用 rspec_api_documentation 和 rswag-ui 或通过将 swagger-ui 直接添加到项目中来显示参数和响应的多个示例。我在用我的配置生成正确的 open_api.json 时遇到了一些问题,我想知道我做错了什么。

gem :

  • https://github.com/zipmark/rspec_api_documentation
  • https://github.com/rswag/rswag

  • 用于测试的 rspec_api_documentation 配置:
    # spec/acceptance_helper.rb
    require 'spec_helper'
    require 'rspec_api_documentation'
    require 'rspec_api_documentation/dsl'
    
    RspecApiDocumentation.configure do |config|
      config.app = Rails.application
    
      config.api_name = 'My API'
      config.api_explanation = 'API Description'
    
      config.configurations_dir = Rails.root.join('public', 'docs', 'api', 'config')
      config.docs_dir = Rails.root.join('public', 'docs', 'api', 'generated')
    
      config.format = :open_api
    
      API_VERSIONS.each do |version|
        config.define_group(version) do |config|
          config.docs_dir = Rails.root.join('public', 'docs', 'api', 'generated', version.to_s)
        end
      end
    
      config.client_method = :client
    
      config.io_docs_protocol = 'https'
    
      config.request_headers_to_include = nil
      config.request_body_formatter = :json
    
      config.response_headers_to_include = []
      config.response_body_formatter = Proc.new { |response_content_type, response_body|
        response_body
      }
    end
    
    

    OpenAPI 配置:
    swagger: '2.0'
    info:
      title: My Api
      description: Blah.
      termsOfService: 'http://open-api.io/terms/'
      contact:
        name: API Support
        url: 'http://www.open-api.io/support'
        email: support@domain.com
      license:
        name: Apache 2.0
        url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
      version: 1.0.0
    host: 'localhost:3000'
    schemes:
      - http
      - https
    consumes:
      - application/json
    produces:
      - application/json
    
    

    示例测试:
    require 'documentation_helper'
    
    resource 'Sessions' do
      header 'Accept', 'application/json'
      header 'Content-Type', 'application/json'
    
      explanation 'Endpoints to start and end API sessions for a user'
    
      route '/api/v1/users/sign_in', 'Sign In' do
        route_summary 'Starts a new session for a user'
        route_description 'Given valid credentials, will create a new API session for a user'
    
        post 'Signing in a user', document: :v1  do
          let(:user) { FactoryBot.create(:user) }
    
          parameter :login, 'The username or email of the user', scope: :user, required: true
          parameter :password, 'The password for the user', scope: :user, required: true
    
          example '401 - No user object', document: :v1 do
            request = { login: user.email, password: user.password }
    
            do_request(request)
    
            expect(status).to eq(401)
            expect(json.keys.size).to eq(1)
            expect(json['error']).to eq(I18n.t('devise.failure.unauthenticated'))
          end
    
          example '401 - No login', document: :v1 do
            request = { user: { password: user.password } }
    
            do_request(request)
    
            expect(status).to eq(401)
            expect(json.keys.size).to eq(1)
            expect(json['error']).to eq(I18n.t('devise.failure.unauthenticated'))
          end
        end
      end
    end
    
    

    生成的输出:
    {
      "swagger": "2.0",
      "info": {
        "title": "My Api",
        "description": "Blah.",
        "termsOfService": "http://open-api.io/terms/",
        "contact": {
          "name": "API Support",
          "url": "http://www.open-api.io/support",
          "email": "support@domain.com"
        },
        "license": {
          "name": "Apache 2.0",
          "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
        },
        "version": "1.0.0"
      },
      "host": "localhost:3000",
      "schemes": [
        "http",
        "https"
      ],
      "consumes": [
        "application/json"
      ],
      "produces": [
        "application/json"
      ],
      "paths": {
        "/api/v1/users/sign_in": {
          "post": {
            "tags": [
              "Sessions"
            ],
            "summary": "Starts a new session for a user",
            "description": "Given valid credentials, will create a new API session for a user",
            "consumes": [
              "application/json"
            ],
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "name": "body",
                "in": "body",
                "description": "",
                "required": false,
                "schema": {
                  "type": "object",
                  "properties": {
                    "user": {
                      "type": "object",
                      "properties": {
                        "login": {
                          "type": "string",
                          "description": "The username or email of the user"
                        },
                        "password": {
                          "type": "string",
                          "description": "The password for the user"
                        }
                      },
                      "required": [
                        "login",
                        "password"
                      ]
                    }
                  }
                }
              }
            ],
            "responses": {
              "401": {
                "description": "No login",
                "schema": {
                  "type": "object",
                  "properties": {
                  }
                },
                "headers": {
                },
                "examples": {
                  "application/json": {
                    "error": "You need to sign in or sign up before continuing."
                  }
                }
              }
            },
            "deprecated": false,
            "security": [
    
            ]
          }
        }
      },
      "tags": [
        {
          "name": "Sessions",
          "description": "Endpoints to start and end API sessions for a user"
        }
      ]
    }
    

    enter image description here
    期望的输出(至少我认为):
    {
      "swagger": "2.0",
      "info": {
        "title": "My Api",
        "description": "Blah.",
        "termsOfService": "http://open-api.io/terms/",
        "contact": {
          "name": "API Support",
          "url": "http://www.open-api.io/support",
          "email": "support@domain.com"
        },
        "license": {
          "name": "Apache 2.0",
          "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
        },
        "version": "1.0.0"
      },
      "host": "localhost:3000",
      "schemes": [
        "http",
        "https"
      ],
      "consumes": [
        "application/json"
      ],
      "produces": [
        "application/json"
      ],
      "paths": {
        "/api/v1/users/sign_in": {
          "post": {
            "tags": [
              "Sessions"
            ],
            "summary": "Starts a new session for a user",
            "description": "Given valid credentials, will create a new API session for a user",
            "consumes": [
              "application/json"
            ],
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "name": "body",
                "in": "body",
                "description": "",
                "required": false,
                "schema": {
                  "type": "object",
                  "properties": {
                    "user": {
                      "type": "object",
                      "properties": {
                        "login": {
                          "type": "string",
                          "description": "The username or email of the user"
                        },
                        "password": {
                          "type": "string",
                          "description": "The password for the user"
                        }
                      },
                      "required": [
                        "login",
                        "password"
                      ]
                    }
                  }
                }
              }
            ],
            "responses": {
              "401": {
                "description": "Invalid params",
                "schema": {
                  "type": "object",
                  "properties": {
                  }
                },
                "headers": {
                },
                "examples": {
                  "No password": {
                    "error": "You need to sign in or sign up before continuing."
                  },
                  "No login": {
                    "error": "You need to sign in or sign up before continuing."
                  }
                }
              }
            },
            "deprecated": false,
            "security": [
    
            ]
          }
        }
      },
      "tags": [
        {
          "name": "Sessions",
          "description": "Endpoints to start and end API sessions for a user"
        }
      ]
    }
    

    enter image description here

    最佳答案

    对不起,我迟到了一年,但我自己也遇到了这个。我目前正在尝试通过使用 swagger-codegen 将 open_api 输出转换为 open_api v3 来将我们的文档连接到 postman 。
    在查看 rspec_api_documentation 的代码后,它看起来像是使用哈希作为构建文档的类型,并且它使用的 key 依赖于 path + http_method .因此,如果您尝试有多个使用相同 key 但具有不同有效负载的示例,那么由于此原因,它将采用第一个:https://github.com/zipmark/rspec_api_documentation/blob/d3892cc7388460a98476734963face5a7a2ac158/lib/rspec_api_documentation/open_api/node.rb#L65
    我解决这个问题的方法是将一个虚拟查询参数传递给路径以创建一个唯一的键。例子:

            post "/api/v2/foos?example=example1" do
              example "example1" do
                do_request(payload1)
              end
            end
    
            post "/api/v2/foos?example=example2" do
              example "example2" do
                do_request(payload2)
              end
            end
    
    这并不完全理想,因为我宁愿在同一请求下将示例组合在一起,但它至少为我提供了我想要的文档(减去虚拟参数)。
    希望这个解决方法有帮助。如果我找到一种提交补丁的方法,以便附加而不是跳过示例,我将发布一个指向 PR 的链接。

    关于ruby-on-rails - rspec_api_documentation - 如何有多个例子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60471608/

    相关文章:

    ruby-on-rails - 如何在 Rails 中创建具有 NULLS LAST 的索引?

    swagger - 打开 api 3 发布一组文件

    swagger - OpenAPI 3.0 - 如何避免在通过 ref 包含示例时添加 "value" key

    yaml - OpenAPI YAML 描述中 |、> 和 >- 之间有什么区别?

    javascript - 让 jQuery 在 Rails 应用程序上运行

    javascript - 带有 stylesheet_link_tag 的 HTML1506 : Unexpected token,

    node.js - 在 swagger Node 项目中使用异步中间件功能

    java - Swagger 集成多个 jaxrs 服务器

    datetime - 带有时区信息的 OpenAPI DateTime

    ruby-on-rails - NotImplementedError(仅支持部分劫持。)使用 message_bus