more code cleanup

This commit is contained in:
Thomas Walpole 2018-01-13 13:06:03 -08:00
parent 63a12e7ba0
commit dfaf958ea7
24 changed files with 165 additions and 265 deletions

View File

@ -34,12 +34,9 @@ module Capybara
#
# Return the proc that Capybara will call to run the Rack application.
# The block returned receives a rack app, port, and host/ip and should run a Rack handler
# By default, Capybara will try to run webrick.
# By default, Capybara will try to use puma.
#
def server
raise ArgumentError, "Capybara#server no longer accepts a block" if block_given?
@server
end
attr_reader :server
##
#

View File

@ -27,13 +27,11 @@ module Capybara
# @return [String] Escaped text
#
def to_regexp(text, regexp_options = nil, exact = false)
if text.is_a?(Regexp)
text
else
escaped = Regexp.escape(normalize_whitespace(text))
escaped = "\\A#{escaped}\\z" if exact
Regexp.new(escaped, regexp_options)
end
return text if text.is_a?(Regexp)
escaped = Regexp.escape(normalize_whitespace(text))
escaped = "\\A#{escaped}\\z" if exact
Regexp.new(escaped, regexp_options)
end
##
@ -47,11 +45,8 @@ module Capybara
def inject_asset_host(html, asset_host = Capybara.asset_host)
if asset_host && Nokogiri::HTML(html).css("base").empty?
match = html.match(/<head[^<]*?>/)
if match
return html.clone.insert match.end(0), "<base href='#{asset_host}' />"
end
return html.clone.insert match.end(0), "<base href='#{asset_host}' />" if match
end
html
end
@ -66,11 +61,7 @@ module Capybara
# @param [Integer] count The number of items
#
def declension(singular, plural, count)
if count == 1
singular
else
plural
end
count == 1 ? singular : plural
end
if defined?(Process::CLOCK_MONOTONIC)

View File

@ -8,17 +8,14 @@ module Capybara
@child_node = node
node.synchronize do
match_results = super(node.session.current_scope, exact)
node.all(:xpath, XPath.ancestor) do |el|
match_results.include?(el)
end
node.all(:xpath, XPath.ancestor) { |el| match_results.include?(el) }
end
end
def description
child_query = @child_node && @child_node.instance_variable_get(:@query)
desc = super
if @child_node && (child_query = @child_node.instance_variable_get(:@query))
desc += " that is an ancestor of #{child_query.description}"
end
desc += " that is an ancestor of #{child_query.description}" if child_query
desc
end
end

View File

@ -31,11 +31,7 @@ module Capybara
# Returns false if query does not have any count options specified.
#
def expects_none?
if COUNT_KEYS.any? { |k| options.key? k }
matches_count?(0)
else
false
end
count_specified? ? matches_count?(0) : false
end
##
@ -52,7 +48,7 @@ module Capybara
return false if options[:maximum] && (Integer(options[:maximum]) < count)
return false if options[:minimum] && (Integer(options[:minimum]) > count)
return false if options[:between] && !options[:between].include?(count)
return true
true
end
##
@ -69,6 +65,10 @@ module Capybara
private
def count_specified?
COUNT_KEYS.any? { |k| options.key? k }
end
def count_message
message = "".dup
if options[:count]

View File

@ -19,11 +19,7 @@ module Capybara
def resolves_for?(session)
uri = ::Addressable::URI.parse(session.current_url)
uri.query = nil if uri && options[:ignore_query]
@actual_path = if options[:url]
uri.to_s
else
uri && uri.request_uri
end
@actual_path = options[:url] ? uri.to_s : uri && uri.request_uri
if @expected_path.is_a? Regexp
@actual_path.to_s.match(@expected_path)

View File

@ -2,11 +2,7 @@ module Capybara
module Queries
class MatchQuery < Capybara::Queries::SelectorQuery
def visible
if options.key?(:visible)
super
else
:all
end
options.key?(:visible) ? super : :all
end
private

