ruby-on-railsrspecjson-apirswag

Following JSON Api with rswag


I'm using rswag to test a rather common RubyOnRails JSON Api application, but I can't figure out a rather common case where I upload a file to an endpoint.

The endpoint expects the usual data attribute in the request body with a file attribute containing the binary, and I cannot make rswag to generate a request with the correct parameters.

  path '/documents' do
    post 'Creates a document' do
      tags 'Documents'
      consumes 'multipart/form-data'
      produces 'application/vnd.api+json'

      parameter name: 'data',
                description: 'Whatever',
                attributes: {
                  schema: {
                    type: :object,
                    properties: {
                      file: { type: :binary },
                    },
                  },
                }

      response '201', 'success' do
        let(:data) do
          {
            attributes: {
              file: Rack::Test::UploadedFile.new($REALARGS),
            },
          }
        end

        schema "$ref": '#/definitions/post_document_responses/201'

        run_test! do |_example|
          # ACTUAL TEST
        end
      end
    end
  end

There are some other simpler parameters (Authorization for example) that are correctly generated, I'm then sure rswag is hooked correctly. The request I'm seeing has no parameters, I can remove the data parameter and nothing changes. I've tried a million combinations, always the same result and I don't know what's going on.

The params the controller expects is data[attributes][file].

Can anyone help me?


Solution

  • The parameter block needs to specify where it will be inserted. There's an example spec where I found a reference to :formData, which it turns out must be set (i.e. you can't use :body, it just sends an empty request).

    After a bit of jiggery-pokery I managed to get your example working with the nested attribute in the form data:

    path '/documents' do
      post 'Creates a document' do
        tags 'Documents'
        consumes 'multipart/form-data'
        produces 'application/vnd.api+json'
    
        parameter name: 'data[attributes][file]',
                  description: 'Whatever',
                  in: :formData,
                  attributes: {
                    schema: {
                      type: :object,
                      properties: {
                        file: { type: :binary },
                      },
                    },
                  }
    
        response '201', 'success' do
          let(:"data[attributes][file]") { Rack::Test::UploadedFile.new(Rails.root.join("spec/requests/api/v1/documents_post_spec.rb")) }
          end
    
          schema "$ref": '#/definitions/post_document_responses/201'
    
          run_test! do |_example|
            # ACTUAL TEST
          end
        end
      end
    end