diff --git a/History.txt b/History.txt index c4938424..3e64dc88 100644 --- a/History.txt +++ b/History.txt @@ -1,3 +1,11 @@ +# Version 1.0.0 + +Release date: + +### Changed + +* Capybara now prefers visible elements over hidden elements, disable by setting Capybara.prefer_visible_elements = false + # Version 0.4.1 Release date: diff --git a/lib/capybara.rb b/lib/capybara.rb index 9ccb53de..7d43a6fd 100644 --- a/lib/capybara.rb +++ b/lib/capybara.rb @@ -14,7 +14,7 @@ module Capybara class << self attr_accessor :asset_root, :app_host, :run_server, :default_host attr_accessor :server_port, :server_boot_timeout - attr_accessor :default_selector, :default_wait_time, :ignore_hidden_elements + attr_accessor :default_selector, :default_wait_time, :ignore_hidden_elements, :prefer_visible_elements attr_accessor :save_and_open_page_path ## @@ -34,6 +34,7 @@ module Capybara # [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: CSS) # [default_wait_time = Integer] The number of seconds to wait for asynchronous processes to finish (Default: 2) # [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: false) + # [prefer_visible_elements = Boolean] Whether to prefer visible elements over hidden elements (Default: true) # # === DSL Options # @@ -212,6 +213,7 @@ Capybara.configure do |config| config.default_selector = :css config.default_wait_time = 2 config.ignore_hidden_elements = false + config.prefer_visible_elements = true end Capybara.register_driver :rack_test do |app| diff --git a/lib/capybara/node/finders.rb b/lib/capybara/node/finders.rb index 9f8b1e64..dcc8b2e7 100644 --- a/lib/capybara/node/finders.rb +++ b/lib/capybara/node/finders.rb @@ -138,16 +138,17 @@ module Capybara # def first(*args) options = extract_normalized_options(args) + found_elements = [] Capybara::Selector.normalize(*args).each do |path| find_in_base(path).each do |node| if matches_options(node, options) - return convert_element(node) + found_elements << convert_element(node) + return found_elements.last if not Capybara.prefer_visible_elements or node.visible? end end end - - nil + found_elements.first end protected diff --git a/lib/capybara/spec/session/first_spec.rb b/lib/capybara/spec/session/first_spec.rb index bcb83174..84f40df8 100644 --- a/lib/capybara/spec/session/first_spec.rb +++ b/lib/capybara/spec/session/first_spec.rb @@ -44,19 +44,52 @@ shared_examples_for "first" do context "with visible filter" do after { Capybara.ignore_hidden_elements = false } - it "should only find visible nodes" do - @session.first(:css, "a.visibility").should_not be_visible - @session.first(:css, "a.visibility", :visible => true).should be_visible + it "should only find visible nodes if true given" do + @session.first(:css, "a#invisible").should_not be_nil + @session.first(:css, "a#invisible", :visible => true).should be_nil Capybara.ignore_hidden_elements = true - @session.first(:css, "a.visibility").should be_visible + @session.first(:css, "a#invisible").should be_nil end - it "should only find invisible nodes" do + it "should include invisible nodes if false given" do Capybara.ignore_hidden_elements = true - @session.first(:css, "a.visibility", :visible => false).should_not be_visible + @session.first(:css, "a#invisible", :visible => false).should_not be_nil + @session.first(:css, "a#invisible").should be_nil end end + context "with prefer visible elements" do + it "should find invisible elements if no visible element exists" do + @session.first(:css, 'a#invisible')[:id].should == 'invisible' + end + + it "should prefer visible elements over invisible elements" do + @session.first(:css, 'a.visibility')[:id].should == 'visible' + end + + it "should return the first invisible element if no visible elements exist" do + @session.first(:css, 'a.hidden')[:id].should == 'first_invisble' + end + + it "find visible links normally" do + @session.first(:css, 'a#visible')[:id].should == 'visible' + end + end + + context "without prefer visible elements" do + before { Capybara.prefer_visible_elements = false } + + it "should find invisible elements if no visible element exists" do + @session.first(:css, 'a#invisible')[:id].should == 'invisible' + end + + it "should not prefer visible elements over invisible elements" do + @session.first(:css, 'a.visibility')[:id].should == 'invisible' + end + + after { Capybara.prefer_visible_elements = true } + end + context "within a scope" do before do @session.visit('/with_scope') diff --git a/lib/capybara/spec/views/with_html.erb b/lib/capybara/spec/views/with_html.erb index 1e55c087..fbc3a4c4 100644 --- a/lib/capybara/spec/views/with_html.erb +++ b/lib/capybara/spec/views/with_html.erb @@ -56,11 +56,15 @@
- hidden link + +
+ +
+
- visible link + visible link