From 09edc918c1b0e926692e694d42b3e5d874f795db Mon Sep 17 00:00:00 2001 From: Mauro Asprea Date: Tue, 4 Dec 2012 15:11:27 +0100 Subject: [PATCH] Add Capybara 2 compatibility --- .gitignore | 2 + README.md | 17 ++++--- ci/install_phantomjs | 2 +- lib/capybara/poltergeist/client.rb | 2 +- lib/capybara/poltergeist/driver.rb | 19 ++++--- lib/capybara/poltergeist/node.rb | 5 +- poltergeist.gemspec | 4 +- spec/integration/driver_spec.rb | 82 ++++++++++++++---------------- spec/integration/session_spec.rb | 16 +++--- spec/spec_helper.rb | 20 +++++--- 10 files changed, 86 insertions(+), 83 deletions(-) diff --git a/.gitignore b/.gitignore index 310a603..4f59941 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ /ci/Gemfile.*.lock /spec/tmp /rspec.failures +/vendor +/.bundle diff --git a/README.md b/README.md index 947dd81..7b9b2e1 100644 --- a/README.md +++ b/README.md @@ -24,20 +24,21 @@ detail](https://github.com/jnicklas/capybara/blob/master/README.md#transactions- ## Installing PhantomJS ## -You need at least PhantomJS 1.7.0. There are *no other external +You need at least PhantomJS 1.8.1. There are *no other external dependencies* (you don't need Qt, or a running X server, etc.) ### Mac ### * *Homebrew*: `brew install phantomjs` -* *Manual install*: [Download this](http://code.google.com/p/phantomjs/downloads/detail?name=phantomjs-1.7.0-macosx.zip&can=2&q=) +* *MacPorts*: `sudo port install phantomjs` +* *Manual install*: [Download this](http://code.google.com/p/phantomjs/downloads/detail?name=phantomjs-1.8.1-macosx.zip&can=2&q=) ### Linux ### * Download the [32 -bit](http://code.google.com/p/phantomjs/downloads/detail?name=phantomjs-1.7.0-linux-i686.tar.bz2&can=2&q=) +bit](http://code.google.com/p/phantomjs/downloads/detail?name=phantomjs-1.8.1-linux-i686.tar.bz2&can=2&q=) or [64 -bit](http://code.google.com/p/phantomjs/downloads/detail?name=phantomjs-1.7.0-linux-x86_64.tar.bz2&can=2&q=) +bit](http://code.google.com/p/phantomjs/downloads/detail?name=phantomjs-1.8.1-linux-x86_64.tar.bz2&can=2&q=) binary. * Extract the tarball and copy `bin/phantomjs` into your `PATH` @@ -46,7 +47,7 @@ binary. Do this as a last resort if the binaries don't work for you. It will take quite a long time as it has to build WebKit. -* Download [the source tarball](http://code.google.com/p/phantomjs/downloads/detail?name=phantomjs-1.7.0-source.zip&can=2&q=) +* Download [the source tarball](http://code.google.com/p/phantomjs/downloads/detail?name=phantomjs-1.8.1-source.zip&can=2&q=) * Extract and cd in * `./build.sh` @@ -175,8 +176,7 @@ end * `:debug` (Boolean) - When true, debug output is logged to `STDERR` * `:logger` (Object responding to `puts`) - When present, debug output is written to this object * `:timeout` (Numeric) - The number of seconds we'll wait for a response - when communicating with PhantomJS. `nil` means wait forever. Default - is 30. + when communicating with PhantomJS. Default is 30. * `:inspector` (Boolean, String) - See 'Remote Debugging', above. * `:js_errors` (Boolean) - When false, Javascript errors do not get re-raised in Ruby. * `:window_size` (Array) - The dimensions of the browser window in which to test, expressed @@ -324,10 +324,13 @@ Include as much information as possible. For example: ### Next release ### +#### Bug fixes #### + #### Features #### * Add `page.driver.click(x, y)` to click precise coordinates. (Micah Geisel) +* Add Capybara 2.0 support. (Mauro Asprea) [Issue #163] ### 1.0.2 ### diff --git a/ci/install_phantomjs b/ci/install_phantomjs index 48dd399..26339d7 100755 --- a/ci/install_phantomjs +++ b/ci/install_phantomjs @@ -1,6 +1,6 @@ #!/bin/bash -version=phantomjs-1.7.0-linux-i686 +version=phantomjs-1.8.1-linux-i686 wget http://phantomjs.googlecode.com/files/$version.tar.bz2 tar xjf $version.tar.bz2 mv $version phantomjs diff --git a/lib/capybara/poltergeist/client.rb b/lib/capybara/poltergeist/client.rb index 25f32c5..9da7ee3 100644 --- a/lib/capybara/poltergeist/client.rb +++ b/lib/capybara/poltergeist/client.rb @@ -1,7 +1,7 @@ module Capybara::Poltergeist class Client PHANTOMJS_SCRIPT = File.expand_path('../client/compiled/main.js', __FILE__) - PHANTOMJS_VERSION = '1.7.0' + PHANTOMJS_VERSION = '1.8.1' PHANTOMJS_NAME = 'phantomjs' def self.start(*args) diff --git a/lib/capybara/poltergeist/driver.rb b/lib/capybara/poltergeist/driver.rb index 3c639a8..4cab9b3 100644 --- a/lib/capybara/poltergeist/driver.rb +++ b/lib/capybara/poltergeist/driver.rb @@ -4,7 +4,7 @@ module Capybara::Poltergeist class Driver < Capybara::Driver::Base DEFAULT_TIMEOUT = 30 - attr_reader :app, :app_server, :server, :client, :browser, :options + attr_reader :app, :server, :client, :browser, :options def initialize(app, options = {}) @app = app @@ -13,9 +13,10 @@ module Capybara::Poltergeist @inspector = nil @server = nil @client = nil + end - @app_server = Capybara::Server.new(app) - @app_server.boot if Capybara.run_server + def needs_server? + true end def browser @@ -77,8 +78,8 @@ module Capybara::Poltergeist options.fetch(:js_errors, true) end - def visit(path) - browser.visit app_server.url(path) + def visit(url) + browser.visit(url) end def current_url @@ -89,9 +90,10 @@ module Capybara::Poltergeist browser.status_code end - def body + def html browser.body end + alias_method :body, :html def source browser.source.to_s @@ -126,9 +128,10 @@ module Capybara::Poltergeist browser.reset end - def render(path, options = {}) + def save_screenshot(path, options = {}) browser.render(path, options) end + alias_method :render, :save_screenshot def resize(width, height) browser.resize(width, height) @@ -155,7 +158,7 @@ module Capybara::Poltergeist browser.set_cookie({ :name => name, :value => value, - :domain => URI.parse(app_server.url('')).host + :domain => URI.parse(browser.current_url).host }.merge(options)) end diff --git a/lib/capybara/poltergeist/node.rb b/lib/capybara/poltergeist/node.rb index 0c31e1d..5ced0d6 100644 --- a/lib/capybara/poltergeist/node.rb +++ b/lib/capybara/poltergeist/node.rb @@ -1,5 +1,8 @@ module Capybara::Poltergeist class Node < Capybara::Driver::Node + NBSP = "\xC2\xA0" + NBSP.force_encoding("UTF-8") if NBSP.respond_to?(:force_encoding) + attr_reader :page_id, :id def initialize(driver, page_id, id) @@ -31,7 +34,7 @@ module Capybara::Poltergeist end def text - command(:text).strip.gsub(/\s+/, ' ') + command(:text).gsub(NBSP, ' ').gsub(/\s+/u, ' ').strip end def [](name) diff --git a/poltergeist.gemspec b/poltergeist.gemspec index b2481f2..095089c 100644 --- a/poltergeist.gemspec +++ b/poltergeist.gemspec @@ -14,13 +14,13 @@ Gem::Specification.new do |s| s.summary = "PhantomJS driver for Capybara" s.description = "PhantomJS driver for Capybara" - s.add_dependency "capybara", "~> 1.1" + s.add_dependency "capybara", "~> 2.0", ">= 2.0.1" s.add_dependency "multi_json", "~> 1.0" s.add_dependency "childprocess", "~> 0.3" s.add_dependency "http_parser.rb", "~> 0.5.3" s.add_dependency "faye-websocket", "~> 0.4", ">= 0.4.4" - s.add_development_dependency 'rspec', '~> 2.8' + s.add_development_dependency 'rspec', '~> 2.12' s.add_development_dependency 'sinatra', '~> 1.0' s.add_development_dependency 'rake', '~> 0.9.2' s.add_development_dependency 'image_size', '~> 1.0' diff --git a/spec/integration/driver_spec.rb b/spec/integration/driver_spec.rb index bf41225..bb8eec6 100644 --- a/spec/integration/driver_spec.rb +++ b/spec/integration/driver_spec.rb @@ -1,25 +1,17 @@ require 'spec_helper' -require 'capybara/spec/driver' require 'image_size' module Capybara::Poltergeist describe Driver do before do - @driver = TestSessions::Poltergeist.driver + @session = TestSessions::Poltergeist + @driver = @session.driver end after do @driver.reset! end - it_should_behave_like "driver" - it_should_behave_like "driver with javascript support" - it_should_behave_like "driver with frame support" - it_should_behave_like "driver with status code support" - it_should_behave_like "driver with cookies support" - it_should_behave_like "driver with header support" - it_should_behave_like "driver with support for window switching" - it 'supports a custom phantomjs path' do begin file = POLTERGEIST_ROOT + '/spec/support/custom_phantomjs_called' @@ -47,18 +39,18 @@ module Capybara::Poltergeist it 'raises an error and restart the client, if the client dies while executing a command' do lambda { @driver.browser.command('exit') }.should raise_error(DeadClient) - @driver.visit('/') - @driver.body.should include('Hello world') + @session.visit('/') + @driver.html.should include('Hello world') end it 'has a viewport size of 1024x768 by default' do - @driver.visit('/') + @session.visit('/') @driver.evaluate_script('[window.innerWidth, window.innerHeight]').should == [1024, 768] end it 'allows the viewport to be resized' do begin - @driver.visit('/') + @session.visit('/') @driver.resize(200, 400) @driver.evaluate_script('[window.innerWidth, window.innerHeight]').should == [200, 400] ensure @@ -87,22 +79,22 @@ module Capybara::Poltergeist it 'supports rendering the page' do file = POLTERGEIST_ROOT + '/spec/tmp/screenshot.png' FileUtils.rm_f file - @driver.visit('/') - @driver.render(file) + @session.visit('/') + @driver.save_screenshot(file) File.exist?(file).should == true end it 'supports rendering the whole of a page that goes outside the viewport' do file = POLTERGEIST_ROOT + '/spec/tmp/screenshot.png' - @driver.visit('/poltergeist/long_page') - @driver.render(file) + @session.visit('/poltergeist/long_page') + @driver.save_screenshot(file) File.open(file, 'rb') do |f| ImageSize.new(f.read).size.should == @driver.evaluate_script('[window.innerWidth, window.innerHeight]') end - @driver.render(file, :full => true) + @driver.save_screenshot(file, :full => true) File.open(file, 'rb') do |f| ImageSize.new(f.read).size.should == @@ -116,20 +108,20 @@ module Capybara::Poltergeist "Cookie" => "foo=bar", "Host" => "foo.com" } - @driver.visit('/poltergeist/headers') + @session.visit('/poltergeist/headers') @driver.body.should include('COOKIE: foo=bar') @driver.body.should include('HOST: foo.com') end it 'supports User-Agent' do @driver.headers = { 'User-Agent' => 'foo' } - @driver.visit '/' + @session.visit '/' @driver.evaluate_script('window.navigator.userAgent').should == 'foo' end it 'sets headers for all HTTP requests' do @driver.headers = { 'X-Omg' => 'wat' } - @driver.visit '/' + @session.visit '/' @driver.execute_script <<-JS var request = new XMLHttpRequest(); request.open('GET', '/poltergeist/headers', false); @@ -146,13 +138,13 @@ module Capybara::Poltergeist it 'supports rendering the page with a nonstring path' do file = POLTERGEIST_ROOT + '/spec/tmp/screenshot.png' FileUtils.rm_f file - @driver.visit('/') - @driver.render(Pathname(file)) + @session.visit('/') + @driver.save_screenshot(Pathname(file)) File.exist?(file).should == true end it 'supports clicking precise coordinates' do - @driver.visit('/poltergeist/click_coordinates') + @session.visit('/poltergeist/click_coordinates') @driver.click(100, 150) @driver.body.should include('x: 100, y: 150') end @@ -250,7 +242,7 @@ module Capybara::Poltergeist end it 'propagates a Javascript error during page load to a ruby exception' do - expect { @driver.visit "/poltergeist/js_error" }.to raise_error(JavascriptError) + expect { @session.visit "/poltergeist/js_error" }.to raise_error(JavascriptError) end it "doesn't propagate a Javascript error to ruby if error raising disabled" do @@ -271,7 +263,7 @@ module Capybara::Poltergeist end it "keeps track of network traffic" do - @driver.visit('/poltergeist/with_js') + @session.visit('/poltergeist/with_js') urls = @driver.network_traffic.map(&:url) urls.grep(%r{/poltergeist/jquery-1.6.2.min.js$}).size.should == 1 @@ -280,51 +272,51 @@ module Capybara::Poltergeist end it "captures responses" do - @driver.visit('/poltergeist/with_js') + @session.visit('/poltergeist/with_js') request = @driver.network_traffic.last request.response_parts.last.status.should == 200 end it "keeps a running list between multiple web page views" do - @driver.visit('/poltergeist/with_js') + @session.visit('/poltergeist/with_js') @driver.network_traffic.length.should equal(4) - @driver.visit('/poltergeist/with_js') + @session.visit('/poltergeist/with_js') @driver.network_traffic.length.should equal(8) end it "gets cleared on restart" do - @driver.visit('/poltergeist/with_js') + @session.visit('/poltergeist/with_js') @driver.network_traffic.length.should equal(4) @driver.restart - @driver.visit('/poltergeist/with_js') + @session.visit('/poltergeist/with_js') @driver.network_traffic.length.should equal(4) end end context 'status code support' do it 'should determine status from the simple response' do - @driver.visit('/poltergeist/status/500') + @session.visit('/poltergeist/status/500') @driver.status_code.should == 500 end it 'should determine status code when the page has a few resources' do - @driver.visit('/poltergeist/with_different_resources') + @session.visit('/poltergeist/with_different_resources') @driver.status_code.should == 200 end it 'should determine status code even after redirect' do - @driver.visit('/poltergeist/redirect') + @session.visit('/poltergeist/redirect') @driver.status_code.should == 200 end end context 'cookies support' do it 'returns set cookies' do - @driver.visit('/set_cookie') + @session.visit('/set_cookie') cookie = @driver.cookies['capybara'] cookie.name.should == 'capybara' @@ -336,38 +328,38 @@ module Capybara::Poltergeist end it 'can set cookies' do - @driver.set_cookie 'capybara', 'omg' - @driver.visit('/get_cookie') + @driver.set_cookie 'capybara', 'omg', :domain => '127.0.0.1' + @session.visit('/get_cookie') @driver.body.should include('omg') end it 'can set cookies with custom settings' do - @driver.set_cookie 'capybara', 'omg', :path => '/poltergeist' + @driver.set_cookie 'capybara', 'omg', :path => '/poltergeist', :domain => '127.0.0.1' - @driver.visit('/get_cookie') + @session.visit('/get_cookie') @driver.body.should_not include('omg') - @driver.visit('/poltergeist/get_cookie') + @session.visit('/poltergeist/get_cookie') @driver.body.should include('omg') @driver.cookies['capybara'].path.should == '/poltergeist' end it 'can remove a cookie' do - @driver.visit('/set_cookie') + @session.visit('/set_cookie') - @driver.visit('/get_cookie') + @session.visit('/get_cookie') @driver.body.should include('test_cookie') @driver.remove_cookie 'capybara' - @driver.visit('/get_cookie') + @session.visit('/get_cookie') @driver.body.should_not include('test_cookie') end it 'can set cookies with an expires time' do time = Time.at(Time.now.to_i + 10000) - @driver.visit '/' + @session.visit '/' @driver.set_cookie 'foo', 'bar', :expires => time @driver.cookies['foo'].expires.should == time end diff --git a/spec/integration/session_spec.rb b/spec/integration/session_spec.rb index 6738575..827ca4a 100644 --- a/spec/integration/session_spec.rb +++ b/spec/integration/session_spec.rb @@ -1,5 +1,6 @@ require 'spec_helper' -require 'capybara/spec/session' + +Capybara::SpecHelper.run_specs TestSessions::Poltergeist, "Poltergeist" describe Capybara::Session do context 'with poltergeist driver' do @@ -7,11 +8,6 @@ describe Capybara::Session do @session = TestSessions::Poltergeist end - it_should_behave_like "session" - it_should_behave_like "session with javascript support" - it_should_behave_like "session with headers support" - it_should_behave_like "session with status code support" - describe Capybara::Poltergeist::Node do it 'raises an error if the element has been removed from the DOM' do @session.visit('/poltergeist/with_js') @@ -146,7 +142,7 @@ describe Capybara::Session do it "fires the keyup event after the value is updated" do @session.find(:css, '#value_on_keyup').text.should == "Hello!" end - + it "clears the input before setting the new value" do element = @session.find(:css, '#change_me') element.set "" @@ -199,7 +195,7 @@ describe Capybara::Session do @session.visit '/poltergeist/index' @session.click_link "JS redirect" sleep 0.1 - @session.body.should include("Hello world") + @session.html.should include("Hello world") end context 'click tests' do @@ -335,7 +331,7 @@ describe Capybara::Session do CODE @session.within_window 'popup' do - @session.body.should include('slow page') + @session.html.should include('slow page') end end end @@ -352,7 +348,7 @@ describe Capybara::Session do @session.within_frame 'frame' do @session.current_path.should == "/poltergeist/slow" - @session.body.should include('slow page') + @session.html.should include('slow page') end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 15a185c..73235d2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,13 +4,12 @@ $:.unshift(POLTERGEIST_ROOT + '/lib') require 'bundler/setup' require 'rspec' +require 'capybara/spec/spec_helper' require 'capybara/poltergeist' require 'support/test_app' require 'support/spec_logger' -Capybara.default_wait_time = 0 # less timeout so tests run faster - alias :running :lambda @@ -31,12 +30,6 @@ module TestSessions end RSpec.configure do |config| - config.before do - Capybara.configure do |config| - config.default_selector = :xpath - end - end - config.before do TestSessions.logger.reset end @@ -48,4 +41,15 @@ RSpec.configure do |config| example.exception.message << "\n\nDebug info:\n" + TestSessions.logger.messages.join("\n") end end + + Capybara::SpecHelper.configure(config) + + config.before(:each) do + Capybara.default_wait_time = 0 + end + + config.before(:each, :requires => :js) do + Capybara.default_wait_time = 1 + end + end