follow me icons

Sunday, November 21, 2010

Error When installing Nokogiri gem - 'no such file to load -- mkmf (LoadError)'

So basically when I try to install nokogiri gem using 'gem install nokogiri', I get the following error:


root@ubuntu:/home# gem install nokogiri
Building native extensions. This could take a while...
ERROR: Error installing nokogiri:
ERROR: Failed to build gem native extension.

/usr/bin/ruby1.8 extconf.rb
extconf.rb:5:in
`require': no such file to load -- mkmf (LoadError)
from extconf.rb:5


Gem files will remain installed in
/usr/lib/ruby/gems/1.8/
gems/nokogiri for inspection.
Results logged to
/usr/lib/ruby/gems/1.8/
gems/nokogiri/ext/nokogiri/gem_make.out



I was able to successfully install nokogiri on Windows and Mac so I was confused as to why it is failing in Ubuntu. I found out that you need to install the ruby1.8-dev to make it work.


sudo apt-get install ruby1.8-dev


If that still does not work try to install the following as well:

sudo apt-get install libxml2 libxml2-dev libxslt1-dev
sudo gem install nokogiri


Then just run the gem install nokogiri:


root@ubuntu:/home# gem install nokogiri -v 1.4.3.1
Building native extensions. This could take a while...
Successfully installed nokogiri-1.4.3.1
1 gem installed
Installing ri documentation for nokogiri-1.4.3.1...
r
No definition for parse_memory

No definition for parse_file

No definition for parse_with

No definition for get_options

No definition for set_options
Installing RDoc documentation for nokogiri-1.4.3.1...

No definition for parse_memory

No definition for parse_file

No definition for parse_with

No definition for get_options


This above solution will also work if you get the following error message:

Could not open library 'xml2' : xml2:
cannot open shared object file: No such file or directory.
Could not open library 'libxml2.so' :
libxml2.so: cannot open shared object file: No such file or directory (LoadError)

as mentioned on this blog

Sunday, November 7, 2010

Upgrading to Capybara 0.4.0

So Capybara 0.4.0 is out now and if you do a 'gem install capybara', you will get Capybara 0.4.0 by default. This has byfar the most changes and not backward compatible with the previous version.

After upgrading to 0.4.0, my test started to fail with a very weird error message ("superclass mismatch for class Node (TypeError)"). It took me one whole day to familiarize myself with the new version which include looking at Capybara code to be able to modify my current test.

Here are what I have to do to upgrade to Capybara 0.4.0 from 0.3.9 in my project

1. Changed "class Node < Capybara::Node" to "class Capybara::Element < Capybara::Node"
See How to send keystrokes to an element in the browser
2. Changed the use of variable "node" to "native"
3. #locate is now deprecated, changed all of my use of "locate" into "find"
4. Changed the way we setup the capybara config

Before

Capybara.default_driver = :selenium
Capybara.run_server = false
Capybara.default_selector = :css
Capybara.default_wait_time = 30


After

Capybara.configure do |config|
config.default_driver = :selenium
config.default_driver = :selenium
config.run_server = false
config.default_selector = :css
config.default_wait_time = 30
end


5. Changed the way we register the browser driver

Before

class Capybara::Driver::Selenium
def self.driver
unless @driver

profile = Selenium::WebDriver::Firefox::Profile.new
profile["network.proxy.type"] = 1
profile["network.proxy.http"] = "proxy setting"
profile["network.proxy.http_port"] = 8080
@driver = Selenium::WebDriver.for(:firefox, :profile => profile)

at_exit do
@driver.quit
end
end
@driver
end
end


After

Capybara.register_driver :selenium do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile["network.proxy.type"] = 1
profile["network.proxy.http"] = "proxy setting"
profile["network.proxy.http_port"] = 8080
Capybara::Driver::Selenium.new(app, :browser => :firefox, :profile => profile)
end

Wednesday, November 3, 2010

How to send keystrokes to an element in the browser

From time to time you might need to test sending a keystroke to the browser. For example, for a map based application such as google map, you might want to test the arrow keys on the keyboard to test that pressing the arrow key will move the maps.

Fortunately, webdriver already implements the send-keys class and if you use capybara you can use this extensions by Mark Gandolfo. Please note that as of this writing, the current send-keys version in github does not support capybara 0.4.0 It only supports version < 0.4.0.

However, I have modified the code to work with capybara version 0.4.0 below:

Cucumber Scenario

And I send arrow_left to google map
And I send arrow_up to google map
And I send arrow_right to google map
And I send arrow_down to google map


Steps Definitions - send_keys_steps.rb
put this into your step_definitions directory

And /^I send (.*) to google map$/ do |key|
find(:css,"#page").send(key)
end


Class definition - send_keys.rb
put this into your support/patches/send_keys.rb. If you use capybara version < 0.4.0, then change the "Class Capybara::Element < Capybara::Node" into "Node < Capybara::Node" and change the "native.send_keys(send_key)" to "node.send_keys(send_key)".

If you don't, then you will get this error:
"superclass mismatch for class Node (TypeError)"


class Capybara::Driver::Selenium < Capybara::Driver::Base
class Capybara::Element < Capybara::Node
def allowed_keys
@allowed_keys ||= %q(option, null cancel help backspace
tab clear return enter shift left_shift control left_control
alt left_alt pause escape space page_up page_down end home
left arrow_left uparrow_up right arrow_rightdown arrow_down
insert delete semicolon equals numpad0 numpad1 numpad2 numpad3
numpad4 numpad5 numpad6 numpad7 numpad8 numpad9 multiplyadd
separator subtract decimal divide f1 f2 f3 f4 f5 f6 f7 f8
f9 f10 f11 f12)
end

def send(key)
send_key = []

if key.match(/\[.*\]/i)
key.gsub!(/[\[\]]/,'')
key = key.split(',')
else
key = [key]
end

key.each do |k|
if k.match(/(\'|\")/i)
send_key << k.gsub(/(\"|\')/, '')
elsif allowed_keys.include?(k)
send_key << k.to_sym
else
send_key << "#{k}"
end
end

native.send_keys(send_key)
end
end
end


Modify support/env.rb to include send_keys

require 'features/support/patches/send_keys'