lundi 27 juin 2016

Why is my controller acting different in the rspec execution than in the browser execution?

I have my controller:

class Api::BunknotesController < Api::ApiController
  # ... omitted code
  def show
    @bunknote =
      current_user.bunknotes.includes(:person).find(params[:id])

    respond_to do |format|
      format.html {
        render layout: false
      }
      format.pdf {
        render pdf: @bunknote.filename,
          template: '/bunknotes/show.pdf',
          margin: { top: 5, bottom: 5 }
        byebug
      }
      format.json {
        render json: @bunknote.api_json(true)
      }
    end
  end
  # ... omitted code
end

In the second format, Wicked PDF is used to render. The rendered template looks like this:

<%= wicked_pdf_stylesheet_link_tag "bunknotes" %>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<div class="page <% if @bunknote.reply %>pagebreak<% end %> bunknote_pdf">
    <div class="bn-id">bn<%= @bunknote.id %></div>
    <h1>Bunk Note to <%= @bunknote.person ? @bunknote.person.name : @bunknote.writein %> <%= "(#{@bunknote.address})" if @bunknote.address && @bunknote.address.length > 1 %></h1>
    <%= render partial: 'details', locals: { :bunknote => @bunknote } %>
</div>
<% if @bunknote.reply %>
<div class="page bunkreply-stationery">
  <%=
    render partial: '/common/stationery',
    locals: {
      user_fullname: @bunknote.user.fullname,
      org_name: @bunknote.organization.name,
      org_id: @bunknote.organization.id,
      user_id: @bunknote.user.id,
      bunknote_id: "bn#{@bunknote.id}",
      barcode_value: "#{has_bunknote = 1}#{@bunknote.id}",
      height: "720px",
      camper_name:  @bunknote.person ? @bunknote.person.name : @bunknote.writein
    }
  %>
</div>
<% end %>

When I try to hit my controller, I have a template error. The error's nature is like this: Inside my show.pdf.erb template, which is /bunknotes/show.pdf.erb, I am referencing the file 'details'. Since my controller is Api::BunknotesController (there is another controller named BunknotesController, without prefix, which had a copy of this template in first place), the relative inclusion would try to find the file in /app/views/api/bunknotes/ instead of /app/views/bunknotes.

By trying to hit it in my browser, I get a 500 when trying to render the pdf, and the byebug instruction is not reached (as anyone could expect when having any exception out of the special purpose ones in rails like RecordInvalid and so). Due to other internals, the generated pdf is corrupt on this scenario (something we will fix later but for now it serves as a good sign that something did not go well).

However a pretty different behavior is triggered when running a test

My test file looks like:

# ... omitted code
describe Api::BunknotesController do
    # ... omitted code
    it "gets a bunknote (PDF)" do
      get :show, {id: bunknote1.id, format: :pdf}
      expect(response.status).to be 200
    end
    # ... omitted code
end
# ... omitted code

When the rspec utility runs this example, A blank pdf (non-corrupt, but totally blank) is generated by the controller, and a 200 response code is returned.

I made this test to succeed for a 200 code if things got well. The test should have failed when the show view misreferenced (for my needs) the inner view. But instead it succeeded, seeming to absorb the error like a diaper, and generating the blank PDF file. I expect that this behave exactly as the browser call, generate the corrupt pdf, returns a 500 code, and fails.

Summary:

  1. Yes, I will fix the path to the included view so it is absolute.
  2. Yes, I will fix the corrupt pdf generation so that no pdf attachment files are ever sent.
  3. The test should not have succeeded as it did. The test is expected to succeed only if the response code is 200. This is right, but the controller produced a 200 in the rspec execution, while returning a 500 in the browser execution.

Why is my controller acting different in the rspec execution than in the browser execution?

I am using:

  • Ruby 2.3.0p0
  • Rails 3.2.22.2
  • RSpec 3.4.1

Aucun commentaire:

Enregistrer un commentaire