View File

@ -13,17 +13,10 @@ module Capybara
@options = options.dup
super(@options)
self.session_options = session_options
@filter_block = filter_block
@selector = if args[0].is_a?(Symbol)
Selector.all.fetch(args.shift) do |selector_type|
raise ArgumentError, "Unknown selector type (:#{selector_type})"
end
else
Selector.all.values.find { |s| s.match?(args[0]) }
end
@selector = find_selector(args[0].is_a?(Symbol) ? args.shift : args[0])
@locator = args.shift
@selector ||= Selector.all[session_options.default_selector]
@filter_block = filter_block
warn "Unused parameters passed to #{self.class.name} : #{args}" unless args.empty?
@ -35,7 +28,7 @@ module Capybara
end
def name; selector.name; end
def label; selector.label or selector.name; end
def label; selector.label || selector.name; end
def description
@description = "".dup
@ -75,8 +68,7 @@ module Capybara
end
def exact?
return false unless supports_exact?
options.fetch(:exact, session_options.exact)
supports_exact? ? options.fetch(:exact, session_options.exact) : false
end
def match
@ -120,6 +112,15 @@ module Capybara
private
def find_selector(locator)
selector = if locator.is_a?(Symbol)
Selector.all.fetch(locator) { |sel_type| raise ArgumentError, "Unknown selector type (:#{sel_type})" }
else
Selector.all.values.find { |s| s.match?(locator) }
end
selector || Selector.all[session_options.default_selector]
end
def valid_keys
VALID_KEYS + custom_keys
end

View File

@ -8,7 +8,7 @@ module Capybara
@sibling_node = node
node.synchronize do
match_results = super(node.session.current_scope, exact)
node.all(:xpath, XPath.preceding_sibling.union(XPath.following_sibling)) do |el|
node.all(:xpath, XPath.preceding_sibling + XPath.following_sibling) do |el|
match_results.include?(el)
end
end
@ -16,9 +16,8 @@ module Capybara
def description
desc = super
if @sibling_node && (sibling_query = @sibling_node.instance_variable_get(:@query))
desc += " that is a sibling of #{sibling_query.description}"
end
sibling_query = @sibling_node && @sibling_node.instance_variable_get(:@query)
desc += " that is a sibling of #{sibling_query.description}" if sibling_query
desc
end
end

View File

@ -5,16 +5,22 @@ module Capybara
module Queries
class TextQuery < BaseQuery
def initialize(type = nil, expected_text, session_options:, **options) # rubocop:disable Style/OptionalArguments
@type = type
@type = Capybara.ignore_hidden_elements || Capybara.visible_text_only ? :visible : :all if @type.nil?
@expected_text = expected_text
@type = if type.nil?
Capybara.ignore_hidden_elements || Capybara.visible_text_only ? :visible : :all
else
type
end
@expected_text = if expected_text.is_a?(Regexp)
expected_text
else
Capybara::Helpers.normalize_whitespace(expected_text)
end
@options = options
super(@options)
self.session_options = session_options
unless @expected_text.is_a?(Regexp)
@expected_text = Capybara::Helpers.normalize_whitespace(@expected_text)
end
@search_regexp = Capybara::Helpers.to_regexp(@expected_text, nil, exact?)
assert_valid_keys
end

View File

@ -5,19 +5,15 @@ module Capybara
module Queries
class TitleQuery < BaseQuery
def initialize(expected_title, **options)
@expected_title = expected_title
@expected_title = expected_title.is_a?(Regexp) ? expected_title : Capybara::Helpers.normalize_whitespace(expected_title)
@options = options
super(@options)
unless @expected_title.is_a?(Regexp)
@expected_title = Capybara::Helpers.normalize_whitespace(@expected_title)
end
@search_regexp = Capybara::Helpers.to_regexp(@expected_title, nil, options.fetch(:exact, false))
assert_valid_keys
end
def resolves_for?(node)
@actual_title = node.title
@actual_title.match(@search_regexp)
(@actual_title = node.title).match(@search_regexp)
end
def failure_message

