AXLSX: Parsing xlsx file for rspec tests - ruby-on-rails

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

Related

Why response.body not readable with xlsx format

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

Declaring XML Tags in Ruby

I am using Ruby to pull information from an excel sheet and with this information produce an xml file. I need to produce this in Ruby:
What I want:
<Betrag waehrung="EUR">150000</Betrag>
What I have:
<Betrag waehrung ="EUR"/>
I am currently trying xml.Betrag "Waehrung": "Eur"
the Betrag has a row Identifier of "#{row[13]}" which is where it can be found on the excel sheet I am using. I have tried: xml.Betrag "Waehrung": ("Eur"), ("#{row[13]}") with no success, could you please advise?
require 'nokogiri'
builder = Nokogiri::XML::Builder.new do |xml|
xml.Betrag(waehrung: 'EUR') do |e|
e << '150000'
end
end
puts builder.to_xml
=>
<?xml version="1.0"?>
<Betrag waehrung="EUR">150000</Betrag>

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

How to grep file name and extensions in webpage using nokogiri/hpricot and other gem?

I am working on an application where I have to
1) get all the links of website
2) and then get the list of all the files and file extensions in each
of the web page/link.
I am done with the first part of it :)
I get all the links of website by below code..
require 'rubygems'
require 'spidr'
require 'uri'
Spidr.site('http://testasp.vulnweb.com/') do |spider|
spider.every_url { |url|
puts url
}
end
now I have to get the all the files/file-extensions in each of the
page so I tried the below code
require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'spidr'
site = 'http://testasp.vulnweb.com'
in1=[]
Spidr.site(site) do |spider|
spider.every_url { |url| in1.push url }
end
in1.each do |input1|
input1 = input1.to_s
#puts input1
begin
doc = Nokogiri::HTML(open(input1))
doc.traverse do |el|
[el[:src], el[:href]].grep(/\.(txt|css|gif|jpg|png|pdf)$/i).map{|l| URI.join(input1, l).to_s}.each do |link|
puts link
end
end
rescue => e
puts "errrooooooooor"
end
end
but Can anybody guide me how to parse the links/webpage and get the file-
extensions in the page?
You might want to take a look at URI#parse. The URI module is a part of the Ruby standard library and is a dependency of the spidr gem. Example implementation with a spec for good measure.
require 'rspec'
require 'uri'
class ExtensionExtractor
def extract(uri)
/\A.*\/(?<file>.*\.(?<extension>txt|css|gif|jpg|png|pdf))\z/i =~ URI.parse(uri).path
{:path => uri, :file => file, :extension => extension}
end
end
describe ExtensionExtractor do
before(:all) do
#css_uri = "http://testasp.vulnweb.com/styles.css"
#gif_uri = "http://testasp.vulnweb.com/Images/logo.gif"
#gif_uri_with_param = "http://testasp.vulnweb.com/Images/logo.gif?size=350x350"
end
describe "Common Extensions" do
it "should extract CSS files from URIs" do
file = subject.extract(#css_uri)
file[:path].should eq #css_uri
file[:file].should eq "styles.css"
file[:extension].should eq "css"
end
it "should extract GIF files from URIs" do
file = subject.extract(#gif_uri)
file[:path].should eq #gif_uri
file[:file].should eq "logo.gif"
file[:extension].should eq "gif"
end
it "should properly extract extensions even when URIs have parameters" do
file = subject.extract(#gif_uri_with_param)
file[:path].should eq #gif_uri_with_param
file[:file].should eq "logo.gif"
file[:extension].should eq "gif"
end
end
end

Setting page/respone.body in Capybara used to work in Webrat

I am migrating to Capybara.
One of the problems I have is migrating the pdf step.
This step sets page.body to a parsed pdf.
That way I can use the default cucumber steps.
When 'I follow the PDF link "$label"' do |label|
click_link(label)
page.body = PDF::Inspector::Text.analyze(page.body).strings.join(" ")
end
Ex.
When I follow the PDF link "Catalogue"
Then I should see "Cheap products"
The error I get is this one:
undefined method `body=' for #<Capybara::`enter code here`Document> (NoMethodError)
On top, make sure you set :js => true like this:
scenario 'do something', :js => true do
str = PDF::Inspector::Text.analyze(page.body).strings.join(" ") # or whatever string you want
# then just use javascript to edit or add the body
page.evaluate_script("document.write(#{str});")
end
Now this is dependent on the driver, but it's one solution...
There is no setter for body defined in the source in capybara, so you cannot set it externally like that. Try this (untested):
page.instance_variable_set(:#body, PDF::Inspector::Text.analyze(page.body).strings.join(" "))
This worked for me:
Then /^I should be served the document as a PDF$/ do
page.response_headers['Content-Type'].should == "application/pdf"
pdf = PDF::Inspector::Text.analyze(page.source).strings.join(" ")
page.driver.response.instance_variable_set('#body', pdf)
end
Then /^I should see the document details$/ do
page.should have_content("#{#document.customer.name}")
page.should have_content("#{#document.resources.first.resource.name}")
page.should have_content("Document opened at #{#document.created_at.strftime("%e-%b-%4Y %r")}")
end
Note that I'm serving my PDF inline
pdf = DocumentPdf.new(#document)
send_data pdf.render, :filename => "document_#{#document.created_at.strftime("%Y-%m-%d")}",
:type => "application/pdf",
:disposition => "inline"

Resources