mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
#first now raises when no matching elements
This commit is contained in:
parent
60a75e6cc9
commit
b6be01daf3
7 changed files with 64 additions and 50 deletions
|
@ -1,6 +1,14 @@
|
|||
# Version 3.0.0
|
||||
|
||||
Release date: unreleased
|
||||
|
||||
### Added
|
||||
|
||||
* Ruby 2.2+ required
|
||||
* RSpec 2.x no longer supported
|
||||
* Deprecated methods removed
|
||||
* `first` now raises ElementNotFound by default instead of returning nil, when no matches are found - Issue #1507
|
||||
|
||||
# Version 2.17.0
|
||||
Release date: 2018-01-02
|
||||
|
||||
|
@ -244,6 +252,7 @@ Release date: 2016-10-05
|
|||
Release date: 2016-09-29
|
||||
|
||||
### Fixed
|
||||
|
||||
* :label built-in selector finds nested label/control by control id if the label has no 'for' attribute [Thomas Walpole]
|
||||
* Warning issued if an unknown selector type is specified [Thomas Walpole]
|
||||
|
||||
|
|
|
@ -51,8 +51,6 @@ module Capybara
|
|||
# See {Capybara.configure}
|
||||
# @!method always_include_port
|
||||
# See {Capybara.configure}
|
||||
# @!method wait_on_first_by_default
|
||||
# See {Capybara.configure}
|
||||
SessionConfig::OPTIONS.each do |method|
|
||||
def_delegators :config, method, "#{method}="
|
||||
end
|
||||
|
@ -79,7 +77,6 @@ module Capybara
|
|||
# [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: true)
|
||||
# [automatic_reload = Boolean] Whether to automatically reload elements as Capybara is waiting (Default: true)
|
||||
# [save_path = String] Where to put pages saved through save_(page|screenshot), save_and_open_(page|screenshot) (Default: Dir.pwd)
|
||||
# [wait_on_first_by_default = Boolean] Whether Node#first defaults to Capybara waiting behavior for at least 1 element to match (Default: false)
|
||||
# [automatic_label_click = Boolean] Whether Node#choose, Node#check, Node#uncheck will attempt to click the associated label element if the checkbox/radio button are non-visible (Default: false)
|
||||
# [enable_aria_label = Boolean] Whether fields, links, and buttons will match against aria-label attribute (Default: false)
|
||||
# [reuse_server = Boolean] Reuse the server thread between multiple sessions using the same app object (Default: true)
|
||||
|
@ -464,7 +461,6 @@ Capybara.configure do |config|
|
|||
config.raise_server_errors = true
|
||||
config.server_errors = [StandardError]
|
||||
config.visible_text_only = false
|
||||
config.wait_on_first_by_default = false
|
||||
config.automatic_label_click = false
|
||||
config.enable_aria_label = false
|
||||
config.reuse_server = true
|
||||
|
|
|
@ -271,11 +271,7 @@ module Capybara
|
|||
##
|
||||
#
|
||||
# Find the first element on the page matching the given selector
|
||||
# and options, or nil if no element matches. By default no waiting
|
||||
# behavior occurs, however if {Capybara.wait_on_first_by_default} is set to true
|
||||
# it will trigger Capybara's waiting behavior for a minimum of 1 matching element to be found and
|
||||
# return the first. Waiting behavior can also be triggered by passing in any of the count
|
||||
# expectation options.
|
||||
# and options. Will raise an error if no matching element is found
|
||||
#
|
||||
# @overload first([kind], locator, options)
|
||||
# @param [:css, :xpath] kind The type of selector
|
||||
|
@ -283,12 +279,11 @@ module Capybara
|
|||
# @param [Hash] options Additional options; see {#all}
|
||||
# @return [Capybara::Node::Element] The found element or nil
|
||||
#
|
||||
def first(*args, **options, &optional_filter_block)
|
||||
if session_options.wait_on_first_by_default
|
||||
def first(*args, allow_nil: false, **options, &optional_filter_block)
|
||||
options = {minimum: 1}.merge(options)
|
||||
end
|
||||
all(*args, **options, &optional_filter_block).first
|
||||
rescue Capybara::ExpectationNotMet
|
||||
rescue Capybara::ElementNotFound
|
||||
raise unless allow_nil
|
||||
nil
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'delegate'
|
|||
module Capybara
|
||||
class SessionConfig
|
||||
OPTIONS = [:always_include_port, :run_server, :default_selector, :default_max_wait_time, :ignore_hidden_elements,
|
||||
:automatic_reload, :match, :exact, :exact_text, :raise_server_errors, :visible_text_only, :wait_on_first_by_default,
|
||||
:automatic_reload, :match, :exact, :exact_text, :raise_server_errors, :visible_text_only,
|
||||
:automatic_label_click, :enable_aria_label, :save_path, :exact_options, :asset_host, :default_host, :app_host,
|
||||
:save_and_open_page_path, :server_host, :server_port, :server_errors]
|
||||
|
||||
|
@ -31,8 +31,6 @@ module Capybara
|
|||
# See {Capybara.configure}
|
||||
#@!method visible_text_only
|
||||
# See {Capybara.configure}
|
||||
#@!method wait_on_first_by_default
|
||||
# See {Capybara.configure}
|
||||
#@!method automatic_label_click
|
||||
# See {Capybara.configure}
|
||||
#@!method enable_aria_label
|
||||
|
|
|
@ -9,8 +9,14 @@ Capybara::SpecHelper.spec '#first' do
|
|||
expect(@session.first("//input[@id='test_field']").value).to eq('monkey')
|
||||
end
|
||||
|
||||
it "should return nil when nothing was found" do
|
||||
expect(@session.first('//div[@id="nosuchthing"]')).to be_nil
|
||||
it "should raise ElementNotFound when nothing was found" do
|
||||
expect do
|
||||
@session.first('//div[@id="nosuchthing"]')
|
||||
end.to raise_error Capybara::ElementNotFound
|
||||
end
|
||||
|
||||
it "should return nil when nothing was found if count options allow no results" do
|
||||
expect(@session.first('//div[@id="nosuchthing"]', minimum: 0)).to be_nil
|
||||
end
|
||||
|
||||
it "should accept an XPath instance" do
|
||||
|
@ -22,7 +28,7 @@ Capybara::SpecHelper.spec '#first' do
|
|||
|
||||
it "should warn when unused parameters are passed" do
|
||||
expect_any_instance_of(Kernel).to receive(:warn).with(/Unused parameters passed.*unused text/)
|
||||
@session.first(:css, '.header h2', 'unused text')
|
||||
@session.first(:css, 'h1', 'unused text')
|
||||
end
|
||||
|
||||
context "with css selectors" do
|
||||
|
@ -49,40 +55,52 @@ Capybara::SpecHelper.spec '#first' do
|
|||
|
||||
context "with visible filter" do
|
||||
it "should only find visible nodes when true" do
|
||||
expect(@session.first(:css, "a#invisible", visible: true)).to be_nil
|
||||
expect do
|
||||
@session.first(:css, "a#invisible", visible: true)
|
||||
end.to raise_error Capybara::ElementNotFound
|
||||
end
|
||||
|
||||
it "should find nodes regardless of whether they are invisible when false" do
|
||||
expect(@session.first(:css, "a#invisible", visible: false)).not_to be_nil
|
||||
expect(@session.first(:css, "a#invisible", visible: false, text: 'hidden link')).not_to be_nil
|
||||
expect(@session.first(:css, "a#visible", visible: false)).not_to be_nil
|
||||
expect(@session.first(:css, "a#invisible", visible: false)).to be
|
||||
expect(@session.first(:css, "a#invisible", visible: false, text: 'hidden link')).to be
|
||||
expect(@session.first(:css, "a#visible", visible: false)).to be
|
||||
end
|
||||
|
||||
it "should find nodes regardless of whether they are invisible when :all" do
|
||||
expect(@session.first(:css, "a#invisible", visible: :all)).not_to be_nil
|
||||
expect(@session.first(:css, "a#invisible", visible: :all, text: 'hidden link')).not_to be_nil
|
||||
expect(@session.first(:css, "a#visible", visible: :all)).not_to be_nil
|
||||
expect(@session.first(:css, "a#invisible", visible: :all)).to be
|
||||
expect(@session.first(:css, "a#invisible", visible: :all, text: 'hidden link')).to be
|
||||
expect(@session.first(:css, "a#visible", visible: :all)).to be
|
||||
end
|
||||
|
||||
it "should find only hidden nodes when :hidden" do
|
||||
expect(@session.first(:css, "a#invisible", visible: :hidden)).not_to be_nil
|
||||
expect(@session.first(:css, "a#invisible", visible: :hidden, text: 'hidden link')).not_to be_nil
|
||||
expect(@session.first(:css, "a#invisible", visible: :hidden, text: 'not hidden link')).to be_nil
|
||||
expect(@session.first(:css, "a#visible", visible: :hidden)).to be_nil
|
||||
expect(@session.first(:css, "a#invisible", visible: :hidden)).to be
|
||||
expect(@session.first(:css, "a#invisible", visible: :hidden, text: 'hidden link')).to be
|
||||
expect do
|
||||
@session.first(:css, "a#invisible", visible: :hidden, text: 'not hidden link')
|
||||
end.to raise_error Capybara::ElementNotFound
|
||||
expect do
|
||||
@session.first(:css, "a#visible", visible: :hidden)
|
||||
end.to raise_error Capybara::ElementNotFound
|
||||
end
|
||||
|
||||
it "should find only visible nodes when :visible" do
|
||||
expect(@session.first(:css, "a#invisible", visible: :visible)).to be_nil
|
||||
expect(@session.first(:css, "a#invisible", visible: :visible, text: 'hidden link')).to be_nil
|
||||
expect(@session.first(:css, "a#visible", visible: :visible)).not_to be_nil
|
||||
expect do
|
||||
@session.first(:css, "a#invisible", visible: :visible)
|
||||
end.to raise_error Capybara::ElementNotFound
|
||||
expect do
|
||||
@session.first(:css, "a#invisible", visible: :visible, text: 'hidden link')
|
||||
end.to raise_error Capybara::ElementNotFound
|
||||
expect(@session.first(:css, "a#visible", visible: :visible)).to be
|
||||
end
|
||||
|
||||
it "should default to Capybara.ignore_hidden_elements" do
|
||||
Capybara.ignore_hidden_elements = true
|
||||
expect(@session.first(:css, "a#invisible")).to be_nil
|
||||
expect do
|
||||
@session.first(:css, "a#invisible")
|
||||
end.to raise_error Capybara::ElementNotFound
|
||||
Capybara.ignore_hidden_elements = false
|
||||
expect(@session.first(:css, "a#invisible")).not_to be_nil
|
||||
expect(@session.first(:css, "a")).not_to be_nil
|
||||
expect(@session.first(:css, "a#invisible")).to be
|
||||
expect(@session.first(:css, "a")).to be
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -93,35 +111,34 @@ Capybara::SpecHelper.spec '#first' do
|
|||
|
||||
it "should find the first element using the given locator" do
|
||||
@session.within(:xpath, "//div[@id='for_bar']") do
|
||||
expect(@session.first('.//form')).not_to be_nil
|
||||
expect(@session.first('.//form')).to be
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with Capybara.wait_on_first_by_default", requires: [:js] do
|
||||
context "waiting behavior", requires: [:js] do
|
||||
before do
|
||||
@session.visit('/with_js')
|
||||
end
|
||||
|
||||
it "should not wait if false" do
|
||||
Capybara.wait_on_first_by_default = false
|
||||
it "should not wait if minimum: 0" do
|
||||
@session.click_link('clickable')
|
||||
expect(@session.first(:css, 'a#has-been-clicked')).to be_nil
|
||||
expect(@session.first(:css, 'a#has-been-clicked', minimum: 0)).to be_nil
|
||||
end
|
||||
|
||||
it "should wait for at least one match if true" do
|
||||
Capybara.wait_on_first_by_default = true
|
||||
it "should wait for at least one match by default" do
|
||||
Capybara.using_wait_time(3) do
|
||||
@session.click_link('clickable')
|
||||
expect(@session.first(:css, 'a#has-been-clicked')).not_to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it "should return nil after waiting if no match" do
|
||||
Capybara.wait_on_first_by_default = true
|
||||
Capybara.using_wait_time(3) do
|
||||
it "should return nil after waiting if no match and allow_nil is true" do
|
||||
@session.click_link('clickable')
|
||||
expect(@session.first(:css, 'a#not-a-real-link')).to be_nil
|
||||
start_time = Time.now
|
||||
Capybara.using_wait_time(3) do
|
||||
expect(@session.first(:css, 'a#not-a-real-link', allow_nil: true)).to be_nil
|
||||
expect(Time.now-start_time).to be > 3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,7 +30,6 @@ module Capybara
|
|||
Capybara.raise_server_errors = true
|
||||
Capybara.visible_text_only = false
|
||||
Capybara.match = :smart
|
||||
Capybara.wait_on_first_by_default = false
|
||||
Capybara.enable_aria_label = false
|
||||
reset_threadsafe
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ RSpec.describe Capybara::SessionConfig do
|
|||
session = Capybara::Session.new(:rack_test, TestApp)
|
||||
[:default_host, :app_host, :save_and_open_page_path,
|
||||
:always_include_port, :run_server, :default_selector, :default_max_wait_time, :ignore_hidden_elements,
|
||||
:automatic_reload, :match, :exact, :raise_server_errors, :visible_text_only, :wait_on_first_by_default,
|
||||
:automatic_reload, :match, :exact, :raise_server_errors, :visible_text_only,
|
||||
:automatic_label_click, :enable_aria_label,
|
||||
:save_path, :exact_options, :asset_host].each do |m|
|
||||
expect(session.config.public_send(m)).to eq Capybara.public_send(m)
|
||||
|
|
Loading…
Add table
Reference in a new issue