View File

@ -23,9 +23,9 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
form_element_types = %i[input select textarea]
form_elements_xpath = XPath.generate do |x|
xpath = x.descendant(*form_element_types).where(~x.attr(:form))
xpath = xpath.union(x.anywhere(*form_element_types).where(x.attr(:form) == native[:id])) if native[:id]
xpath.where(~x.attr(:disabled))
xpath = x.descendant(*form_element_types).where(!x.attr(:form))
xpath += x.anywhere(*form_element_types).where(x.attr(:form) == native[:id]) if native[:id]
xpath.where(!x.attr(:disabled))
end.to_s
native.xpath(form_elements_xpath).map do |field|
@ -88,17 +88,16 @@ private
merge_param!(params, field['name'].to_s, node.value.to_s)
end
elsif %w[submit image].include? field['type']
# TO DO identify the click button here (in document order, rather
# TODO: identify the click button here (in document order, rather
# than leaving until the end of the params)
elsif field['type'] == 'file'
if multipart?
file = \
if (value = field['value']).to_s.empty?
NilUploadedFile.new
else
mime_info = MiniMime.lookup_by_filename(value)
Rack::Test::UploadedFile.new(value, (mime_info && mime_info.content_type).to_s)
end
file = if (value = field['value']).to_s.empty?
NilUploadedFile.new
else
mime_info = MiniMime.lookup_by_filename(value)
Rack::Test::UploadedFile.new(value, (mime_info && mime_info.content_type).to_s)
end
merge_param!(params, field['name'].to_s, file)
else
merge_param!(params, field['name'].to_s, File.basename(field['value'].to_s))
@ -110,13 +109,11 @@ private
def add_select_param(field, params)
if field['multiple'] == 'multiple'
options = field.xpath(".//option[@selected]")
options.each do |option|
field.xpath(".//option[@selected]").each do |option|
merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s)
end
else
option = field.xpath(".//option[@selected]").first
option ||= field.xpath('.//option').first
option = field.xpath('.//option[@selected]').first || field.xpath('.//option').first
merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s) if option
end
end

View File

