Why response.body not readable with xlsx format - ruby-on-rails

I want to add the RSpec test for our exporting file with the xlsx file but after getting the index of the end-point with xlsx format, my response.body is not readable and I can't check file contents
rspec:
it 'returns a successful 200 response for xlsx format' do
get :index, format: :json
expect(response).to be_successful
expect(response.headers['Content-Type']).to eq('my_value'; charset=utf-8')
expect(response.request.fullpath).to eq('end_poing_path.xlsx')
end
but when I want to check response.body I got bellow picture

I used caxlsx gem and it's can't read Excel files, so I had to install another gem (Roo or simple_xlsx_reader) for reading excel files, then I open response.body or file with simple_xlsx_reader gem

Related

How get pdf file from httparty get response

I would like render a PDF with wicked_pdf or download it from GET response with httparty,
I succeed to do it with curl -o filename url but i dont know how do it with Rails
You can do it like this:
filename = "tmp/test.pdf"
File.open(filename, "w") do |file|
file.binmode
HTTParty.get(URL_TO_PDF, stream_body: true) do |fragment|
file.write(fragment)
end
end
Replace URL_TO_PDF with your pdf url

Download zip file from rails 4 to angularjs

I'm trying to download a zip file, sent from a rails 4 application to the front-end.
The zip file construction is working correctly, I can unzip the file and get the content
filename = "cvs_job_#{params[:job_id]}.zip"
archive_path ="#{Rails.root}/tmp/#{filename}"
File.delete(archive_path) if File.exists?(archive_path)
Zip::File.open(archive_path, Zip::File::CREATE) do |zipfile|
params[:user_ids].each do |user_id|
user = User.find(user_id)
zipfile.add("#{user.last_name}_#{user.first_name}.pdf", user.cv_file.path) unless user.cv_file.nil?
end
end
send_file("#{Rails.root}/tmp/#{filename}", :type => 'application/zip', :disposition => 'attachment')
but how am I supposed to handle the response back in the promise?
$http(req).success(function(success){
console.log(success)
})
I saw the zip file in the chrome console, such as :
"...8f�~��/g6�I�-v��=� ..."
I have tried many solutions but none are working.
I thought that I would be able to send the file and download from my front.

AXLSX: Parsing xlsx file for rspec tests

Any idea how to write view specs (presence of headers, rows, etc.) for a generated xlsx file from the xlsx gem? Not sure if I'm doing it correctly in the first place but here's what I have so far
RSpec.describe "spreadsheet.xlsx.axlsx", :type => :view do
...
it "should have header Books" do
assign(:spreadsheet, spreadsheet)
render
# rendered.rows[0].cells.map(&:value).should include "Books"
end
end
In pry, rendered is in a utf-8 encoded string I'm not sure how to parse for headers, etc.
=> "PK\u0003\u0004\u0014\u0000\u0000\u0000\b\u0000\u0000\u0000!\xECc8k\xD4\
Is there a way I can just test the generated xlsx file like I would an html view?
Something like...
it "has header Books" do
assign(:worksheet, worksheet)
render
expect(rendered).to have_xpath("(//table)[1]/thead/tr/td", :text => "Books")
end
Thanks in advance!
It appears rendered is the raw response so you can use something like the axlsx_rails request specs:
File.open('/tmp/xlsx_temp.xlsx', 'w') {|f| f.write(rendered) }
wb = nil
expect{ wb = Roo::Excelx.new('/tmp/xlsx_temp.xlsx') }.to_not raise_error
wb.cell(2,1).should == 'Some value'
This uses the roo gem to parse the file since Axlsx does not read xlsx.
See:
https://github.com/straydogstudio/axlsx_rails/blob/master/spec/axlsx_request_spec.rb#L19-L22

Test download of pdf with rspec and pdfkit

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!
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!
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

Posting JSON with file content on Ruby / Rails

Does anyone know how to post a JSON to a Rails server with a file attached? Would the content be base64 encoded? Multipart? I honestly have no idea and havent really found anything here to help. Idea is to have a client posting a JSON to a rails API with the file attached, as well as having the Rails (with paperclip would be perfect) getting the JSON and saving the file properly. Thanks in advance
Here is how I solved this problem. First I created a rake task to upload the file within the json content:
desc "Tests JSON uploads with attached files on multipart formats"
task :picture => :environment do
file = File.open(Rails.root.join('lib', 'assets', 'photo.jpg'))
data = {title: "Something", description: "Else", file_content: Base64.encode64(file.read)}.to_json
req = Net::HTTP::Post.new("/users.json", {"Content-Type" => "application/json", 'Accept' => '*/*'})
req.body = data
response = Net::HTTP.new("localhost", "3000").start {|http| http.request(req) }
puts response.body
end
And then got this on the controller/model of my rails app, like this:
params[:user] = JSON.parse(request.body.read)
...
class User < ActiveRecord::Base
...
has_attached_file :picture, formats: {medium: "300x300#", thumb: "100#100"}
def file_content=(c)
filename = "#{Time.now.to_f.to_s.gsub('.', '_')}.jpg"
File.open("/tmp/#{filename}", 'wb') {|f| f.write(Base64.decode64(c).strip) }
self.picture = File.open("/tmp/#{filename}", 'r')
end
end
JSON is a data serializing format. There is no standard pattern for uploading data or files as data in the serialized object. JSON has expectations that the data fields will be basic objects so you probably want to use Base64 encoding of the file to turn it into a string.
You are free to define your structure however you want, and processing it is your responsibility.

Resources