Cucumber reading a pdf into a temp file - ruby-on-rails

I've got a cucumber suite set up to read a static PDF file and do assertions on it's content.
I recently updated all my gems, and since doing so, it doesn't work anymore.
The cucumber step is as follows:
When /^I follow PDF link "([^"]*)"$/ do |arg1|
temp_pdf = Tempfile.new('foo')
temp_pdf << page.body
temp_pdf.close
temp_txt = Tempfile.new('txt')
temp_txt.close
'pdftotext -q #{temp_pdf.path} #{temp_txt.path}'
page.drive.instance_variable_set('#body', File.read(temp_txt.path))
end
This used to work just fine. But after updating to Lion/my gems, It throws the following error when executing the line temp_pdf << page.body
encoding error: output conversion failed due to conv error, bytes 0xA3 0xC3 0x8F 0xC3
I/O error : encoder error
I tried a few different PDFs from different sources and they all seem to be failing. How can I get the PDF read into the temporary file?

The following piece of code works for me. Had to change temp_pdf << page.body, to page.source (as body is already parsed faulty). I also had to set the instance variable #dom on the drivers browser, instead of #body on the driver. This is because in the recent capybara versions (rack_test) driver no instance variable body exists, instead body calls '#browser.body':
https://github.com/jnicklas/capybara/blob/master/lib/capybara/rack_test/driver.rb
browser.body again, calls 'dom.to_xml', and if you look at 'dom' you see that it initializes #dom with Nokogiri::HTML, thus it makes a lot of sense that there've been nokogiri conversion errors in the first place.
https://github.com/jnicklas/capybara/blob/master/lib/capybara/rack_test/browser.rb
with_scope(selector) do
click_link(label)
temp_pdf = Tempfile.new('pdf')
temp_pdf << page.source
temp_pdf.close
temp_txt = Tempfile.new('txt')
temp_txt.close
temp_txt_path = "#{temp_txt.path}.html"
`pdftohtml -c -noframes #{temp_pdf.path} #{temp_txt_path}`
page.driver.browser.instance_variable_set('#dom', Nokogiri::HTML(File.read(temp_txt_path))
end

Related

Ruby on Rails: MiniMagick get_pixels gives "unable to write file"

This has been working for us for years as a quick-and-dirty way to check for duplicate images being uploaded to our Ruby on Rails site:
file.blob.open do |temp_file|
file_data = MiniMagick::Image.open(temp_file.path)
file_data.resize '1024x768'
#md5 = Digest::MD5.hexdigest(file_data.get_pixels.join)
# etc.
end
After recent Rails upgrades (I believe it started around 6.0.4; we're gradually moving to 7.0), this started throwing errors like:
/home/jeff/.rvm/gems/ruby-3.1.2/gems/mini_magick-4.11.0/lib/mini_magick/shell.rb:17:in `run': `convert /tmp/mini_magick20221120-1647726-dit0yb.png -depth 8 RGB:-` failed with error: (MiniMagick::Error) convert-im6.q16: unable to write file `-' # error/constitute.c/WriteImage/1341.
I tracked the problem down to get_pixels. Everything works fine until there, including resizing the image in the previous line. Why do we get this error when calling get_pixels? Why is it trying to write a file when getting the pixels matrix?
Thanks for your help!
Jeff

RSpec wrong with MiniMagick convert file only gitlab ci/cd (not in env development)

class **ConverterFile**
attr_accessor :old_file
SUPPORT_IMAGE_FORMAT = %w[png jpg jpeg pdf].freeze
def initialize(old_file)
#old_file = old_file
end
def to_image_type(file_format)
raise 'format not support' if file_format.blank? || SUPPORT_IMAGE_FORMAT.exclude?(file_format)
return old_file if File.extname(#old_file) == ".#{file_format}"
converted_file = MiniMagick::Image.open(#old_file.path)
converted_file.format(file_format)
File.open(converted_file.path)
rescue StandardError => e
nil
end
end
describe '#to_image_type' do
let(:png_file) { File.open(Rails.root.join('spec/support/files/logo.png')) }
context 'when convert to jpg file' do
it 'convert png file to jpg successfuly' do
new_file = described_class.new(png_file).to_image_type('jpg')
expect(File.extname(new_file)).to eq('.jpg')
end
end
end
error-in-gitlab-ci-cd
I'am confusing because i' try run spec in env dev local is pass but gitlab ci/cd error every times. I think error is about reference file missing not sure.
The error says that File.extname is being called with a nil argument:
File.extname(nil)
#=> TypeError: no implicit conversion of nil into String
This means new_file must be nil.
This means described_class.new(png_file).to_image_type('jpg') must be returning nil.
Why is this happening? Well, it's hard for me to say for sure without taking a closer look at the CI setup, but I am highly suspicious of this part of the code:
rescue StandardError => e
nil
end
Your method is silently swallowing errors, and returning nil. That doesn't seem like a good idea here in general, and it's probably hiding the true cause of the test failure!
My suspicion is that you have not committed the file 'spec/support/files/logo.png' into source control. So the test passes locally, but fails on CI where this file does not exist.
I think an exception is being raised when the non-existed file gets opened, but you're capturing the exception and returning nil -- which results in this more confusing test failure message.

invalid byte sequence in UTF-8 for single quote in Ruby

I'm using the following code to show description in template:
json.description resource.description if resource.description.present?
It gives me invalid byte sequence in UTF-8 error. I dig this a little bit, and find out the issue is my description has single quote as ’ instead of '. Wondering what's the best way to fix this encoding issue? Description is input by user and I have no control over it. Another weird issue is, I have multiple test environments, they all have the same Ruby and Rails version and they are running the same code, but only one of the environment has this error.
def to_utf8(str)
str = str.force_encoding("UTF-8")
return str if str.valid_encoding?
str = str.force_encoding("BINARY")
str.encode("UTF-8", invalid: :replace, undef: :replace)
end
ref: https://stackoverflow.com/a/17028706/455770

Read the content of a file and display with line numbers on the view

I am trying to write code to read a Ruby script entered by the user and stored it in a temp file, then pass that temp file to jruby -c temp_file to do syntax validation.
If any errors are found, I have to show the errors, along with the script entered by the user with line numbers.
How would I do this?
If there is a syntax error you see the failing line number:
blah.rb:2: syntax error, unexpected '.'
So just split your script on newline (\n) and thats your error line (1 index based of course).
If I understand correctly what you are trying to achieve, you can use jruby-parser (install gem install jruby-parser) with JRuby to find line numbers where errors occur:
require 'jruby-parser'
# Read script file into a String
script = File.open('hello.rb', 'r').read
begin
JRubyParser.parse(script)
rescue Exception => e
# Display line number
puts e.position.start_line
# Display error message
puts e.message
end

Setting more than one cookie in integration test causes NoMethodError after upgrading rails 2.3

This all worked fine in rails 2.3.5, but when a contractor firm upgraded directly to 2.3.14 suddenly all the integration tests were saying:
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
I have a before_filter on my ApplicationController that sets a bunch of cookies for some javascript to use, and I found that if I comment out all but one of the lines that sets cookie values, it works fine, and it doesn't matter which line I leave in.
before_filter :set_cookies
def set_cookies
cookies['logged_in'] = (logged_in ? 'y' : 'n')
cookies['gets_premium'] = (gets_premium ? 'y' : 'n')
cookies['is_admin'] = (is_admin ? 'y' : 'n')
end
If only one of these lines is active, everything is fine in the integration test, otherwise I get the error above. For example, consider the following test / response:
test "foo" do
get '/'
end
$ ruby -I"lib:test" test/integration/foo_test.rb -n test_foo -v
Loaded suite test/integration/foo_test
Started
test_foo(FooTest): E
Finished in 5.112648 seconds.
1) Error:
test_foo(FooTest):
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
test/integration/foo_test.rb:269:in `test_foo'
1 tests, 0 assertions, 0 failures, 1 errors
But if any two of those cookie setting lines are commented out, I get:
$ ruby -I"lib:test" test/integration/foo_test.rb -n test_foo -v
Loaded suite test/integration/foo_test
Started
test_foo(FooTest): .
Finished in 1.780388 seconds.
1 tests, 0 assertions, 0 failures, 0 errors
The website running in development and production mode works fine - this is just a matter of getting the tests passing. Also, with debugging output I have verified that the error does not get thrown in the method where the cookies get set, that all executes fine, it's somewhere later that the error happens (but the backtrace doesn't tell me where)
This turned out to be a bug in how rack rack writes cookies to the client along with the session cookie. Rack was including double newlines and omitting semi-colons.
Browsers like firefox can handle mildly malformed cookie data, but the integration test client couldn't.
To fix this I had to rewrite the cookie header before sending it to the client.
In environment.rb:
require 'rack_rails_cookie_header_hack'
And in lib/rack_rails_cookie_header_hack.rb:
class RackRailsCookieHeaderHack
def initialize(app)
#app = app
end
def call(env)
status, headers, body = #app.call(env)
if headers['Set-Cookie']
cookies = headers['Set-Cookie']
cookies = cookies.split("\n") if is_str = cookies.is_a?(String)
if cookies.respond_to?(:collect!)
cookies.collect! { |h| h.strip }
cookies.delete_if { |h| h.empty? }
cookies.collect! { |h| h.include?(';') ? h : h + ';' }
end
headers['Set-Cookie'] = is_str ? cookies.join("\n").strip : cookies
end
[status, headers, body]
end
end
Sorry the sources aren't articulated, I actually fixed this awhile ago and came across this questions and figured I'd post my patch.
L0ne's answer works for me, but you also need to include this - it can go at the bottom of lib/rack_rails_cookie_header_hack.rb, providing you're requiring it at the bottom of your environment.rb file - ie after the Rails::Initializer has run:
ActionController::Dispatcher.middleware.insert_before(ActionController::Base.session_store, RackRailsCookieHeaderHack)
Old forgotten issues...
I haven't tested Lone's fix but he has correctly identified the problem. If you catch the exception and print using exception.backtrace, you'll see that the problem is caused by
gems/actionpack/lib/action_controller/integration.rb:329
The offending code is this:
cookies.each do |cookie|
name, value = cookie.match(/^([^=]*)=([^;]*);/)[1,2]
#cookies[name] = value
end
If you're like me, and you're only interested in some super quick integration tests, and don't care too much about future maintainability (since it's rails 2), then you can just add a conditional filter in that method
cookies.each do |cookie|
unless cookie.blank?
name, value = cookie.match(/^([^=]*)=([^;]*);/)[1,2]
#cookies[name] = value
end
end
and problem solved

Resources