@ -26,42 +26,33 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
raise TypeError, "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}"
end
if radio?
set_radio(value)
elsif checkbox?
set_checkbox(value)
elsif input_field?
set_input(value)
elsif textarea?
native['_capybara_raw_value'] = value.to_s
if radio? then set_radio(value)
elsif checkbox? then set_checkbox(value)
elsif input_field? then set_input(value)
elsif textarea? then native['_capybara_raw_value'] = value.to_s
end
end
def select_option
return if disabled?
if select_node['multiple'] != 'multiple'
select_node.find_xpath(".//option[@selected]").each { |node| node.native.remove_attribute("selected") }
end
deselect_options unless select_node.multiple?
native["selected"] = 'selected'
end
def unselect_option
if select_node['multiple'] != 'multiple'
raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box."
end
raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box." unless select_node.multiple?
native.remove_attribute('selected')
end
def click(keys = [], offset = {})
raise ArgumentError, "The RackTest driver does not support click options" unless keys.empty? && offset.empty?
if tag_name == 'a' && !self[:href].nil?
if link?
follow_link
elsif (tag_name == 'input' and %w[submit image].include?(type)) or
(tag_name == 'button' and [nil, "submit"].include?(type))
elsif submits?
associated_form = form
Capybara::RackTest::Form.new(driver, associated_form).submit(self) if associated_form
elsif tag_name == 'input' and %w[checkbox radio].include?(type)
elsif checkable?
set(!checked?)
elsif tag_name == 'label'
click_label
@ -85,10 +76,12 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
end
def disabled?
return true if string_node.disabled?
if %w[option optgroup].include? tag_name
string_node.disabled? || find_xpath("parent::*[self::optgroup or self::select]")[0].disabled?
find_xpath("parent::*[self::optgroup or self::select]")[0].disabled?
else
string_node.disabled? || !find_xpath("parent::fieldset[@disabled] | ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]").empty?
!find_xpath("parent::fieldset[@disabled] | ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]").empty?
end
end
@ -126,6 +119,10 @@ protected
private
def deselect_options
select_node.find_xpath(".//option[@selected]").each { |node| node.native.remove_attribute("selected") }
end
def string_node
@string_node ||= Capybara::Node::Simple.new(native)
end
@ -141,10 +138,10 @@ private
def form
if native[:form]
native.xpath("//form[@id='#{native[:form]}']").first
native.xpath("//form[@id='#{native[:form]}']")
else
native.ancestors('form').first
end
native.ancestors('form')
end.first
end
def set_radio(_value) # rubocop:disable Naming/AccessorMethodName
@ -192,16 +189,28 @@ private
def click_label
labelled_control = if native[:for]
find_xpath("//input[@id='#{native[:for]}']").first
find_xpath("//input[@id='#{native[:for]}']")
else
find_xpath(".//input").first
end
find_xpath(".//input")
end.first
if labelled_control && (labelled_control.checkbox? || labelled_control.radio?)
labelled_control.set(!labelled_control.checked?)
end
end
def link?
tag_name == 'a' && !self[:href].nil?
end
def submits?
(tag_name == 'input' and %w[submit image].include?(type)) || (tag_name == 'button' and [nil, "submit"].include?(type))
end
def checkable?
tag_name == 'input' and %w[checkbox radio].include?(type)
end
protected
def checkbox?

View File

@ -92,8 +92,7 @@ module Capybara
end
if @query.options[:between]
max = Integer(@query.options[:between].max)
min = Integer(@query.options[:between].min)
min, max = @query.options[:between].minmax
loop do
break if @result_cache.size > max
@result_cache << @results_enum.next
@ -112,10 +111,10 @@ module Capybara
def failure_message
message = @query.failure_message
if count > 0
message << ", found #{count} #{Capybara::Helpers.declension("match", "matches", count)}: " << full_results.map(&:text).map(&:inspect).join(", ")
else
if count.zero?
message << " but there were no matches"
else
message << ", found #{count} #{Capybara::Helpers.declension("match", "matches", count)}: " << full_results.map(&:text).map(&:inspect).join(", ")
end
unless rest.empty?
elements = rest.map { |el| el.text rescue "<<ERROR>>" }.map(&:inspect).join(", ")

View File

@ -16,10 +16,8 @@ module Capybara
end
class CapybaraEvaluator
def initialize(actual, matcher1, matcher2)
def initialize(actual)
@actual = actual
@matcher1 = matcher1
@matcher2 = matcher2
@match_results = Hash.new { |h, matcher| h[matcher] = matcher.matches?(@actual) }
end
@ -36,7 +34,7 @@ module Capybara
private
def match(_expected, actual)
@evaluator = CapybaraEvaluator.new(actual, matcher_1, matcher_2)
@evaluator = CapybaraEvaluator.new(actual)
syncer = sync_element(actual)
begin
syncer.synchronize do
@ -64,7 +62,7 @@ module Capybara
private
def match(_expected, actual)
@evaluator = CapybaraEvaluator.new(actual, matcher_1, matcher_2)
@evaluator = CapybaraEvaluator.new(actual)
syncer = sync_element(actual)
begin
syncer.synchronize do

View File

