Test download of pdf with rspec and pdfkit
Solution 1
Not sure why you're getting that failure but you could instead test the response headers:
response_headers["Content-Type"].should == "application/pdf"
response_headers["Content-Disposition"].should == "attachment; filename=\"<invoice_name>.pdf\""
You asked for advice regarding better test coverage. I thought I'd recommend this: https://www.destroyallsoftware.com/screencasts. These screencasts have had a huge impact on my understanding of test-driven development -- highly recommended!
Solution 2
I recommend using the pdf-inspector gem for writing specs for PDF related Rails actions.
Here's an exemplary spec (which assumes the Rails #report
action writes data about a Ticket
model in the generated PDF):
describe 'GET /report.pdf' do
it 'returns downloadable PDF with the ticket' do
ticket = FactoryGirl.create :ticket
get report_path, format: :pdf
expect(response).to be_successful
analysis = PDF::Inspector::Text.analyze response.body
expect(analysis.strings).to include ticket.state
expect(analysis.strings).to include ticket.title
end
end
![Dennis Hackethal](https://i.stack.imgur.com/Qpq1r.png?s=256&g=1)
Comments
-
Dennis Hackethal almost 2 years
I am developing a rails 3.2 application with which users can download pdfs. I enjoy test driven development a lot using rspec and shoulda matchers, but I'm at a loss with this one.
I have the following code inside my controller:
def show_as_pdf @client = Client.find(params[:client_id]) @invoice = @client.invoices.find(params[:id]) PDFKit.configure do |config| config.default_options = { :footer_font_size => "6", :encoding => "UTF-8", :margin_top=>"1in", :margin_right=>"1in", :margin_bottom=>"1in", :margin_left=>"1in" } end pdf = PDFKit.new(render_to_string "invoices/pdf", layout: false) invoice_stylesheet_path = File.expand_path(File.dirname(__FILE__) + "/../assets/stylesheets/pdfs/invoices.css.scss") bootstrap_path = File.expand_path(File.dirname(__FILE__) + "../../../vendor/assets/stylesheets/bootstrap.min.css") pdf.stylesheets << invoice_stylesheet_path pdf.stylesheets << bootstrap_path send_data pdf.to_pdf, filename: "#{@invoice.created_at.strftime("%Y-%m-%d")}_#{@client.name.gsub(" ", "_")}_#{@client.company.gsub(" ", "_")}_#{@invoice.number.gsub(" ", "_")}", type: "application/pdf" return true end
This is fairly simple code, all it does is configure my PDFKit and download the generated pdf. Now I want to test the whole thing, including:
- Assignment of instance variables (easy, of course, and that works)
- The sending of data, i.e. the rendering of the pdf => And this is where I'm stuck
I have tried the following:
controller.should_receive(:send_data)
but that gives me
Failure/Error: controller.should_receive(:send_data) (#<InvoicesController:0x007fd96fa3e580>).send_data(any args) expected: 1 time received: 0 times
Does anyone know of a way to test that the pdf is actually downloaded/sent? Also, what more things do you see that should be tested for good test coverage? E.g., testing for the data type, i.e. application/pdf, would be nice.
Thanks!
-
Dennis Hackethal over 11 yearsThanks, but unfortunately that gives me
undefined method 'response_headers'
- what am I doing wrong? -
Dennis Hackethal over 11 yearsHaha, I forgot to
get :show_as_pdf
:) That solves all problems. Thanks a lot! -
Ian Vaughan over 9 yearsI'd like to test the download contents, but with selenium, which doesn't seem to work, anyone know more about that?
-
xhh about 9 yearsusing
response.headers["Content-Type"]
works for me -
ChaosPredictor almost 8 yearsIt works for me with rails 4 / rspec 3.5.0 but not for rails 5. any idea?
-
phil pirozhkov over 7 yearsNote: this spec should be a request spec, not controller spec, the latter stubs
render
with an empty string.