diff --git a/README.md b/README.md index 0ac0e3e..0c230d3 100644 --- a/README.md +++ b/README.md @@ -532,3 +532,16 @@ bundle exec rake rswag:ui:copy_assets[public/api-docs] ``` __NOTE:__: The provided subfolder MUST correspond to the UI mount prefix - "api-docs" by default. + + +Notes to test swagger output locally with swagger editor +``` +docker pull swaggerapi/swagger-editor +``` +``` +docker run -d -p 80:8080 swaggerapi/swagger-editor +``` +This will run the swagger editor in the docker daemon and can be accessed +at ```http://localhost```. From here, you can use the UI to load the generated swagger.json to validate the output. + + diff --git a/rswag-specs/lib/rswag/specs/example_group_helpers.rb b/rswag-specs/lib/rswag/specs/example_group_helpers.rb index fedd5d7..27bd2db 100644 --- a/rswag-specs/lib/rswag/specs/example_group_helpers.rb +++ b/rswag-specs/lib/rswag/specs/example_group_helpers.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +require 'hashie' module Rswag module Specs @@ -75,6 +76,30 @@ module Rswag end end + def request_body_multipart(schema:, description: nil) + content_hash = { 'multipart/form-data' => { schema: schema }} + request_body(description: description, content: content_hash) + + schema.extend(Hashie::Extensions::DeepLocate) + file_properties = schema.deep_locate -> (_k, v, _obj) { v == :binary } + + hash_locator = [] + + file_properties.each do |match| + hash_match = schema.deep_locate -> (_k, v, _obj) { v == match } + hash_locator.concat(hash_match) unless hash_match.empty? + end + + property_hashes = hash_locator.flat_map do |locator| + locator.select { |_k,v| file_properties.include?(v) } + end + + property_hashes.each do |property_hash| + file_name = property_hash.keys.first + parameter name: file_name, in: :formData, type: :file, required: true + end + end + def parameter(attributes) if attributes[:in] && attributes[:in].to_sym == :path attributes[:required] = true diff --git a/rswag-specs/lib/rswag/specs/swagger_formatter.rb b/rswag-specs/lib/rswag/specs/swagger_formatter.rb index 35a90bb..3456e40 100644 --- a/rswag-specs/lib/rswag/specs/swagger_formatter.rb +++ b/rswag-specs/lib/rswag/specs/swagger_formatter.rb @@ -44,7 +44,7 @@ module Rswag value[:requestBody][:content]['application/json'].merge!(schema: schema_param[:schema]) end - value[:parameters].reject! { |p| p[:in] == :body } + value[:parameters].reject! { |p| p[:in] == :body || p[:in] == :formData } value[:parameters].each { |p| p.delete(:type) } value[:headers].each { |p| p.delete(:type)} if value[:headers] end diff --git a/rswag-specs/rswag-specs.gemspec b/rswag-specs/rswag-specs.gemspec index bbf04eb..f402cdb 100644 --- a/rswag-specs/rswag-specs.gemspec +++ b/rswag-specs/rswag-specs.gemspec @@ -18,5 +18,6 @@ Gem::Specification.new do |s| s.add_dependency 'activesupport', '>= 3.1', '< 6.0' s.add_dependency 'json-schema', '~> 2.2' s.add_dependency 'railties', '>= 3.1', '< 6.0' + s.add_dependency 'hashie' s.add_development_dependency 'guard-rspec' end diff --git a/test-app/spec/integration/blogs_spec.rb b/test-app/spec/integration/blogs_spec.rb index 50d5247..c603a80 100644 --- a/test-app/spec/integration/blogs_spec.rb +++ b/test-app/spec/integration/blogs_spec.rb @@ -65,7 +65,7 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do description 'Retrieves a specific blog by id' operationId 'getBlog' produces 'application/json' - + parameter name: :id, in: :path, type: :string response '200', 'blog found' do @@ -106,7 +106,9 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do description 'Upload a thumbnail for specific blog by id' operationId 'uploadThumbnailBlog' consumes 'multipart/form-data' - parameter name: :file, in: :formData, type: :file, required: true + # parameter name: :file, in: :formData, type: :file, required: true + + request_body_multipart schema: {properties: {:orderId => { type: :integer }, file: { type: :string, format: :binary }} } response '200', 'blog updated' do let(:file) { Rack::Test::UploadedFile.new(Rails.root.join('spec/fixtures/thumbnail.png')) } @@ -115,3 +117,4 @@ describe 'Blogs API', type: :request, swagger_doc: 'v1/swagger.json' do end end end + diff --git a/test-app/swagger/v1/swagger.json b/test-app/swagger/v1/swagger.json index f90ea02..9660b82 100644 --- a/test-app/swagger/v1/swagger.json +++ b/test-app/swagger/v1/swagger.json @@ -177,14 +177,6 @@ "schema": { "type": "string" } - }, - { - "name": "file", - "in": "formData", - "required": true, - "schema": { - "type": "file" - } } ], "tags": [ @@ -192,6 +184,23 @@ ], "description": "Upload a thumbnail for specific blog by id", "operationId": "uploadThumbnailBlog", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "properties": { + "orderId": { + "type": "integer" + }, + "file": { + "type": "string", + "format": "binary" + } + } + } + } + } + }, "responses": { "200": { "description": "blog updated"