From 07f9ae6b094b356c3fbcbd193e52452b2770fecb Mon Sep 17 00:00:00 2001 From: Andrea Fazzi Date: Mon, 11 Jan 2010 14:45:36 +0100 Subject: [PATCH] Add the new global setting ignore_hidden_elements that is true by default. This setting adds a new behaviour in the interaction with hidden elements. By default #locate, #click*, #choose, #select, etc. will ignore hidden elements. You can override this behaviour setting ignore_hidden_elements = false --- lib/capybara.rb | 9 +++++++-- lib/capybara/session.rb | 6 ++++-- spec/drivers_spec.rb | 3 ++- spec/dsl/attach_file_spec.rb | 18 +++++++++++++++++- spec/dsl/check_spec.rb | 18 +++++++++++++++++- spec/dsl/choose_spec.rb | 18 +++++++++++++++++- spec/dsl/click_button_spec.rb | 16 ++++++++++++++++ spec/dsl/click_link_spec.rb | 18 +++++++++++++++++- spec/dsl/click_spec.rb | 19 ++++++++++++++++++- spec/dsl/fill_in_spec.rb | 18 +++++++++++++++++- spec/dsl/locate_spec.rb | 20 +++++++++++++++++++- spec/dsl/select_spec.rb | 18 +++++++++++++++++- spec/dsl/uncheck_spec.rb | 18 +++++++++++++++++- spec/views/form.erb | 20 ++++++++++++++++++++ spec/views/with_html.erb | 1 + 15 files changed, 206 insertions(+), 14 deletions(-) diff --git a/lib/capybara.rb b/lib/capybara.rb index 66149196..41c10af8 100644 --- a/lib/capybara.rb +++ b/lib/capybara.rb @@ -9,11 +9,12 @@ module Capybara class ElementNotFound < CapybaraError; end class NotSupportedByDriverError < CapybaraError; end class TimeoutError < CapybaraError; end - + class LocateHiddenElementError < CapybaraError; end + class << self attr_accessor :debug, :asset_root, :app_host attr_writer :default_selector, :default_wait_time - + attr_writer :ignore_hidden_elements def default_selector @default_selector ||= :xpath @@ -23,6 +24,10 @@ module Capybara @default_wait_time ||= 2 end + def ignore_hidden_elements + (@ignore_hidden_elements.nil? || @ignore_hidden_elements) ? true : false + end + def log(message) puts "[capybara] #{message}" if debug true diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb index 74f5e598..195e5382 100644 --- a/lib/capybara/session.rb +++ b/lib/capybara/session.rb @@ -167,11 +167,13 @@ module Capybara Capybara::SaveAndOpenPage.save_and_open_page(body) end - #return node identified by locator or raise ElementNotFound(using desc) + # Return element identified by locator or raise ElementNotFound (using desc). + # If element is hidden raise LocateHiddenElementError. def locate(locator, fail_msg = nil) - node = wait_conditionally_until { find(locator) } + node = wait_conditionally_until { Capybara.ignore_hidden_elements ? find(locator, :visible => true) : find(locator) } ensure raise Capybara::ElementNotFound, fail_msg || "Unable to locate '#{locator}'" unless node + raise Capybara::LocateHiddenElementError, "The element selected by '#{locator}' is hidden" unless node.visible? return node end diff --git a/spec/drivers_spec.rb b/spec/drivers_spec.rb index f11f868c..d5dd94ef 100644 --- a/spec/drivers_spec.rb +++ b/spec/drivers_spec.rb @@ -35,7 +35,8 @@ shared_examples_for 'driver' do end it "should find the correct number of elements" do - @driver.find('//a').size.should == 3 + debugger + @driver.find('//a').size.should == 4 end it "should extract node texts" do diff --git a/spec/dsl/attach_file_spec.rb b/spec/dsl/attach_file_spec.rb index 713f3c66..d792ba92 100644 --- a/spec/dsl/attach_file_spec.rb +++ b/spec/dsl/attach_file_spec.rb @@ -48,6 +48,22 @@ module AttachFileSpec running { @session.attach_file('does not exist', 'foo.txt') }.should raise_error(Capybara::ElementNotFound) end end + + context "with a locator that selects a hidden node" do + before do + Capybara.ignore_hidden_elements = false + end + + after do + Capybara.ignore_hidden_elements = true + end + + it "should raise an error" do + running do + @session.attach_file("hidden_form_upload", 'foo.txt') + end.should raise_error(Capybara::LocateHiddenElementError) + end + end end end -end \ No newline at end of file +end diff --git a/spec/dsl/check_spec.rb b/spec/dsl/check_spec.rb index 8c4fb40a..e7d637ad 100644 --- a/spec/dsl/check_spec.rb +++ b/spec/dsl/check_spec.rb @@ -23,6 +23,22 @@ module CheckSpec running { @session.check('does not exist') }.should raise_error(Capybara::ElementNotFound) end end + + context "with a locator that selects a hidden node" do + before do + Capybara.ignore_hidden_elements = false + end + + after do + Capybara.ignore_hidden_elements = true + end + + it "should raise an error" do + running do + @session.check('hidden_unchecked_checkbox') + end.should raise_error(Capybara::LocateHiddenElementError) + end + end end end -end \ No newline at end of file +end diff --git a/spec/dsl/choose_spec.rb b/spec/dsl/choose_spec.rb index 2049f7d2..95d258a6 100644 --- a/spec/dsl/choose_spec.rb +++ b/spec/dsl/choose_spec.rb @@ -23,6 +23,22 @@ module ChooseSpec running { @session.choose('does not exist') }.should raise_error(Capybara::ElementNotFound) end end + + context "with a locator that selects a hidden node" do + before do + Capybara.ignore_hidden_elements = false + end + + after do + Capybara.ignore_hidden_elements = true + end + + it "should raise an error" do + running do + @session.choose("hidden_gender_male") + end.should raise_error(Capybara::LocateHiddenElementError) + end + end end end -end \ No newline at end of file +end diff --git a/spec/dsl/click_button_spec.rb b/spec/dsl/click_button_spec.rb index 18564fe3..67143c35 100644 --- a/spec/dsl/click_button_spec.rb +++ b/spec/dsl/click_button_spec.rb @@ -144,6 +144,22 @@ module ClickButtonSpec end end + context "with a locator that selects a hidden node" do + before do + Capybara.ignore_hidden_elements = false + end + + after do + Capybara.ignore_hidden_elements = true + end + + it "should raise an error" do + running do + @session.click('Hidden button') + end.should raise_error(Capybara::LocateHiddenElementError) + end + end + it "should serialize and send GET forms" do @session.visit('/form') @session.click_button('med') diff --git a/spec/dsl/click_link_spec.rb b/spec/dsl/click_link_spec.rb index 60ebe63e..61241932 100644 --- a/spec/dsl/click_link_spec.rb +++ b/spec/dsl/click_link_spec.rb @@ -34,10 +34,26 @@ module ClickLinkSpec end end + context "with a locator that selects a hidden node" do + before do + Capybara.ignore_hidden_elements = false + end + + after do + Capybara.ignore_hidden_elements = true + end + + it "should raise an error" do + running do + @session.click('hidden link') + end.should raise_error(Capybara::LocateHiddenElementError) + end + end + it "should follow redirects" do @session.click_link('Redirect') @session.body.should include('You landed') end end end -end \ No newline at end of file +end diff --git a/spec/dsl/click_spec.rb b/spec/dsl/click_spec.rb index d689890b..2bd7ad0b 100644 --- a/spec/dsl/click_spec.rb +++ b/spec/dsl/click_spec.rb @@ -21,6 +21,23 @@ module ClickSpec end.should raise_error(Capybara::ElementNotFound) end end + + context "with a locator that selects a hidden node" do + before do + @session.visit('/with_html') + Capybara.ignore_hidden_elements = false + end + + after do + Capybara.ignore_hidden_elements = true + end + + it "should raise an error" do + running do + @session.click('hidden link') + end.should raise_error(Capybara::LocateHiddenElementError) + end + end end end -end \ No newline at end of file +end diff --git a/spec/dsl/fill_in_spec.rb b/spec/dsl/fill_in_spec.rb index cae12ac8..1792ca3e 100644 --- a/spec/dsl/fill_in_spec.rb +++ b/spec/dsl/fill_in_spec.rb @@ -60,6 +60,22 @@ module FillInSpec end.should raise_error(Capybara::ElementNotFound) end end + + context "with a locator that selects a hidden node" do + before do + Capybara.ignore_hidden_elements = false + end + + after do + Capybara.ignore_hidden_elements = true + end + + it "should raise an error" do + running do + @session.fill_in('First Name', :with => 'Blah blah') + end.should raise_error(Capybara::LocateHiddenElementError) + end + end end end -end \ No newline at end of file +end diff --git a/spec/dsl/locate_spec.rb b/spec/dsl/locate_spec.rb index b796b52a..d6f8af1a 100644 --- a/spec/dsl/locate_spec.rb +++ b/spec/dsl/locate_spec.rb @@ -22,6 +22,24 @@ module LocateSpec @session.locate(@xpath).value.should == 'John Smith' end + it "should return a visible node by default" do + @session.visit('/form') + @session.locate(Capybara::XPath.text_field('First Name')).should be_visible + end + + context "when ignore_hidden_elements is false" do + after do + Capybara.ignore_hidden_elements = true + end + it "should raise an exception hitting a hidden element" do + Capybara.ignore_hidden_elements = false + @session.visit('/form') + running do + @session.locate(Capybara::XPath.text_field('First Name')).should_not be_visible + end.should raise_error(Capybara::LocateHiddenElementError) + end + end + context "within a scope" do before do @session.visit('/with_scope') @@ -35,4 +53,4 @@ module LocateSpec end end end -end \ No newline at end of file +end diff --git a/spec/dsl/select_spec.rb b/spec/dsl/select_spec.rb index 083cb9a2..8aea8790 100644 --- a/spec/dsl/select_spec.rb +++ b/spec/dsl/select_spec.rb @@ -22,6 +22,22 @@ module SelectSpec running { @session.select('foo', :from => 'does not exist') }.should raise_error(Capybara::ElementNotFound) end end + + context "with a locator that selects a hidden node" do + before do + Capybara.ignore_hidden_elements = false + end + + after do + Capybara.ignore_hidden_elements = true + end + + it "should raise an error" do + running do + @session.select("Finish", :from => 'Locale') + end.should raise_error(Capybara::LocateHiddenElementError) + end + end end end -end \ No newline at end of file +end diff --git a/spec/dsl/uncheck_spec.rb b/spec/dsl/uncheck_spec.rb index 1e47acd6..b6a0382b 100644 --- a/spec/dsl/uncheck_spec.rb +++ b/spec/dsl/uncheck_spec.rb @@ -24,6 +24,22 @@ module UncheckSpec running { @session.uncheck('does not exist') }.should raise_error(Capybara::ElementNotFound) end end + + context "with a locator that selects a hidden node" do + before do + Capybara.ignore_hidden_elements = false + end + + after do + Capybara.ignore_hidden_elements = true + end + + it "should raise an error" do + running do + @session.uncheck('hidden_checked_checkbox') + end.should raise_error(Capybara::LocateHiddenElementError) + end + end end end -end \ No newline at end of file +end diff --git a/spec/views/form.erb b/spec/views/form.erb index c5aaa5c2..2f53520f 100644 --- a/spec/views/form.erb +++ b/spec/views/form.erb @@ -1,6 +1,26 @@

Form

+ +
+ + + + + + + + +
+

\ No newline at end of file