@ -135,15 +135,9 @@ module Capybara
end
class HaveText < Matcher
attr_reader :type, :content, :options
def initialize(*args)
@args = args.dup
# are set just for backwards compatability
@type = args.shift if args.first.is_a?(Symbol)
@content = args.shift
@options = args.first.is_a?(Hash) ? args.first : {}
@content = args[0].is_a?(Symbol) ? args[1] : args[0]
end
def matches?(actual)
@ -155,7 +149,7 @@ module Capybara
end
def description
"text #{format(content)}"
"text #{format(@content)}"
end
def format(content)
@ -165,8 +159,6 @@ module Capybara
end
class HaveTitle < Matcher
attr_reader :title
def initialize(*args)
@args = args
@ -183,17 +175,13 @@ module Capybara
end
def description
"have title #{title.inspect}"
"have title #{@title.inspect}"
end
end
class HaveCurrentPath < Matcher
attr_reader :current_path
def initialize(*args)
@args = args
# are set just for backwards compatability
@current_path = args.first
end
@ -206,7 +194,7 @@ module Capybara
end
def description
"have current path #{current_path.inspect}"
"have current path #{@current_path.inspect}"
end
end

View File

@ -2,8 +2,8 @@ module Capybara
class Selector
class CSS
def self.escape(str)
out = "".dup
value = str.dup
out = "".dup
out << value.slice!(0...1) if value =~ /^[-_]/
out << (value[0] =~ NMSTART ? value.slice!(0...1) : escape_char(value.slice!(0...1)))
out << value.gsub(/[^a-zA-Z0-9_-]/) { |c| escape_char c }

View File

@ -26,13 +26,9 @@ module Capybara
end
def description(**options)
options_with_defaults = options.dup
filters.each do |name, filter|
options_with_defaults[name] = filter.default if filter.default? && !options_with_defaults.key?(name)
end
opts = options_with_defaults(options)
@descriptions.map do |desc|
desc.call(options_with_defaults).to_s
desc.call(opts).to_s
end.join
end
@ -64,6 +60,14 @@ module Capybara
private
def options_with_defaults(options)
options = options.dup
filters.each do |name, filter|
options[name] = filter.default if filter.default? && !options.key?(name)
end
options
end
def add_filter(name, filter_class, *types, **options, &block)
types.each { |k| options[k] = true }
filters[name] = filter_class.new(name, block, options)

View File

@ -8,32 +8,15 @@ module Capybara
class ExpressionFilter < Base
def apply_filter(expr, value)
return expr if skip?(value)
unless valid_value?(value)
msg = "Invalid value #{value.inspect} passed to expression filter #{@name} - "
if default?
warn msg + "defaulting to #{default}"
value = default
else
warn msg + "skipping"
return expr
end
end
raise "ArgumentError", "Invalid value #{value.inspect} passed to expression filter #{@name}" unless valid_value?(value)
@block.call(expr, value)
end
end
class IdentityExpressionFilter < ExpressionFilter
def initialize; end
def default?
false
end
def apply_filter(expr, _value)
return expr
end
def default?; false; end
def apply_filter(expr, _value); expr; end
end
end
end

View File

@ -8,18 +8,7 @@ module Capybara
class NodeFilter < Base
def matches?(node, value)
return true if skip?(value)
unless valid_value?(value)
msg = "Invalid value #{value.inspect} passed to filter #{@name} - "
if default?
warn msg + "defaulting to #{default}"
value = default
else
warn msg + "skipping"
return true
end
end
raise ArgumentError, "Invalid value #{value.inspect} passed to filter #{@name}" unless valid_value?(value)
@block.call(node, value)
end
end

View File

@ -152,7 +152,6 @@ module Capybara
def call(locator, **options)
if format
# @expression.call(locator, options.select {|k,v| @expression_filters.include?(k)})
@expression.call(locator, options)
else
warn "Selector has no format"
@ -265,13 +264,7 @@ module Capybara
end
def find_by_class_attr(classes)
if classes
Array(classes).map do |klass|
XPath.attr(:class).contains_word(klass)
end.reduce(:&)
else
nil
end
Array(classes).map { |klass| XPath.attr(:class).contains_word(klass) }.reduce(:&)
end
end
end

