From 8ad161b0413ffe905b0c1cb99ed6d18d390f09b3 Mon Sep 17 00:00:00 2001
From: jgagner
Date: Tue, 12 Jan 2010 11:40:10 -0800
Subject: [PATCH 01/84] #within_frame method
---
lib/capybara/driver/base.rb | 4 ++++
lib/capybara/driver/selenium_driver.rb | 7 ++++++-
spec/driver/selenium_driver_spec.rb | 2 +-
spec/drivers_spec.rb | 3 +++
4 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/lib/capybara/driver/base.rb b/lib/capybara/driver/base.rb
index 2f94d106..dbdc064e 100644
--- a/lib/capybara/driver/base.rb
+++ b/lib/capybara/driver/base.rb
@@ -27,6 +27,10 @@ class Capybara::Driver::Base
raise NotImplementedError
end
+ def within_frame frame_id
+ raise Capybara::NotSupportedByDriverError
+ end
+
def source
raise NotImplementedError
end
diff --git a/lib/capybara/driver/selenium_driver.rb b/lib/capybara/driver/selenium_driver.rb
index 2f1deabb..076fcc15 100644
--- a/lib/capybara/driver/selenium_driver.rb
+++ b/lib/capybara/driver/selenium_driver.rb
@@ -103,7 +103,12 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
def browser
self.class.driver
end
-
+ def with_frame(frame_id)
+ old_window = browser.window_handle
+ browser.switch_to.frame(frame_id)
+ yield
+ browser.switch_to.window old_window
+ end
private
def url(path)
diff --git a/spec/driver/selenium_driver_spec.rb b/spec/driver/selenium_driver_spec.rb
index a71047e0..0fdfa652 100644
--- a/spec/driver/selenium_driver_spec.rb
+++ b/spec/driver/selenium_driver_spec.rb
@@ -8,5 +8,5 @@ describe Capybara::Driver::Selenium do
it_should_behave_like "driver"
it_should_behave_like "driver with javascript support"
it_should_behave_like "driver without node path support"
-
+ it_should_behave_like "driver with frame support"
end
diff --git a/spec/drivers_spec.rb b/spec/drivers_spec.rb
index 8643b4e6..523be045 100644
--- a/spec/drivers_spec.rb
+++ b/spec/drivers_spec.rb
@@ -1,5 +1,8 @@
require File.expand_path('spec_helper', File.dirname(__FILE__))
+shared_examples_for 'driver with frame support' do
+ it_should_behave_like 'within_frame'
+end
shared_examples_for 'driver' do
describe '#visit' do
From 28605a5d9c38481678a8bd8a41d7f9174026dfc9 Mon Sep 17 00:00:00 2001
From: jgagner
Date: Tue, 12 Jan 2010 11:56:17 -0800
Subject: [PATCH 02/84] added specs for with_frame
---
spec/drivers_spec.rb | 2 +-
spec/dsl/with_frame_spec.rb | 32 ++++++++++++++++++++++++++++++++
spec/views/frame_one.erb | 8 ++++++++
spec/views/frame_two.erb | 8 ++++++++
spec/views/with_frames.erb | 10 ++++++++++
5 files changed, 59 insertions(+), 1 deletion(-)
create mode 100644 spec/dsl/with_frame_spec.rb
create mode 100644 spec/views/frame_one.erb
create mode 100644 spec/views/frame_two.erb
create mode 100644 spec/views/with_frames.erb
diff --git a/spec/drivers_spec.rb b/spec/drivers_spec.rb
index 523be045..8d833609 100644
--- a/spec/drivers_spec.rb
+++ b/spec/drivers_spec.rb
@@ -1,7 +1,7 @@
require File.expand_path('spec_helper', File.dirname(__FILE__))
shared_examples_for 'driver with frame support' do
- it_should_behave_like 'within_frame'
+ it_should_behave_like 'with_frame'
end
shared_examples_for 'driver' do
diff --git a/spec/dsl/with_frame_spec.rb b/spec/dsl/with_frame_spec.rb
new file mode 100644
index 00000000..6bf6ae53
--- /dev/null
+++ b/spec/dsl/with_frame_spec.rb
@@ -0,0 +1,32 @@
+module WithFrameSpec
+ shared_examples_for "with_frame" do
+ describe '#with_frame' do
+ before(:each) do
+ @driver.visit('/with_frames')
+ end
+
+ it "should find the div in frameOne" do
+ @driver.with_frame("frameOne") do
+ @driver.find("//*[@id='divInFrameOne']")[0].text.should eql 'This is the text of divInFrameOne'
+ end
+ end
+ it "should find the div in FrameTwo" do
+ @driver.with_frame("frameTwo") do
+ @driver.find("//*[@id='divInFrameTwo']")[0].text.should eql 'This is the text of divInFrameTwo'
+ end
+ end
+ it "should find the text div in the main window after finding text in frameOne" do
+ @driver.with_frame("frameOne") do
+ @driver.find("//*[@id='divInFrameOne']")[0].text.should eql 'This is the text of divInFrameOne'
+ end
+ @driver.find("//*[@id='divInMainWindow']")[0].text.should eql 'This is the text for divInMainWindow'
+ end
+ it "should find the text div in the main window after finding text in frameTwo" do
+ @driver.with_frame("frameTwo") do
+ @driver.find("//*[@id='divInFrameTwo']")[0].text.should eql 'This is the text of divInFrameTwo'
+ end
+ @driver.find("//*[@id='divInMainWindow']")[0].text.should eql 'This is the text for divInMainWindow'
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/spec/views/frame_one.erb b/spec/views/frame_one.erb
new file mode 100644
index 00000000..6b8f8a7b
--- /dev/null
+++ b/spec/views/frame_one.erb
@@ -0,0 +1,8 @@
+
+
+ This is the title of frame one
+
+
+
This is the text of divInFrameOne
+
+
\ No newline at end of file
diff --git a/spec/views/frame_two.erb b/spec/views/frame_two.erb
new file mode 100644
index 00000000..b344964d
--- /dev/null
+++ b/spec/views/frame_two.erb
@@ -0,0 +1,8 @@
+
+
+ This is the title of frame two
+
+
+
This is the text of divInFrameTwo
+
+
\ No newline at end of file
diff --git a/spec/views/with_frames.erb b/spec/views/with_frames.erb
new file mode 100644
index 00000000..871e5dc5
--- /dev/null
+++ b/spec/views/with_frames.erb
@@ -0,0 +1,10 @@
+
+
+ With Frames
+
+
+
This is the text for divInMainWindow
+
+
+
+
\ No newline at end of file
From 1e096ddcc02d09351ee61475e40ed6e8f5e4bca5 Mon Sep 17 00:00:00 2001
From: jgagner
Date: Tue, 12 Jan 2010 12:27:39 -0800
Subject: [PATCH 03/84] Fixed naming
---
lib/capybara/driver/selenium_driver.rb | 2 +-
lib/capybara/session.rb | 6 +++++-
spec/drivers_spec.rb | 2 +-
spec/dsl/{with_frame_spec.rb => within_frame_spec.rb} | 0
spec/views/{with_frames.erb => within_frames.erb} | 0
5 files changed, 7 insertions(+), 3 deletions(-)
rename spec/dsl/{with_frame_spec.rb => within_frame_spec.rb} (100%)
rename spec/views/{with_frames.erb => within_frames.erb} (100%)
diff --git a/lib/capybara/driver/selenium_driver.rb b/lib/capybara/driver/selenium_driver.rb
index 076fcc15..d450c629 100644
--- a/lib/capybara/driver/selenium_driver.rb
+++ b/lib/capybara/driver/selenium_driver.rb
@@ -103,7 +103,7 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
def browser
self.class.driver
end
- def with_frame(frame_id)
+ def within_frame(frame_id)
old_window = browser.window_handle
browser.switch_to.frame(frame_id)
yield
diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb
index a82d4347..ba0e6a67 100644
--- a/lib/capybara/session.rb
+++ b/lib/capybara/session.rb
@@ -8,7 +8,7 @@ module Capybara
:all, :attach_file, :body, :check, :choose, :click, :click_button, :click_link, :current_url, :drag, :evaluate_script,
:field_labeled, :fill_in, :find, :find_button, :find_by_id, :find_field, :find_link, :has_content?, :has_css?,
:has_no_content?, :has_no_css?, :has_no_xpath?, :has_xpath?, :locate, :save_and_open_page, :select, :source, :uncheck,
- :visit, :wait_until, :within, :within_fieldset, :within_table
+ :visit, :wait_until, :within, :within_fieldset, :within_table,:within_frame
]
attr_reader :mode, :app
@@ -33,6 +33,10 @@ module Capybara
end
end
+ def within_frame frame_id
+ driver.within_frame frame_id
+ end
+
def current_url
driver.current_url
end
diff --git a/spec/drivers_spec.rb b/spec/drivers_spec.rb
index 8d833609..523be045 100644
--- a/spec/drivers_spec.rb
+++ b/spec/drivers_spec.rb
@@ -1,7 +1,7 @@
require File.expand_path('spec_helper', File.dirname(__FILE__))
shared_examples_for 'driver with frame support' do
- it_should_behave_like 'with_frame'
+ it_should_behave_like 'within_frame'
end
shared_examples_for 'driver' do
diff --git a/spec/dsl/with_frame_spec.rb b/spec/dsl/within_frame_spec.rb
similarity index 100%
rename from spec/dsl/with_frame_spec.rb
rename to spec/dsl/within_frame_spec.rb
diff --git a/spec/views/with_frames.erb b/spec/views/within_frames.erb
similarity index 100%
rename from spec/views/with_frames.erb
rename to spec/views/within_frames.erb
From 35c70890376e8d8bbb76785c5f7fdc3394ad6e28 Mon Sep 17 00:00:00 2001
From: jgagner
Date: Tue, 12 Jan 2010 12:33:06 -0800
Subject: [PATCH 04/84] Fixed bug with within_frame session method and changed
naming in spec
---
lib/capybara/session.rb | 4 +++-
spec/dsl/within_frame_spec.rb | 16 ++++++++--------
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb
index ba0e6a67..a66b86f8 100644
--- a/lib/capybara/session.rb
+++ b/lib/capybara/session.rb
@@ -34,7 +34,9 @@ module Capybara
end
def within_frame frame_id
- driver.within_frame frame_id
+ driver.within_frame(frame_id) do
+ yield
+ end
end
def current_url
diff --git a/spec/dsl/within_frame_spec.rb b/spec/dsl/within_frame_spec.rb
index 6bf6ae53..be46f7d5 100644
--- a/spec/dsl/within_frame_spec.rb
+++ b/spec/dsl/within_frame_spec.rb
@@ -1,28 +1,28 @@
-module WithFrameSpec
- shared_examples_for "with_frame" do
- describe '#with_frame' do
+module WithinFrameSpec
+ shared_examples_for "within_frame" do
+ describe '#within_frame' do
before(:each) do
- @driver.visit('/with_frames')
+ @driver.visit('/within_frames')
end
it "should find the div in frameOne" do
- @driver.with_frame("frameOne") do
+ @driver.within_frame("frameOne") do
@driver.find("//*[@id='divInFrameOne']")[0].text.should eql 'This is the text of divInFrameOne'
end
end
it "should find the div in FrameTwo" do
- @driver.with_frame("frameTwo") do
+ @driver.within_frame("frameTwo") do
@driver.find("//*[@id='divInFrameTwo']")[0].text.should eql 'This is the text of divInFrameTwo'
end
end
it "should find the text div in the main window after finding text in frameOne" do
- @driver.with_frame("frameOne") do
+ @driver.within_frame("frameOne") do
@driver.find("//*[@id='divInFrameOne']")[0].text.should eql 'This is the text of divInFrameOne'
end
@driver.find("//*[@id='divInMainWindow']")[0].text.should eql 'This is the text for divInMainWindow'
end
it "should find the text div in the main window after finding text in frameTwo" do
- @driver.with_frame("frameTwo") do
+ @driver.within_frame("frameTwo") do
@driver.find("//*[@id='divInFrameTwo']")[0].text.should eql 'This is the text of divInFrameTwo'
end
@driver.find("//*[@id='divInMainWindow']")[0].text.should eql 'This is the text for divInMainWindow'
From 2b813f09b921e4ec2ec06c9d602f3eb972650361 Mon Sep 17 00:00:00 2001
From: jgagner
Date: Thu, 14 Jan 2010 17:37:19 -0800
Subject: [PATCH 05/84] made it so has_xpath?/has_no_xpath? checks to make sure
the element is visible by default. Can be overriden with options.
---
lib/capybara/session.rb | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb
index a66b86f8..2a6e5d17 100644
--- a/lib/capybara/session.rb
+++ b/lib/capybara/session.rb
@@ -134,7 +134,7 @@ module Capybara
def has_xpath?(path, options={})
wait_conditionally_until do
results = all(path, options)
-
+ options = {:visible => true}.merge options
if options[:count]
results.size == options[:count]
else
@@ -147,6 +147,7 @@ module Capybara
def has_no_xpath?(path, options={})
wait_conditionally_until do
+ options = {:visible => true}.merge options
results = all(path, options)
if options[:count]
From b207370441144e76c587517a5f7138e59026f710 Mon Sep 17 00:00:00 2001
From: jgagner
Date: Thu, 14 Jan 2010 17:37:48 -0800
Subject: [PATCH 06/84] rescues the inevitable
"Selenium::WebDriver::Error::WebDriverError: element is obsolete" if you
check to see if an element that has been removed from the DOM is visible
---
lib/capybara/driver/selenium_driver.rb | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lib/capybara/driver/selenium_driver.rb b/lib/capybara/driver/selenium_driver.rb
index d450c629..5e0226ed 100644
--- a/lib/capybara/driver/selenium_driver.rb
+++ b/lib/capybara/driver/selenium_driver.rb
@@ -44,7 +44,12 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
end
def visible?
- node.displayed? and node.displayed? != "false"
+ begin
+ node.displayed? and node.displayed? != "false"
+ rescue Selenium::WebDriver::Error::WebDriverError
+ # rescues the inevitable "Selenium::WebDriver::Error::WebDriverError: element is obsolete" if you check to see if an element that has been removed from the DOM is visible
+ return false
+ end
end
private
From a19c902a65c1389922e73afc3453d1ca4d7c0b6d Mon Sep 17 00:00:00 2001
From: jgagner
Date: Thu, 14 Jan 2010 17:37:19 -0800
Subject: [PATCH 07/84] made it so has_xpath?/has_no_xpath? checks to make sure
the element is visible by default. Can be overriden with options.
rescues the inevitable "Selenium::WebDriver::Error::WebDriverError: element is obsolete" if you check to see if an element that has been removed from the DOM is visible
---
lib/capybara/driver/selenium_driver.rb | 7 ++++++-
lib/capybara/session.rb | 3 ++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/lib/capybara/driver/selenium_driver.rb b/lib/capybara/driver/selenium_driver.rb
index d450c629..5e0226ed 100644
--- a/lib/capybara/driver/selenium_driver.rb
+++ b/lib/capybara/driver/selenium_driver.rb
@@ -44,7 +44,12 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
end
def visible?
- node.displayed? and node.displayed? != "false"
+ begin
+ node.displayed? and node.displayed? != "false"
+ rescue Selenium::WebDriver::Error::WebDriverError
+ # rescues the inevitable "Selenium::WebDriver::Error::WebDriverError: element is obsolete" if you check to see if an element that has been removed from the DOM is visible
+ return false
+ end
end
private
diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb
index a66b86f8..90d11b6e 100644
--- a/lib/capybara/session.rb
+++ b/lib/capybara/session.rb
@@ -133,8 +133,8 @@ module Capybara
def has_xpath?(path, options={})
wait_conditionally_until do
+ options = {:visible => true}.merge options
results = all(path, options)
-
if options[:count]
results.size == options[:count]
else
@@ -147,6 +147,7 @@ module Capybara
def has_no_xpath?(path, options={})
wait_conditionally_until do
+ options = {:visible => true}.merge options
results = all(path, options)
if options[:count]
From 4b7609ac1522c8e7c1e9462e74fd53f2bcc7460b Mon Sep 17 00:00:00 2001
From: jgagner
Date: Fri, 15 Jan 2010 08:15:38 -0800
Subject: [PATCH 08/84] Ignoring .idea directory
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 7f61f0d3..92836684 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.idea/
.DS_Store
pkg
*~
From 96314c05c57bee0320d6d19d8d78e0bac13fce6a Mon Sep 17 00:00:00 2001
From: Rob Holland
Date: Tue, 23 Feb 2010 17:43:40 +0000
Subject: [PATCH 09/84] Add support for using HTTP verbs directly to the rack
driver.
---
lib/capybara/driver/base.rb | 16 ++++++++
lib/capybara/driver/rack_test_driver.rb | 29 ++++++++++----
lib/capybara/session.rb | 36 +++++++----------
spec/driver/celerity_driver_spec.rb | 1 +
spec/driver/culerity_driver_spec.rb | 3 +-
spec/driver/rack_test_driver_spec.rb | 1 +
spec/driver/selenium_driver_spec.rb | 1 +
spec/drivers_spec.rb | 52 +++++++++++++++++++++++++
8 files changed, 108 insertions(+), 31 deletions(-)
diff --git a/lib/capybara/driver/base.rb b/lib/capybara/driver/base.rb
index 6cf8c00f..3be28d4d 100644
--- a/lib/capybara/driver/base.rb
+++ b/lib/capybara/driver/base.rb
@@ -34,4 +34,20 @@ class Capybara::Driver::Base
def cleanup!
end
+ def get(*args)
+ raise Capybara::NotSupportedByDriverError
+ end
+
+ def post(*args)
+ raise Capybara::NotSupportedByDriverError
+ end
+
+ def delete(*args)
+ raise Capybara::NotSupportedByDriverError
+ end
+
+ def put(*args)
+ raise Capybara::NotSupportedByDriverError
+ end
+
end
diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb
index 3dc9acc0..008d771b 100644
--- a/lib/capybara/driver/rack_test_driver.rb
+++ b/lib/capybara/driver/rack_test_driver.rb
@@ -174,7 +174,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
end
include ::Rack::Test::Methods
- attr_reader :app, :html, :body
+ attr_reader :app
alias_method :response, :last_response
alias_method :request, :last_request
@@ -188,7 +188,6 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
return if path.gsub(/^#{current_path}/, '') =~ /^#/
get(path, attributes, env)
follow_redirects!
- cache_body
end
def current_url
@@ -203,13 +202,29 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
path = current_path if not path or path.empty?
send(method, path, attributes, env)
follow_redirects!
- cache_body
end
def find(selector)
html.xpath(selector).map { |node| Node.new(self, node) }
end
-
+
+ ['get', 'post', 'put', 'delete'].each do |method|
+ class_eval <<-RUBY, __FILE__, __LINE__+1
+ def #{method}(*args, &block)
+ reset_cache
+ super
+ end
+ RUBY
+ end
+
+ def body
+ @body ||= response.body
+ end
+
+ def html
+ @html ||= Nokogiri::HTML(body)
+ end
+
private
def current_path
@@ -236,9 +251,9 @@ private
env
end
- def cache_body
- @body = response.body
- @html = Nokogiri::HTML(body)
+ def reset_cache
+ @body = nil
+ @html = nil
end
end
diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb
index f98afd39..f95f7a34 100644
--- a/lib/capybara/session.rb
+++ b/lib/capybara/session.rb
@@ -1,10 +1,13 @@
+require 'forwardable'
require 'capybara/wait_until'
module Capybara
class Session
+ extend Forwardable
include Searchable
DSL_METHODS = [
+ :get, :put, :post, :delete,
:all, :attach_file, :body, :check, :choose, :click, :click_button, :click_link, :current_url, :drag, :evaluate_script,
:field_labeled, :fill_in, :find, :find_button, :find_by_id, :find_field, :find_link, :has_content?, :has_css?,
:has_no_content?, :has_no_css?, :has_no_xpath?, :has_xpath?, :locate, :save_and_open_page, :select, :source, :uncheck,
@@ -34,21 +37,16 @@ module Capybara
end
end
- def cleanup!
- driver.cleanup!
- end
-
- def current_url
- driver.current_url
- end
-
- def response_headers
- driver.response_headers
- end
-
- def visit(path)
- driver.visit(path)
- end
+ def_delegator :driver, :cleanup!
+ def_delegator :driver, :current_url
+ def_delegator :driver, :response_headers
+ def_delegator :driver, :visit
+ def_delegator :driver, :body
+ def_delegator :driver, :source
+ def_delegator :driver, :get
+ def_delegator :driver, :post
+ def_delegator :driver, :put
+ def_delegator :driver, :delete
def click(locator)
msg = "no link or button '#{locator}' found"
@@ -106,14 +104,6 @@ module Capybara
locate(:xpath, XPath.file_field(locator), msg).set(path)
end
- def body
- driver.body
- end
-
- def source
- driver.source
- end
-
def within(kind, scope=nil)
kind, scope = Capybara.default_selector, kind unless scope
scope = XPath.from_css(scope) if kind == :css
diff --git a/spec/driver/celerity_driver_spec.rb b/spec/driver/celerity_driver_spec.rb
index bd31440a..fa3ebfd3 100644
--- a/spec/driver/celerity_driver_spec.rb
+++ b/spec/driver/celerity_driver_spec.rb
@@ -10,6 +10,7 @@ if RUBY_PLATFORM =~ /java/
it_should_behave_like "driver with javascript support"
it_should_behave_like "driver with header support"
it_should_behave_like "driver with node path support"
+ it_should_behave_like "driver without direct HTTP support"
end
else
diff --git a/spec/driver/culerity_driver_spec.rb b/spec/driver/culerity_driver_spec.rb
index ec6a4e3d..4753d48f 100644
--- a/spec/driver/culerity_driver_spec.rb
+++ b/spec/driver/culerity_driver_spec.rb
@@ -8,6 +8,7 @@ describe Capybara::Driver::Culerity do
it_should_behave_like "driver"
it_should_behave_like "driver with javascript support"
it_should_behave_like "driver with header support"
- it_should_behave_like "driver with node path support"
+ it_should_behave_like "driver with node path support"
+ it_should_behave_like "driver without direct HTTP support"
end
diff --git a/spec/driver/rack_test_driver_spec.rb b/spec/driver/rack_test_driver_spec.rb
index 7b2c8d67..9ce4b692 100644
--- a/spec/driver/rack_test_driver_spec.rb
+++ b/spec/driver/rack_test_driver_spec.rb
@@ -8,5 +8,6 @@ describe Capybara::Driver::RackTest do
it_should_behave_like "driver"
it_should_behave_like "driver with header support"
it_should_behave_like "driver with node path support"
+ it_should_behave_like "driver with direct HTTP support"
end
diff --git a/spec/driver/selenium_driver_spec.rb b/spec/driver/selenium_driver_spec.rb
index a71047e0..5bc8407b 100644
--- a/spec/driver/selenium_driver_spec.rb
+++ b/spec/driver/selenium_driver_spec.rb
@@ -8,5 +8,6 @@ describe Capybara::Driver::Selenium do
it_should_behave_like "driver"
it_should_behave_like "driver with javascript support"
it_should_behave_like "driver without node path support"
+ it_should_behave_like "driver without direct HTTP support"
end
diff --git a/spec/drivers_spec.rb b/spec/drivers_spec.rb
index b5fbb892..ee20a095 100644
--- a/spec/drivers_spec.rb
+++ b/spec/drivers_spec.rb
@@ -137,3 +137,55 @@ shared_examples_for "driver without node path support" do
end
end
+
+shared_examples_for "driver with direct HTTP support" do
+ describe "direct HTTP calls" do
+ it "should create a response for a GET" do
+ @driver.get('/tables')
+ @driver.body.should_not be_nil
+ end
+
+ it "should create a response for a PUT" do
+ @driver.put('/tables')
+ @driver.body.should_not be_nil
+ end
+
+ it "should create a response for a POST" do
+ @driver.post('/table')
+ @driver.body.should_not be_nil
+ end
+
+ it "should create a response for a DELETE" do
+ @driver.delete('/table')
+ @driver.body.should_not be_nil
+ end
+ end
+end
+
+shared_examples_for "driver without direct HTTP support" do
+ describe "direct HTTP calls" do
+ it "should get NotSupportedByDriverError for a GET" do
+ running do
+ @driver.get('/tables')
+ end.should raise_error(Capybara::NotSupportedByDriverError)
+ end
+
+ it "should get NotSupportedByDriverError for a PUT" do
+ running do
+ @driver.put('/tables')
+ end.should raise_error(Capybara::NotSupportedByDriverError)
+ end
+
+ it "should get NotSupportedByDriverError for a POST" do
+ running do
+ @driver.post('/tables')
+ end.should raise_error(Capybara::NotSupportedByDriverError)
+ end
+
+ it "should get NotSupportedByDriverError for a DELETE" do
+ running do
+ @driver.delete('/tables')
+ end.should raise_error(Capybara::NotSupportedByDriverError)
+ end
+ end
+end
From e6ed2cd8b04916ee89e88fef2fdf6502da93ef15 Mon Sep 17 00:00:00 2001
From: Robot Made
Date: Sun, 21 Feb 2010 16:59:17 -0800
Subject: [PATCH 10/84] rails3
---
lib/capybara/rails.rb | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/lib/capybara/rails.rb b/lib/capybara/rails.rb
index 2911d60d..b6a62ec1 100644
--- a/lib/capybara/rails.rb
+++ b/lib/capybara/rails.rb
@@ -3,9 +3,10 @@ require 'capybara/dsl'
Capybara.app = Rack::Builder.new do
map "/" do
- use Rails::Rack::Static
- run ActionController::Dispatcher.new
+ ActionDispatch::Static
+ run Rails.application
end
end.to_app
Capybara.asset_root = Rails.root.join('public')
+
From dba9a0421c4a7f99d77f9761424d7489fdc799cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aslak=20Helles=C3=B8y?=
Date: Wed, 24 Feb 2010 09:25:47 +0100
Subject: [PATCH 11/84] Support both Rails 2 and Rails 3
---
lib/capybara/rails.rb | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/lib/capybara/rails.rb b/lib/capybara/rails.rb
index b6a62ec1..13ad0267 100644
--- a/lib/capybara/rails.rb
+++ b/lib/capybara/rails.rb
@@ -3,8 +3,13 @@ require 'capybara/dsl'
Capybara.app = Rack::Builder.new do
map "/" do
- ActionDispatch::Static
- run Rails.application
+ if Rails.version.to_f >= 3.0
+ ActionDispatch::Static
+ run Rails.application
+ else # Rails 2
+ use Rails::Rack::Static
+ run ActionController::Dispatcher.new
+ end
end
end.to_app
From 7ae8f8db5885fb388131b04e318633cfff0dbee3 Mon Sep 17 00:00:00 2001
From: Darrin Holst
Date: Wed, 24 Feb 2010 12:37:31 -0600
Subject: [PATCH 12/84] emulate browser behavior in the rack driver by sending
the button that was clicked even if it doesn't have a value
---
lib/capybara/driver/rack_test_driver.rb | 8 +++----
spec/dsl/click_button_spec.rb | 28 +++++++++++++++----------
spec/views/form.erb | 1 +
3 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb
index 3dc9acc0..e4c4a7be 100644
--- a/lib/capybara/driver/rack_test_driver.rb
+++ b/lib/capybara/driver/rack_test_driver.rb
@@ -106,7 +106,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
class Form < Node
def params(button)
params = {}
-
+
text_fields = %w[text hidden password url color tel email search].map{|f| "@type='#{f}'"}.join(' or ')
node.xpath(".//input[#{text_fields}]").map do |input|
@@ -141,7 +141,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
end
end
end
- merge_param!(params, button[:name], button[:value]) if button[:name]
+ merge_param!(params, button[:name], button[:value] || "") if button[:name]
params
end
@@ -154,7 +154,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
end
private
-
+
def method
self[:method] =~ /post/i ? :post : :get
end
@@ -200,7 +200,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
end
def submit(method, path, attributes)
- path = current_path if not path or path.empty?
+ path = current_path if not path or path.empty?
send(method, path, attributes, env)
follow_redirects!
cache_body
diff --git a/spec/dsl/click_button_spec.rb b/spec/dsl/click_button_spec.rb
index 7a96b8f2..1a2aad2b 100644
--- a/spec/dsl/click_button_spec.rb
+++ b/spec/dsl/click_button_spec.rb
@@ -13,33 +13,33 @@ shared_examples_for "click_button" do
end
context "with value given on a submit button" do
- context "on a form with HTML5 fields" do
+ context "on a form with HTML5 fields" do
before do
@session.click_button('html5_submit')
@results = extract_results(@session)
end
-
+
it "should serialise and submit search fields" do
@results['html5_search'].should == 'what are you looking for'
end
-
+
it "should serialise and submit email fields" do
@results['html5_email'].should == 'person@email.com'
end
-
+
it "should serialise and submit url fields" do
@results['html5_url'].should == 'http://www.example.com'
end
-
+
it "should serialise and submit tel fields" do
@results['html5_tel'].should == '911'
end
-
+
it "should serialise and submit color fields" do
@results['html5_color'].should == '#FFF'
- end
+ end
end
-
+
context "on an HTML4 form" do
before do
@session.click_button('awesome')
@@ -175,7 +175,7 @@ shared_examples_for "click_button" do
@session.click_button('ck_me')
extract_results(@session)['first_name'].should == 'John'
end
-
+
it "should prefer exact matches over partial matches" do
@session.click_button('Just a button')
extract_results(@session)['button'].should == 'Just a button'
@@ -190,6 +190,12 @@ shared_examples_for "click_button" do
end
end
+ it "should serialize and send valueless buttons that were clicked" do
+ @session.click_button('No Value!')
+ @results = extract_results(@session)
+ @results['no_value'].should_not be_nil
+ end
+
it "should serialize and send GET forms" do
@session.visit('/form')
@session.click_button('med')
@@ -202,13 +208,13 @@ shared_examples_for "click_button" do
@session.click_button('Go FAR')
@session.body.should include('You landed')
end
-
+
it "should post pack to the same URL when no action given" do
@session.visit('/postback')
@session.click_button('With no action')
@session.body.should include('Postback')
end
-
+
it "should post pack to the same URL when blank action given" do
@session.visit('/postback')
@session.click_button('With blank action')
diff --git a/spec/views/form.erb b/spec/views/form.erb
index b5cc45ab..d38656d5 100644
--- a/spec/views/form.erb
+++ b/spec/views/form.erb
@@ -153,6 +153,7 @@
+
From 99a3bd8f828502cb59a26a6f0ad32b7fe1c8aa7f Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Thu, 25 Feb 2010 00:17:49 +0100
Subject: [PATCH 13/84] Added gemspec
---
capybara.gemspec | 61 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 capybara.gemspec
diff --git a/capybara.gemspec b/capybara.gemspec
new file mode 100644
index 00000000..363dfc20
--- /dev/null
+++ b/capybara.gemspec
@@ -0,0 +1,61 @@
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{capybara}
+ s.version = "0.3.0"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Jonas Nicklas"]
+ s.date = %q{2010-02-25}
+ s.description = %q{Capybara aims to simplify the process of integration testing Rack applications,
+such as Rails, Sinatra or Merb. It is inspired by and aims to replace Webrat as
+a DSL for interacting with a webapplication. It is agnostic about the driver
+running your tests and currently comes bundled with rack-test, Culerity,
+Celerity and Selenium support built in.}
+ s.email = ["jonas.nicklas@gmail.com"]
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
+ s.files = ["History.txt", "Manifest.txt", "README.rdoc", "Rakefile", "config.ru", "lib/capybara.rb", "lib/capybara/cucumber.rb", "lib/capybara/driver/base.rb", "lib/capybara/driver/celerity_driver.rb", "lib/capybara/driver/culerity_driver.rb", "lib/capybara/driver/rack_test_driver.rb", "lib/capybara/driver/selenium_driver.rb", "lib/capybara/dsl.rb", "lib/capybara/node.rb", "lib/capybara/rails.rb", "lib/capybara/save_and_open_page.rb", "lib/capybara/searchable.rb", "lib/capybara/server.rb", "lib/capybara/session.rb", "lib/capybara/wait_until.rb", "lib/capybara/xpath.rb", "script/console", "script/destroy", "script/generate", "spec/capybara_spec.rb", "spec/driver/celerity_driver_spec.rb", "spec/driver/culerity_driver_spec.rb", "spec/driver/rack_test_driver_spec.rb", "spec/driver/remote_culerity_driver_spec.rb", "spec/driver/remote_selenium_driver_spec.rb", "spec/driver/selenium_driver_spec.rb", "spec/drivers_spec.rb", "spec/dsl/all_spec.rb", "spec/dsl/attach_file_spec.rb", "spec/dsl/check_spec.rb", "spec/dsl/choose_spec.rb", "spec/dsl/click_button_spec.rb", "spec/dsl/click_link_spec.rb", "spec/dsl/click_spec.rb", "spec/dsl/current_url_spec.rb", "spec/dsl/fill_in_spec.rb", "spec/dsl/find_button_spec.rb", "spec/dsl/find_by_id_spec.rb", "spec/dsl/find_field_spec.rb", "spec/dsl/find_link_spec.rb", "spec/dsl/find_spec.rb", "spec/dsl/has_button_spec.rb", "spec/dsl/has_content_spec.rb", "spec/dsl/has_css_spec.rb", "spec/dsl/has_field_spec.rb", "spec/dsl/has_link_spec.rb", "spec/dsl/has_xpath_spec.rb", "spec/dsl/locate_spec.rb", "spec/dsl/select_spec.rb", "spec/dsl/uncheck_spec.rb", "spec/dsl/within_spec.rb", "spec/dsl_spec.rb", "spec/fixtures/capybara.jpg", "spec/fixtures/test_file.txt", "spec/public/jquery-ui.js", "spec/public/jquery.js", "spec/public/test.js", "spec/save_and_open_page_spec.rb", "spec/searchable_spec.rb", "spec/server_spec.rb", "spec/session/celerity_session_spec.rb", "spec/session/culerity_session_spec.rb", "spec/session/rack_test_session_spec.rb", "spec/session/selenium_session_spec.rb", "spec/session_spec.rb", "spec/session_with_headers_support_spec.rb", "spec/session_with_javascript_support_spec.rb", "spec/session_without_headers_support_spec.rb", "spec/session_without_javascript_support_spec.rb", "spec/spec_helper.rb", "spec/test_app.rb", "spec/views/buttons.erb", "spec/views/fieldsets.erb", "spec/views/form.erb", "spec/views/postback.erb", "spec/views/tables.erb", "spec/views/with_html.erb", "spec/views/with_js.erb", "spec/views/with_scope.erb", "spec/views/with_simple_html.erb", "spec/wait_until_spec.rb", "spec/xpath_spec.rb"]
+ s.homepage = %q{http://github.com/jnicklas/capybara}
+ s.rdoc_options = ["--main", "README.rdoc"]
+ s.require_paths = ["lib"]
+ s.rubyforge_project = %q{capybara}
+ s.rubygems_version = %q{1.3.5}
+ s.summary = %q{Capybara aims to simplify the process of integration testing Rack applications, such as Rails, Sinatra or Merb}
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ s.add_runtime_dependency(%q, [">= 1.3.3"])
+ s.add_runtime_dependency(%q, [">= 1.16"])
+ s.add_runtime_dependency(%q, [">= 0.2.4"])
+ s.add_runtime_dependency(%q, [">= 0.0.3"])
+ s.add_runtime_dependency(%q, [">= 1.0.0"])
+ s.add_runtime_dependency(%q, [">= 0.5.2"])
+ s.add_development_dependency(%q, [">= 0.9.4"])
+ s.add_development_dependency(%q, [">= 1.2.9"])
+ s.add_development_dependency(%q, [">= 2.5.0"])
+ else
+ s.add_dependency(%q, [">= 1.3.3"])
+ s.add_dependency(%q, [">= 1.16"])
+ s.add_dependency(%q, [">= 0.2.4"])
+ s.add_dependency(%q, [">= 0.0.3"])
+ s.add_dependency(%q, [">= 1.0.0"])
+ s.add_dependency(%q, [">= 0.5.2"])
+ s.add_dependency(%q, [">= 0.9.4"])
+ s.add_dependency(%q, [">= 1.2.9"])
+ s.add_dependency(%q, [">= 2.5.0"])
+ end
+ else
+ s.add_dependency(%q, [">= 1.3.3"])
+ s.add_dependency(%q, [">= 1.16"])
+ s.add_dependency(%q, [">= 0.2.4"])
+ s.add_dependency(%q, [">= 0.0.3"])
+ s.add_dependency(%q, [">= 1.0.0"])
+ s.add_dependency(%q, [">= 0.5.2"])
+ s.add_dependency(%q, [">= 0.9.4"])
+ s.add_dependency(%q, [">= 1.2.9"])
+ s.add_dependency(%q, [">= 2.5.0"])
+ end
+end
From 125478fe2666e81d4c9ba3721dacf231987deb6c Mon Sep 17 00:00:00 2001
From: Bodaniel Jeanes
Date: Thu, 25 Feb 2010 15:34:25 +1000
Subject: [PATCH 14/84] Added failing tests for click_button to find and submit
image input buttons using the text of the alt attribute
---
spec/dsl/click_button_spec.rb | 12 ++++++++++++
spec/views/form.erb | 2 +-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/spec/dsl/click_button_spec.rb b/spec/dsl/click_button_spec.rb
index 7a96b8f2..59efe3c7 100644
--- a/spec/dsl/click_button_spec.rb
+++ b/spec/dsl/click_button_spec.rb
@@ -113,6 +113,18 @@ shared_examples_for "click_button" do
@session.body.should include('You landed')
end
end
+
+ context "with alt given on an image button" do
+ it "should submit the associated form" do
+ @session.click_button('oh hai thar')
+ extract_results(@session)['first_name'].should == 'John'
+ end
+
+ it "should work with partial matches" do
+ @session.click_button('hai')
+ extract_results(@session)['first_name'].should == 'John'
+ end
+ end
context "with value given on an image button" do
it "should submit the associated form" do
diff --git a/spec/views/form.erb b/spec/views/form.erb
index b5cc45ab..32d926ac 100644
--- a/spec/views/form.erb
+++ b/spec/views/form.erb
@@ -151,7 +151,7 @@
-
+
From ffe2a89d383e358894150c05cf305fbd5cebd5e4 Mon Sep 17 00:00:00 2001
From: Bodaniel Jeanes
Date: Thu, 25 Feb 2010 15:36:57 +1000
Subject: [PATCH 15/84] Fixed failing tests so input[@type='button'] can now be
found via the value of the 'alt' attribute
---
lib/capybara/xpath.rb | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/capybara/xpath.rb b/lib/capybara/xpath.rb
index 398ce2b0..9d3afcbc 100644
--- a/lib/capybara/xpath.rb
+++ b/lib/capybara/xpath.rb
@@ -80,6 +80,7 @@ module Capybara
xpath = append("//input[@type='submit' or @type='image' or @type='button'][@id=#{s(locator)} or contains(@value,#{s(locator)})]")
xpath = xpath.append("//button[@id=#{s(locator)} or contains(@value,#{s(locator)}) or contains(.,#{s(locator)})]")
xpath = xpath.prepend("//input[@type='submit' or @type='image' or @type='button'][@value=#{s(locator)}]")
+ xpath = xpath.prepend("//input[@type='image'][@alt=#{s(locator)} or contains(@alt,#{s(locator)})]")
xpath = xpath.prepend("//button[@value=#{s(locator)} or text()=#{s(locator)}]")
end
From e123a602c42991b611f4f506acac8e9396b50b93 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Thu, 25 Feb 2010 17:52:30 +0100
Subject: [PATCH 16/84] Added missing dsl methods
---
lib/capybara/session.rb | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb
index f98afd39..0bbcf7b1 100644
--- a/lib/capybara/session.rb
+++ b/lib/capybara/session.rb
@@ -9,7 +9,8 @@ module Capybara
:field_labeled, :fill_in, :find, :find_button, :find_by_id, :find_field, :find_link, :has_content?, :has_css?,
:has_no_content?, :has_no_css?, :has_no_xpath?, :has_xpath?, :locate, :save_and_open_page, :select, :source, :uncheck,
:visit, :wait_until, :within, :within_fieldset, :within_table, :has_link?, :has_no_link?, :has_button?, :has_no_button?,
- :has_field?, :has_no_field?, :has_checked_field?, :has_unchecked_field?
+ :has_field?, :has_no_field?, :has_checked_field?, :has_unchecked_field?, :has_no_table?, :has_table?, :unselect,
+ :has_select?, :has_no_select?
]
attr_reader :mode, :app
From 1f35a46388c1a7e392485d03edb1013939c5743b Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Thu, 25 Feb 2010 18:01:22 +0100
Subject: [PATCH 17/84] No more annoying deprecation warnings
---
lib/capybara/driver/celerity_driver.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/capybara/driver/celerity_driver.rb b/lib/capybara/driver/celerity_driver.rb
index e3403675..4108859b 100644
--- a/lib/capybara/driver/celerity_driver.rb
+++ b/lib/capybara/driver/celerity_driver.rb
@@ -14,7 +14,7 @@ class Capybara::Driver::Celerity < Capybara::Driver::Base
end
def value
- if node.type == 'select-multiple'
+ if tag_name == "select" and node.multiple?
node.selected_options
else
super
From c23202bb3a015a001eca402fd3defae120ead0b0 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Thu, 25 Feb 2010 18:01:34 +0100
Subject: [PATCH 18/84] Number of tables has changed
---
spec/drivers_spec.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/spec/drivers_spec.rb b/spec/drivers_spec.rb
index b5fbb892..7f89d36d 100644
--- a/spec/drivers_spec.rb
+++ b/spec/drivers_spec.rb
@@ -115,7 +115,7 @@ shared_examples_for "driver with node path support" do
end
it "should be able to navigate/search child nodes" do
- @node.all('//table').size.should == 3
+ @node.all('//table').size.should == 5
@node.find('//form').all('//table').size.should == 1
@node.find('//form').find('//table//caption').text.should == 'Agent'
end
From eb9f552ca0752667c73cc7dd02ffae92baec6f12 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Thu, 25 Feb 2010 19:37:22 +0100
Subject: [PATCH 19/84] Fix multiple select values under selenium
---
lib/capybara/driver/selenium_driver.rb | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/lib/capybara/driver/selenium_driver.rb b/lib/capybara/driver/selenium_driver.rb
index 2ac6ef47..9f424211 100644
--- a/lib/capybara/driver/selenium_driver.rb
+++ b/lib/capybara/driver/selenium_driver.rb
@@ -16,6 +16,14 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
nil
end
+ def value
+ if tag_name == "select" and self[:multiple]
+ node.find_elements(:xpath, ".//option").select { |n| n.selected? }.map { |n| n.text }
+ else
+ super
+ end
+ end
+
def set(value)
if tag_name == 'textarea' or (tag_name == 'input' and %w(text password hidden file).include?(type))
node.clear
From e8846fb48834744eb3bd1410be2f496f4108bcfc Mon Sep 17 00:00:00 2001
From: Steven Parkes
Date: Thu, 25 Feb 2010 14:51:51 -0800
Subject: [PATCH 20/84] Support external drivers and a few tweaks to support
the envjs driver
* Added code to find drivers that are externally loaded
* Support wait_until in driver
* Optionally make xpath absolute paths absolute
* Add predicate to test if drivers shortcircuit waits and tweak spec
* Allows file:/// (envjs) urls as well as http://foo urls (rack)
* Warm the driver in wait_until tests so the init cost isn't included in the test
---
lib/capybara/driver/base.rb | 11 +++++++++++
lib/capybara/session.rb | 17 ++++++-----------
lib/capybara/wait_until.rb | 9 ++++++---
spec/drivers_spec.rb | 12 +++++++++---
spec/dsl/current_url_spec.rb | 2 +-
spec/session_with_javascript_support_spec.rb | 7 ++++++-
6 files changed, 39 insertions(+), 19 deletions(-)
diff --git a/lib/capybara/driver/base.rb b/lib/capybara/driver/base.rb
index 6cf8c00f..d34d44a5 100644
--- a/lib/capybara/driver/base.rb
+++ b/lib/capybara/driver/base.rb
@@ -19,6 +19,9 @@ class Capybara::Driver::Base
false
end
+ def wait_until *args
+ end
+
def response_headers
raise Capybara::NotSupportedByDriverError
end
@@ -34,4 +37,12 @@ class Capybara::Driver::Base
def cleanup!
end
+ def obeys_absolute_xpath
+ false
+ end
+
+ def has_shortcircuit_timeout
+ false
+ end
+
end
diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb
index 0bbcf7b1..a6a9abbb 100644
--- a/lib/capybara/session.rb
+++ b/lib/capybara/session.rb
@@ -21,16 +21,11 @@ module Capybara
end
def driver
- @driver ||= case mode
- when :rack_test
- Capybara::Driver::RackTest.new(app)
- when :selenium
- Capybara::Driver::Selenium.new(app)
- when :celerity
- Capybara::Driver::Celerity.new(app)
- when :culerity
- Capybara::Driver::Culerity.new(app)
- else
+ @driver ||= begin
+ string = mode.to_s
+ string.gsub!(%r{(^.)|(_.)}) { |m| m[m.length-1,1].upcase }
+ Capybara::Driver.const_get(string.to_sym).new(app)
+ rescue NameError
raise Capybara::DriverNotFoundError, "no driver called #{mode} was found"
end
end
@@ -245,7 +240,7 @@ module Capybara
end
def wait_until(timeout = Capybara.default_wait_time)
- WaitUntil.timeout(timeout) { yield }
+ WaitUntil.timeout(timeout,driver) { yield }
end
def evaluate_script(script)
diff --git a/lib/capybara/wait_until.rb b/lib/capybara/wait_until.rb
index 88d5a704..7d661979 100644
--- a/lib/capybara/wait_until.rb
+++ b/lib/capybara/wait_until.rb
@@ -4,7 +4,7 @@ module Capybara
class << self
- def timeout(seconds = 1, &block)
+ def timeout(seconds = 1, driver = nil, &block)
start_time = Time.now
result = nil
@@ -12,9 +12,12 @@ module Capybara
until result
return result if result = yield
- if (Time.now - start_time) > seconds
- raise TimeoutError
+ delay = seconds - (Time.now - start_time)
+ if delay <= 0
+ raise TimeoutError
end
+
+ driver && driver.wait_until(delay)
end
end
diff --git a/spec/drivers_spec.rb b/spec/drivers_spec.rb
index 7f89d36d..5d44ef66 100644
--- a/spec/drivers_spec.rb
+++ b/spec/drivers_spec.rb
@@ -115,9 +115,15 @@ shared_examples_for "driver with node path support" do
end
it "should be able to navigate/search child nodes" do
- @node.all('//table').size.should == 5
- @node.find('//form').all('//table').size.should == 1
- @node.find('//form').find('//table//caption').text.should == 'Agent'
+ if @driver.obeys_absolute_xpath
+ @node.all('.//table').size.should == 5
+ @node.find('.//form').all('.//table').size.should == 1
+ @node.find('.//form').find('.//table//caption').text.should == 'Agent'
+ else
+ @node.all('//table').size.should == 5
+ @node.find('//form').all('//table').size.should == 1
+ @node.find('//form').find('//table//caption').text.should == 'Agent'
+ end
end
end
end
diff --git a/spec/dsl/current_url_spec.rb b/spec/dsl/current_url_spec.rb
index c514d3ea..27074f08 100644
--- a/spec/dsl/current_url_spec.rb
+++ b/spec/dsl/current_url_spec.rb
@@ -2,7 +2,7 @@ shared_examples_for "current_url" do
describe '#current_url' do
it "should return the current url" do
@session.visit('/form')
- @session.current_url.should =~ %r(http://[^/]+/form)
+ @session.current_url.should =~ %r((file|http)://[^/]*/form)
end
end
end
diff --git a/spec/session_with_javascript_support_spec.rb b/spec/session_with_javascript_support_spec.rb
index 4a6dc66c..21a0d8f0 100644
--- a/spec/session_with_javascript_support_spec.rb
+++ b/spec/session_with_javascript_support_spec.rb
@@ -90,12 +90,17 @@ shared_examples_for "session with javascript support" do
end
it "should default to Capybara.default_wait_time before timeout" do
+ @session.driver # init the driver to exclude init timing from test
start = Time.now
Capybara.default_wait_time = 0.2
begin
@session.wait_until { false }
rescue Capybara::TimeoutError; end
- (Time.now - start).should be_close(0.2, 0.1)
+ if @session.driver.has_shortcircuit_timeout
+ (Time.now - start).should be_close(0, 0.1)
+ else
+ (Time.now - start).should be_close(0.2, 0.1)
+ end
end
end
From 2f3dc8f53405190aec39e060abdd6fac17cfd724 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Fri, 26 Feb 2010 01:04:00 +0100
Subject: [PATCH 21/84] Wrap JS specs in describe block so timeout change only
affects them
This caused some specs to time out and fail
---
spec/session_with_javascript_support_spec.rb | 324 ++++++++++---------
1 file changed, 163 insertions(+), 161 deletions(-)
diff --git a/spec/session_with_javascript_support_spec.rb b/spec/session_with_javascript_support_spec.rb
index 4a6dc66c..a89696a1 100644
--- a/spec/session_with_javascript_support_spec.rb
+++ b/spec/session_with_javascript_support_spec.rb
@@ -3,180 +3,182 @@ require File.expand_path('spec_helper', File.dirname(__FILE__))
require 'nokogiri'
shared_examples_for "session with javascript support" do
- before do
- Capybara.default_wait_time = 1
- end
-
- after do
- Capybara.default_wait_time = 0
- end
-
- describe '#find' do
- it "should allow triggering of custom JS events" do
- pending "cannot figure out how to do this with selenium" if @session.mode == :selenium
- @session.visit('/with_js')
- @session.find(:css, '#with_focus_event').trigger(:focus)
- @session.should have_css('#focus_event_triggered')
- end
- end
-
- describe '#body' do
- it "should return the current state of the page" do
- @session.visit('/with_js')
- @session.body.should include('I changed it')
- @session.body.should_not include('This is text')
- end
- end
-
- describe '#source' do
- it "should return the original, unmodified source of the page" do
- pending "cannot figure out how to do this with selenium" if @session.mode == :selenium
- @session.visit('/with_js')
- @session.source.should include('This is text')
- @session.source.should_not include('I changed it')
- end
- end
-
- describe "#evaluate_script" do
- it "should return the evaluated script" do
- @session.visit('/with_js')
- @session.evaluate_script("1+3").should == 4
- end
- end
-
- describe '#locate' do
- it "should wait for asynchronous load" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.locate("//a[contains(.,'Has been clicked')]")[:href].should == '#'
- end
- end
-
- describe '#wait_until' do
+ describe 'all JS specs' do
before do
- @default_timeout = Capybara.default_wait_time
+ Capybara.default_wait_time = 1
end
after do
- Capybara.default_wait_time = @default_wait_time
+ Capybara.default_wait_time = 0
end
-
- it "should wait for block to return true" do
- @session.visit('/with_js')
- @session.select('My Waiting Option', :from => 'waiter')
- @session.evaluate_script('activeRequests == 1').should be_true
- @session.wait_until do
- @session.evaluate_script('activeRequests == 0')
+
+ describe '#find' do
+ it "should allow triggering of custom JS events" do
+ pending "cannot figure out how to do this with selenium" if @session.mode == :selenium
+ @session.visit('/with_js')
+ @session.find(:css, '#with_focus_event').trigger(:focus)
+ @session.should have_css('#focus_event_triggered')
end
- @session.evaluate_script('activeRequests == 0').should be_true
end
- it "should raise Capybara::TimeoutError if block doesn't return true within timeout" do
- @session.visit('/with_html')
- Proc.new do
- @session.wait_until(0.1) do
- @session.find('//div[@id="nosuchthing"]')
+ describe '#body' do
+ it "should return the current state of the page" do
+ @session.visit('/with_js')
+ @session.body.should include('I changed it')
+ @session.body.should_not include('This is text')
+ end
+ end
+
+ describe '#source' do
+ it "should return the original, unmodified source of the page" do
+ pending "cannot figure out how to do this with selenium" if @session.mode == :selenium
+ @session.visit('/with_js')
+ @session.source.should include('This is text')
+ @session.source.should_not include('I changed it')
+ end
+ end
+
+ describe "#evaluate_script" do
+ it "should return the evaluated script" do
+ @session.visit('/with_js')
+ @session.evaluate_script("1+3").should == 4
+ end
+ end
+
+ describe '#locate' do
+ it "should wait for asynchronous load" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.locate("//a[contains(.,'Has been clicked')]")[:href].should == '#'
+ end
+ end
+
+ describe '#wait_until' do
+ before do
+ @default_timeout = Capybara.default_wait_time
+ end
+
+ after do
+ Capybara.default_wait_time = @default_wait_time
+ end
+
+ it "should wait for block to return true" do
+ @session.visit('/with_js')
+ @session.select('My Waiting Option', :from => 'waiter')
+ @session.evaluate_script('activeRequests == 1').should be_true
+ @session.wait_until do
+ @session.evaluate_script('activeRequests == 0')
end
- end.should raise_error(::Capybara::TimeoutError)
+ @session.evaluate_script('activeRequests == 0').should be_true
+ end
+
+ it "should raise Capybara::TimeoutError if block doesn't return true within timeout" do
+ @session.visit('/with_html')
+ Proc.new do
+ @session.wait_until(0.1) do
+ @session.find('//div[@id="nosuchthing"]')
+ end
+ end.should raise_error(::Capybara::TimeoutError)
+ end
+
+ it "should accept custom timeout in seconds" do
+ start = Time.now
+ Capybara.default_wait_time = 5
+ begin
+ @session.wait_until(0.1) { false }
+ rescue Capybara::TimeoutError; end
+ (Time.now - start).should be_close(0.1, 0.1)
+ end
+
+ it "should default to Capybara.default_wait_time before timeout" do
+ start = Time.now
+ Capybara.default_wait_time = 0.2
+ begin
+ @session.wait_until { false }
+ rescue Capybara::TimeoutError; end
+ (Time.now - start).should be_close(0.2, 0.1)
+ end
end
- it "should accept custom timeout in seconds" do
- start = Time.now
- Capybara.default_wait_time = 5
- begin
- @session.wait_until(0.1) { false }
- rescue Capybara::TimeoutError; end
- (Time.now - start).should be_close(0.1, 0.1)
+ describe '#click' do
+ it "should wait for asynchronous load" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.click('Has been clicked')
+ end
end
- it "should default to Capybara.default_wait_time before timeout" do
- start = Time.now
- Capybara.default_wait_time = 0.2
- begin
- @session.wait_until { false }
- rescue Capybara::TimeoutError; end
- (Time.now - start).should be_close(0.2, 0.1)
+ describe '#click_link' do
+ it "should wait for asynchronous load" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.click_link('Has been clicked')
+ end
end
+
+ describe '#click_button' do
+ it "should wait for asynchronous load" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.click_button('New Here')
+ end
+ end
+
+ describe '#fill_in' do
+ it "should wait for asynchronous load" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.fill_in('new_field', :with => 'Testing...')
+ end
+ end
+
+ describe '#has_xpath?' do
+ it "should wait for content to appear" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.should have_xpath("//input[@type='submit' and @value='New Here']")
+ end
+ end
+
+ describe '#has_no_xpath?' do
+ it "should wait for content to disappear" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.should have_no_xpath("//p[@id='change']")
+ end
+ end
+
+ describe '#has_css?' do
+ it "should wait for content to appear" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.should have_css("input[type='submit'][value='New Here']")
+ end
+ end
+
+ describe '#has_no_xpath?' do
+ it "should wait for content to disappear" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.should have_no_css("p#change")
+ end
+ end
+
+ describe '#has_content?' do
+ it "should wait for content to appear" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.should have_content("Has been clicked")
+ end
+ end
+
+ describe '#has_no_content?' do
+ it "should wait for content to disappear" do
+ @session.visit('/with_js')
+ @session.click_link('Click me')
+ @session.should have_no_content("I changed it")
+ end
+ end
+
end
-
- describe '#click' do
- it "should wait for asynchronous load" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.click('Has been clicked')
- end
- end
-
- describe '#click_link' do
- it "should wait for asynchronous load" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.click_link('Has been clicked')
- end
- end
-
- describe '#click_button' do
- it "should wait for asynchronous load" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.click_button('New Here')
- end
- end
-
- describe '#fill_in' do
- it "should wait for asynchronous load" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.fill_in('new_field', :with => 'Testing...')
- end
- end
-
- describe '#has_xpath?' do
- it "should wait for content to appear" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.should have_xpath("//input[@type='submit' and @value='New Here']")
- end
- end
-
- describe '#has_no_xpath?' do
- it "should wait for content to disappear" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.should have_no_xpath("//p[@id='change']")
- end
- end
-
- describe '#has_css?' do
- it "should wait for content to appear" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.should have_css("input[type='submit'][value='New Here']")
- end
- end
-
- describe '#has_no_xpath?' do
- it "should wait for content to disappear" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.should have_no_css("p#change")
- end
- end
-
- describe '#has_content?' do
- it "should wait for content to appear" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.should have_content("Has been clicked")
- end
- end
-
- describe '#has_no_content?' do
- it "should wait for content to disappear" do
- @session.visit('/with_js')
- @session.click_link('Click me')
- @session.should have_no_content("I changed it")
- end
- end
-
end
From 0ed383238fd440e2e3fedcebca480e04bf68b1c2 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Fri, 26 Feb 2010 01:14:58 +0100
Subject: [PATCH 22/84] Init C[ue]lerity driver/session in before(:all)
This way we don't create a crap load of instances
which leads to out-of-memory exceptions.
---
spec/driver/celerity_driver_spec.rb | 4 ++--
spec/driver/culerity_driver_spec.rb | 2 +-
spec/driver/remote_culerity_driver_spec.rb | 5 +----
spec/session/celerity_session_spec.rb | 4 ++--
spec/session/culerity_session_spec.rb | 2 +-
5 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/spec/driver/celerity_driver_spec.rb b/spec/driver/celerity_driver_spec.rb
index bd31440a..3ed2e096 100644
--- a/spec/driver/celerity_driver_spec.rb
+++ b/spec/driver/celerity_driver_spec.rb
@@ -2,7 +2,7 @@ require File.expand_path('../spec_helper', File.dirname(__FILE__))
if RUBY_PLATFORM =~ /java/
describe Capybara::Driver::Celerity do
- before do
+ before(:all) do
@driver = Capybara::Driver::Celerity.new(TestApp)
end
@@ -14,4 +14,4 @@ if RUBY_PLATFORM =~ /java/
end
else
puts "#{File.basename(__FILE__)} requires JRuby; skipping.."
-end
\ No newline at end of file
+end
diff --git a/spec/driver/culerity_driver_spec.rb b/spec/driver/culerity_driver_spec.rb
index ec6a4e3d..ee0fac38 100644
--- a/spec/driver/culerity_driver_spec.rb
+++ b/spec/driver/culerity_driver_spec.rb
@@ -1,7 +1,7 @@
require File.expand_path('../spec_helper', File.dirname(__FILE__))
describe Capybara::Driver::Culerity do
- before do
+ before(:all) do
@driver = Capybara::Driver::Culerity.new(TestApp)
end
diff --git a/spec/driver/remote_culerity_driver_spec.rb b/spec/driver/remote_culerity_driver_spec.rb
index e30fc16d..d3a2c5bd 100644
--- a/spec/driver/remote_culerity_driver_spec.rb
+++ b/spec/driver/remote_culerity_driver_spec.rb
@@ -1,13 +1,10 @@
require File.expand_path('../spec_helper', File.dirname(__FILE__))
describe Capybara::Driver::Culerity do
- before do
- @driver = Capybara::Driver::Culerity.new(TestApp)
- end
-
before(:all) do
Capybara.app_host = "http://capybara-testapp.heroku.com"
Capybara.run_server = false
+ @driver = Capybara::Driver::Culerity.new(TestApp)
end
after(:all) do
diff --git a/spec/session/celerity_session_spec.rb b/spec/session/celerity_session_spec.rb
index 83c06c67..d6b8e989 100644
--- a/spec/session/celerity_session_spec.rb
+++ b/spec/session/celerity_session_spec.rb
@@ -2,7 +2,7 @@ require File.expand_path('../spec_helper', File.dirname(__FILE__))
if RUBY_PLATFORM =~ /java/
describe Capybara::Driver::Celerity do
- before do
+ before(:all) do
@session = Capybara::Session.new(:celerity, TestApp)
end
@@ -24,4 +24,4 @@ if RUBY_PLATFORM =~ /java/
end
else
puts "#{File.basename(__FILE__)} requires JRuby; skipping.."
-end
\ No newline at end of file
+end
diff --git a/spec/session/culerity_session_spec.rb b/spec/session/culerity_session_spec.rb
index 958308b9..6bff94fd 100644
--- a/spec/session/culerity_session_spec.rb
+++ b/spec/session/culerity_session_spec.rb
@@ -2,7 +2,7 @@ require File.expand_path('../spec_helper', File.dirname(__FILE__))
describe Capybara::Session do
context 'with culerity driver' do
- before do
+ before(:all) do
@session = Capybara::Session.new(:culerity, TestApp)
end
From 58380cce3d2121fbafd7e21ddd6969a56508a176 Mon Sep 17 00:00:00 2001
From: Steven Parkes
Date: Thu, 25 Feb 2010 16:32:24 -0800
Subject: [PATCH 23/84] revert spec chanage; disallow file urls again
---
spec/dsl/current_url_spec.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/spec/dsl/current_url_spec.rb b/spec/dsl/current_url_spec.rb
index 27074f08..c514d3ea 100644
--- a/spec/dsl/current_url_spec.rb
+++ b/spec/dsl/current_url_spec.rb
@@ -2,7 +2,7 @@ shared_examples_for "current_url" do
describe '#current_url' do
it "should return the current url" do
@session.visit('/form')
- @session.current_url.should =~ %r((file|http)://[^/]*/form)
+ @session.current_url.should =~ %r(http://[^/]+/form)
end
end
end
From 20e32d9d4a7ccea3ca07e5460671b475b4184929 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Fri, 26 Feb 2010 09:04:45 +0100
Subject: [PATCH 24/84] Darrin Holst to contributors
---
README.rdoc | 1 +
lib/capybara/server.rb | 18 ++++++++++--------
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/README.rdoc b/README.rdoc
index ef22bd3d..6042ed3c 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -377,6 +377,7 @@ The following people have dedicated their time and effort to Capybara:
* Pavel Gabriel
* Bodaniel Jeanes
* Carl Porth
+* Darrin Holst
== License:
diff --git a/lib/capybara/server.rb b/lib/capybara/server.rb
index 3723547b..5d2840a3 100644
--- a/lib/capybara/server.rb
+++ b/lib/capybara/server.rb
@@ -59,16 +59,18 @@ class Capybara::Server
Capybara.log "application has already booted" and return self if responsive?
Capybara.log "booting Rack applicartion on port #{port}"
- Timeout.timeout(10) do
- Thread.new do
- handler.run(Identify.new(@app), :Port => port, :AccessLog => [])
- end
- Capybara.log "checking if application has booted"
+ Thread.new do
+ handler.run(Identify.new(@app), :Port => port, :AccessLog => [])
+ end
+ Capybara.log "checking if application has booted"
- loop do
- Capybara.log("application has booted") and break if responsive?
- Capybara.log("waiting for application to boot...")
+ Capybara::WaitUntil.timeout(10) do
+ if responsive?
+ Capybara.log("application has booted")
+ true
+ else
sleep 0.5
+ false
end
end
self
From 9a19b758cade62a52e0039cffd713a5f98a3b852 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Fri, 26 Feb 2010 18:38:22 +0100
Subject: [PATCH 25/84] All drivers now support relative searching
There is a bug in Selenium, which causes it to
find only descendant nodes, even when asked for
a global search. Bug filed here:
http://code.google.com/p/selenium/issues/detail?id=403
---
lib/capybara/driver/celerity_driver.rb | 8 ++++
lib/capybara/driver/rack_test_driver.rb | 4 ++
lib/capybara/driver/selenium_driver.rb | 4 ++
spec/driver/culerity_driver_spec.rb | 1 -
spec/driver/rack_test_driver_spec.rb | 1 -
spec/driver/selenium_driver_spec.rb | 1 -
spec/drivers_spec.rb | 52 ++++++++++---------------
7 files changed, 36 insertions(+), 35 deletions(-)
diff --git a/lib/capybara/driver/celerity_driver.rb b/lib/capybara/driver/celerity_driver.rb
index 4108859b..d5c63e8d 100644
--- a/lib/capybara/driver/celerity_driver.rb
+++ b/lib/capybara/driver/celerity_driver.rb
@@ -77,6 +77,14 @@ class Capybara::Driver::Celerity < Capybara::Driver::Base
node.fire_event(event.to_s)
end
+ private
+
+ def all_unfiltered(locator)
+ noko_node = Nokogiri::HTML(driver.body).xpath(node.xpath).first
+ all_nodes = noko_node.xpath(locator).map { |n| n.path }.join(' | ')
+ driver.find(all_nodes)
+ end
+
end
attr_reader :app, :rack_server
diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb
index e4c4a7be..dc0c2c1a 100644
--- a/lib/capybara/driver/rack_test_driver.rb
+++ b/lib/capybara/driver/rack_test_driver.rb
@@ -94,6 +94,10 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
private
+ def all_unfiltered(locator)
+ node.xpath(locator).map { |n| self.class.new(driver, n) }
+ end
+
def type
node[:type]
end
diff --git a/lib/capybara/driver/selenium_driver.rb b/lib/capybara/driver/selenium_driver.rb
index 9f424211..20e08407 100644
--- a/lib/capybara/driver/selenium_driver.rb
+++ b/lib/capybara/driver/selenium_driver.rb
@@ -78,6 +78,10 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
private
+ def all_unfiltered(locator)
+ node.find_elements(:xpath, locator).map { |n| self.class.new(driver, n) }
+ end
+
def type
self[:type]
end
diff --git a/spec/driver/culerity_driver_spec.rb b/spec/driver/culerity_driver_spec.rb
index ee0fac38..c01ab97c 100644
--- a/spec/driver/culerity_driver_spec.rb
+++ b/spec/driver/culerity_driver_spec.rb
@@ -8,6 +8,5 @@ describe Capybara::Driver::Culerity do
it_should_behave_like "driver"
it_should_behave_like "driver with javascript support"
it_should_behave_like "driver with header support"
- it_should_behave_like "driver with node path support"
end
diff --git a/spec/driver/rack_test_driver_spec.rb b/spec/driver/rack_test_driver_spec.rb
index 7b2c8d67..e4b03d5e 100644
--- a/spec/driver/rack_test_driver_spec.rb
+++ b/spec/driver/rack_test_driver_spec.rb
@@ -7,6 +7,5 @@ describe Capybara::Driver::RackTest do
it_should_behave_like "driver"
it_should_behave_like "driver with header support"
- it_should_behave_like "driver with node path support"
end
diff --git a/spec/driver/selenium_driver_spec.rb b/spec/driver/selenium_driver_spec.rb
index a71047e0..c2b2b4c1 100644
--- a/spec/driver/selenium_driver_spec.rb
+++ b/spec/driver/selenium_driver_spec.rb
@@ -7,6 +7,5 @@ describe Capybara::Driver::Selenium do
it_should_behave_like "driver"
it_should_behave_like "driver with javascript support"
- it_should_behave_like "driver without node path support"
end
diff --git a/spec/drivers_spec.rb b/spec/drivers_spec.rb
index 7f89d36d..c1614686 100644
--- a/spec/drivers_spec.rb
+++ b/spec/drivers_spec.rb
@@ -72,6 +72,26 @@ shared_examples_for 'driver' do
end
end
+ describe "node relative searching" do
+ before do
+ @driver.visit('/tables')
+ @node = @driver.find('//body').first
+ end
+
+ it "should be able to navigate/search child node" do
+ @node.all('//table').size.should == 5
+ @node.find('//form').all('.//table').size.should == 1
+ @node.find('//form').find('.//table//caption').text.should == 'Agent'
+ if @driver.class == Capybara::Driver::Selenium
+ pending("Selenium gets this wrong, see http://code.google.com/p/selenium/issues/detail?id=403") do
+ @node.find('//form').all('//table').size.should == 5
+ end
+ else
+ @node.find('//form').all('//table').size.should == 5
+ end
+ end
+ end
+
end
shared_examples_for "driver with javascript support" do
@@ -97,7 +117,6 @@ shared_examples_for "driver with javascript support" do
@driver.evaluate_script('1+1').should == 2
end
end
-
end
shared_examples_for "driver with header support" do
@@ -106,34 +125,3 @@ shared_examples_for "driver with header support" do
@driver.response_headers['Content-Type'].should == 'text/html'
end
end
-
-shared_examples_for "driver with node path support" do
- describe "node relative searching" do
- before do
- @driver.visit('/tables')
- @node = @driver.find('//body').first
- end
-
- it "should be able to navigate/search child nodes" do
- @node.all('//table').size.should == 5
- @node.find('//form').all('//table').size.should == 1
- @node.find('//form').find('//table//caption').text.should == 'Agent'
- end
- end
-end
-
-shared_examples_for "driver without node path support" do
- describe "node relative searching" do
- before do
- @driver.visit('/tables')
- @node = @driver.find('//body').first
- end
-
- it "should get NotSupportedByDriverError" do
- running do
- @node.all('//form')
- end.should raise_error(Capybara::NotSupportedByDriverError)
- end
-
- end
-end
From a0e9d78d8f41b90ee3eed76e047082ac3ccfd32b Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Fri, 26 Feb 2010 18:39:23 +0100
Subject: [PATCH 26/84] Yo dawg, I put a revert in ur revert
Readding support for specifying host for mock rack session
This reverts commit 62bd215a476d84da5311a32ecb00fee0d9a8c3e7.
---
lib/capybara.rb | 2 +-
lib/capybara/driver/rack_test_driver.rb | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/capybara.rb b/lib/capybara.rb
index 3ca07809..5cddde47 100644
--- a/lib/capybara.rb
+++ b/lib/capybara.rb
@@ -15,7 +15,7 @@ module Capybara
class InfiniteRedirectError < TimeoutError; end
class << self
- attr_accessor :debug, :asset_root, :app_host, :run_server
+ attr_accessor :debug, :asset_root, :app_host, :run_server, :default_host
attr_accessor :default_selector, :default_wait_time, :ignore_hidden_elements
def default_selector
diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb
index dc0c2c1a..f11fe83d 100644
--- a/lib/capybara/driver/rack_test_driver.rb
+++ b/lib/capybara/driver/rack_test_driver.rb
@@ -216,6 +216,10 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
private
+ def build_rack_mock_session # :nodoc:
+ Rack::MockSession.new(app, Capybara.default_host)
+ end
+
def current_path
request.path rescue ""
end
From 3d673af67178f10e0dcc1127870fe362c2c63300 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Fri, 26 Feb 2010 18:52:28 +0100
Subject: [PATCH 27/84] added History for Capybara 0.3.5
---
History.txt | 36 +++++++++++++++++++++++++++++++++---
1 file changed, 33 insertions(+), 3 deletions(-)
diff --git a/History.txt b/History.txt
index 01496bb3..ceb169d1 100644
--- a/History.txt
+++ b/History.txt
@@ -1,4 +1,34 @@
-=== 0.0.1 2009-11-04
+# Version 0.3.5
+
+Release date: 2010-02-26
+
+This is a mostly backwards compatible release, it does break
+the API in some minor places, which should hopefully not affect
+too many users, please read the release notes carefully!
+
+### Breaking
+
+* Relative searching in a node (e.g. find('//p').all('//a')) will now follow XPath standard
+ this means that if you want to find descendant nodes only, you'll need to prefix a dot!
+* `visit` now accepts fully qualified URLs for drivers that support it.
+* Capybara will always try to run a rack server, unless you set Capybara.run_sever = false
+
+### Changed
+
+* thin is preferred over mongrel and webrick, since it is Ruby 1.9 compatible
+* click_button and click will find , clicking them does nothing in RackTest
+
+### Added
+
+* Much improved error messages in a multitude of places
+* More semantic page querying with has_link?, has_button?, etc...
+* Option to ignore hidden elements when querying and interacting with the page
+* Support for multiple selects
+
+### Fixed
+
+* find_by_id is no longer broken
+* clicking links where the image's alt attribute contains the text is now possible
+* within_fieldset and within_table work when the default selector is CSS
+* boolean attributes work the same across drivers (return true/false)
-* 1 major enhancement:
- * Initial release
From c7a79731e5dba9ff6b37fef475739a64d8a75dba Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Fri, 26 Feb 2010 18:56:38 +0100
Subject: [PATCH 28/84] Added default host when not set
---
lib/capybara/driver/rack_test_driver.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb
index f11fe83d..89ab5047 100644
--- a/lib/capybara/driver/rack_test_driver.rb
+++ b/lib/capybara/driver/rack_test_driver.rb
@@ -217,7 +217,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
private
def build_rack_mock_session # :nodoc:
- Rack::MockSession.new(app, Capybara.default_host)
+ Rack::MockSession.new(app, Capybara.default_host || "example.org")
end
def current_path
From 322cdf43856a50684709dd9bd5947d0275fe7110 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Fri, 26 Feb 2010 18:56:52 +0100
Subject: [PATCH 29/84] Tagged Version 0.3.5
---
lib/capybara.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/capybara.rb b/lib/capybara.rb
index 5cddde47..acf3e57e 100644
--- a/lib/capybara.rb
+++ b/lib/capybara.rb
@@ -2,7 +2,7 @@ require 'timeout'
require 'nokogiri'
module Capybara
- VERSION = '0.3.0'
+ VERSION = '0.3.5'
class CapybaraError < StandardError; end
class DriverNotFoundError < CapybaraError; end
From c1eed949b324cc99b02f9ece4ab3ec199f7bcb17 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Sat, 27 Feb 2010 02:31:27 +0100
Subject: [PATCH 30/84] Changed fallback host to www.example.com
This matches with Cucumber, and should hopefully
cause somewhat less lost sessions
---
lib/capybara/driver/rack_test_driver.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb
index 89ab5047..831f88da 100644
--- a/lib/capybara/driver/rack_test_driver.rb
+++ b/lib/capybara/driver/rack_test_driver.rb
@@ -217,7 +217,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
private
def build_rack_mock_session # :nodoc:
- Rack::MockSession.new(app, Capybara.default_host || "example.org")
+ Rack::MockSession.new(app, Capybara.default_host || "www.example.com")
end
def current_path
From b8154a2f32b3bd2d85e78f830a4d927bff8edbce Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Sat, 27 Feb 2010 19:26:38 +0100
Subject: [PATCH 31/84] Removed unused base code for relative finds
---
lib/capybara/node.rb | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/lib/capybara/node.rb b/lib/capybara/node.rb
index acbc610c..8db3fa1d 100644
--- a/lib/capybara/node.rb
+++ b/lib/capybara/node.rb
@@ -56,14 +56,5 @@ module Capybara
def trigger(event)
raise NotSupportedByDriverError
end
-
- private
-
- def all_unfiltered(locator)
- nodes = XPath.wrap(locator).scope(path).paths.map do |path|
- driver.find(path)
- end.flatten
- end
-
end
end
From d298f4dc8c5030db1708fa3c10cc45afca2f9b23 Mon Sep 17 00:00:00 2001
From: Jonas Nicklas
Date: Sat, 27 Feb 2010 19:27:06 +0100
Subject: [PATCH 32/84] Use #click instead of #toggle for Selenium, Closes #50
---
lib/capybara/driver/selenium_driver.rb | 2 +-
spec/public/test.js | 5 ++++-
spec/session_with_javascript_support_spec.rb | 8 ++++++++
spec/views/with_js.erb | 5 +++++
4 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/lib/capybara/driver/selenium_driver.rb b/lib/capybara/driver/selenium_driver.rb
index 20e08407..8c289f2c 100644
--- a/lib/capybara/driver/selenium_driver.rb
+++ b/lib/capybara/driver/selenium_driver.rb
@@ -31,7 +31,7 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
elsif tag_name == 'input' and type == 'radio'
node.select
elsif tag_name == 'input' and type == 'checkbox'
- node.toggle
+ node.click
end
end
diff --git a/spec/public/test.js b/spec/public/test.js
index 4eeb9d39..7ec9cd16 100644
--- a/spec/public/test.js
+++ b/spec/public/test.js
@@ -27,4 +27,7 @@ $(function() {
$('#with_focus_event').focus(function() {
$('body').append('
Focus Event triggered
')
});
-});
\ No newline at end of file
+ $('#checkbox_with_event').click(function() {
+ $('body').append('
Checkbox event triggered
')
+ });
+});
diff --git a/spec/session_with_javascript_support_spec.rb b/spec/session_with_javascript_support_spec.rb
index a89696a1..d414c7ba 100644
--- a/spec/session_with_javascript_support_spec.rb
+++ b/spec/session_with_javascript_support_spec.rb
@@ -132,6 +132,14 @@ shared_examples_for "session with javascript support" do
end
end
+ describe '#check' do
+ it "should trigger associated events" do
+ @session.visit('/with_js')
+ @session.check('checkbox_with_event')
+ @session.should have_css('#checkbox_event_triggered');
+ end
+ end
+
describe '#has_xpath?' do
it "should wait for content to appear" do
@session.visit('/with_js')
diff --git a/spec/views/with_js.erb b/spec/views/with_js.erb
index 39b829c6..1517d67c 100644
--- a/spec/views/with_js.erb
+++ b/spec/views/with_js.erb
@@ -30,5 +30,10 @@