View File

@ -38,12 +38,10 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
# Array => an array of keys to send before the value being set, e.g. [[:command, 'a'], :backspace]
def set(value, **options)
raise ArgumentError, "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}" if value.is_a?(Array) && !multiple?
tag_name = self.tag_name
type = self[:type]
case tag_name
when 'input'
case type
case self[:type]
when 'radio'
click
when 'checkbox'
@ -123,55 +121,38 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
end
def hover
scroll_if_needed do
driver.browser.action.move_to(native).perform
end
scroll_if_needed { driver.browser.action.move_to(native).perform }
end
def drag_to(element)
scroll_if_needed do
driver.browser.action.drag_and_drop(native, element.native).perform
end
scroll_if_needed { driver.browser.action.drag_and_drop(native, element.native).perform }
end
def tag_name
native.tag_name.downcase
end
def visible?
displayed = native.displayed?
displayed and displayed != "false"
end
def selected?
selected = native.selected?
selected and selected != "false"
end
def visible?; boolean_attr(native.displayed?); end
def readonly?; boolean_attr(self[:readonly]); end
def multiple?; boolean_attr(self[:multiple]); end
def selected?; boolean_attr(native.selected?); end
alias :checked? :selected?
def disabled?
return true unless native.enabled?
# workaround for selenium-webdriver/geckodriver reporting elements as enabled when they are nested in disabling elements
if driver.marionette?
if %w[option optgroup].include? tag_name
!native.enabled? || find_xpath("parent::*[self::optgroup or self::select]")[0].disabled?
find_xpath("parent::*[self::optgroup or self::select]")[0].disabled?
else
!native.enabled? || !find_xpath("parent::fieldset[@disabled] | ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]").empty?
!find_xpath("parent::fieldset[@disabled] | ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]").empty?
end
else
!native.enabled?
false
end
end
def readonly?
readonly = self[:readonly]
readonly and readonly != "false"
end
def multiple?
multiple = self[:multiple]
multiple and multiple != "false"
end
def content_editable?
native.attribute('isContentEditable')
end
@ -189,34 +170,31 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
end
def path
path = find_xpath('ancestor::*').reverse
path.unshift self
path = find_xpath(XPath.ancestor_or_self).reverse
result = []
while (node = path.shift)
parent = path.first
selector = node.tag_name
if parent
siblings = parent.find_xpath(node.tag_name)
if siblings.size == 1
result.unshift node.tag_name
else
index = siblings.index(node)
result.unshift "#{node.tag_name}[#{index + 1}]"
end
else
result.unshift node.tag_name
selector += "[#{siblings.index(node) + 1}]" unless siblings.size == 1
end
result.push selector
end
'/' + result.join('/')
'/' + result.reverse.join('/')
end
private
def boolean_attr(val)
val and val != "false"
end
# a reference to the select node if this is an option node
def select_node
find_xpath('./ancestor::select[1]').first
find_xpath(XPath.ancestor(:select)[1]).first
end
def set_text(value, clear: nil, **)
@ -242,7 +220,7 @@ private
def scroll_if_needed
yield
rescue ::Selenium::WebDriver::Error::MoveTargetOutOfBoundsError
script = <<-JS
script = <<-'JS'
try {
arguments[0].scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'});
} catch(e) {

View File

@ -81,7 +81,7 @@ module Capybara
@app = app
if block_given?
raise "A configuration block is only accepted when Capybara.threadsafe == true" unless Capybara.threadsafe
yield config if block_given?
yield config
end
@server = if config.run_server and @app and driver.needs_server?
Capybara::Server.new(@app, config.server_port, config.server_host, config.server_errors).boot
@ -195,6 +195,7 @@ module Capybara
# Addressable doesn't support opaque URIs - we want nil here
return nil if uri.scheme == "about"
path = uri.path
path if path && !path.empty?
end
@ -351,9 +352,7 @@ module Capybara
# @param [String] locator Id or legend of the fieldset
#
def within_fieldset(locator)
within :fieldset, locator do
yield
end
within(:fieldset, locator) { yield }
end
##
@ -363,9 +362,7 @@ module Capybara
# @param [String] locator Id or caption of the table
#
def within_table(locator)
within :table, locator do
yield
end
within(:table, locator) { yield }
end
##
@ -682,9 +679,9 @@ module Capybara
# @return [String] the path to which the file was saved
#
def save_page(path = nil)
path = prepare_path(path, 'html')
File.write(path, Capybara::Helpers.inject_asset_host(body, config.asset_host), mode: 'wb')
path
prepare_path(path, 'html').tap do |p|
File.write(p, Capybara::Helpers.inject_asset_host(body, config.asset_host), mode: 'wb')
end
end
##
@ -698,8 +695,7 @@ module Capybara
# @param [String] path the path to where it should be saved
#
def save_and_open_page(path = nil)
path = save_page(path)
open_file(path)
save_page(path).tap { |p| open_file(p) }
end
##
@ -714,9 +710,7 @@ module Capybara
# @param [Hash] options a customizable set of options
# @return [String] the path to which the file was saved
def save_screenshot(path = nil, **options)
path = prepare_path(path, 'png')
driver.save_screenshot(path, options)
path
prepare_path(path, 'png').tap { |p| driver.save_screenshot(p, options) }
end
##
@ -732,9 +726,8 @@ module Capybara
#
def save_and_open_screenshot(path = nil, **options)
# rubocop:disable Lint/Debugger
path = save_screenshot(path, options)
save_screenshot(path, options).tap { |p| open_file(p) }
# rubocop:enable Lint/Debugger
open_file(path)
end
def document
@ -760,8 +753,7 @@ module Capybara
def current_scope
scope = scopes.last
scope = document if [nil, :frame].include? scope
scope
[nil, :frame].include?(scope) ? document : scope
end
##
@ -826,14 +818,11 @@ module Capybara
require "launchy"
Launchy.open(path)
rescue LoadError
warn "File saved to #{path}."
warn "Please install the launchy gem to open the file automatically."
warn "File saved to #{path}.\nPlease install the launchy gem to open the file automatically."
end
def prepare_path(path, extension)
path = File.expand_path(path || default_fn(extension), config.save_path)
FileUtils.mkdir_p(File.dirname(path))
path
File.expand_path(path || default_fn(extension), config.save_path).tap { |p| FileUtils.mkdir_p(File.dirname(p)) }
end
def default_fn(extension)

View File

@ -35,10 +35,10 @@ Capybara::SpecHelper.spec '#find_field' do
end.to raise_error(Capybara::ElementNotFound)
end
it "should warn if filter option is invalid" do
expect_any_instance_of(Kernel).to receive(:warn).
with('Invalid value nil passed to filter disabled - defaulting to false')
@session.find_field('Dog', disabled: nil)
it "should raise error if filter option is invalid" do
expect do
@session.find_field('Dog', disabled: nil)
end.to raise_error ArgumentError, "Invalid value nil passed to filter disabled"
end
context "with :exact option" do

View File

@ -34,14 +34,8 @@ Capybara::SpecHelper.spec '#save_and_open_screenshot' do
it 'prints out a correct warning message', requires: [:screenshot] do
file_path = File.join(Dir.tmpdir, 'test.png')
allow(@session).to receive(:require).with('launchy').and_raise(LoadError)
allow(@session).to receive(:warn)
expect(@session).to receive(:warn).with("File saved to #{file_path}.\nPlease install the launchy gem to open the file automatically.")
@session.save_and_open_screenshot(file_path)
expect(@session).to have_received(:warn).
with("File saved to #{file_path}.")
expect(@session).to have_received(:warn).
with('Please install the launchy gem to open the file automatically.')
end
end
end