mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
Add ability to modify a selector
This commit is contained in:
parent
710bc5dca9
commit
46c334cb8a
3 changed files with 99 additions and 21 deletions
|
@ -37,24 +37,24 @@ module Capybara
|
||||||
#
|
#
|
||||||
# === Configurable options
|
# === Configurable options
|
||||||
#
|
#
|
||||||
# [app_host = String] The default host to use when giving a relative URL to visit
|
# [app_host = String] The default host to use when giving a relative URL to visit
|
||||||
# [always_include_port = Boolean] Whether the Rack server's port should automatically be inserted into every visited URL (Default: false)
|
# [always_include_port = Boolean] Whether the Rack server's port should automatically be inserted into every visited URL (Default: false)
|
||||||
# [asset_host = String] Where dynamic assets are hosted - will be prepended to relative asset locations if present (Default: nil)
|
# [asset_host = String] Where dynamic assets are hosted - will be prepended to relative asset locations if present (Default: nil)
|
||||||
# [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
|
# [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
|
||||||
# [raise_server_errors = Boolean] Should errors raised in the server be raised in the tests? (Default: true)
|
# [raise_server_errors = Boolean] Should errors raised in the server be raised in the tests? (Default: true)
|
||||||
# [server_errors = Array\<Class\>] Error classes that should be raised in the tests if they are raised in the server and Capybara.raise_server_errors is true (Default: [StandardError])
|
# [server_errors = Array\<Class\>] Error classes that should be raised in the tests if they are raised in the server and Capybara.raise_server_errors is true (Default: [StandardError])
|
||||||
# [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: :css)
|
# [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: :css)
|
||||||
# [default_max_wait_time = Numeric] The maximum number of seconds to wait for asynchronous processes to finish (Default: 2)
|
# [default_max_wait_time = Numeric] The maximum 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: true)
|
# [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)
|
# [automatic_reload = Boolean] Whether to automatically reload elements as Capybara is waiting (Default: true)
|
||||||
# [save_and_open_page_path = String] Where to put pages saved through save_and_open_page (Default: Dir.pwd)
|
# [save_and_open_page_path = String] Where to put pages saved through save_and_open_page (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)
|
# [wait_on_first_by_default = Boolean] Whether Node#first defaults to Capybara waiting behavior for at least 1 element to match (Default: false)
|
||||||
# === DSL Options
|
# === DSL Options
|
||||||
#
|
#
|
||||||
# when using capybara/dsl, the following options are also available:
|
# when using capybara/dsl, the following options are also available:
|
||||||
#
|
#
|
||||||
# [default_driver = Symbol] The name of the driver to use by default. (Default: :rack_test)
|
# [default_driver = Symbol] The name of the driver to use by default. (Default: :rack_test)
|
||||||
# [javascript_driver = Symbol] The name of a driver to use for JavaScript enabled tests. (Default: :selenium)
|
# [javascript_driver = Symbol] The name of a driver to use for JavaScript enabled tests. (Default: :selenium)
|
||||||
#
|
#
|
||||||
def configure
|
def configure
|
||||||
yield self
|
yield self
|
||||||
|
@ -109,6 +109,23 @@ module Capybara
|
||||||
Capybara::Selector.add(name, &block)
|
Capybara::Selector.add(name, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
#
|
||||||
|
# Modify a selector previously craeated by {Capybara.add_selector}.
|
||||||
|
# For example modifying the :button selector to also find divs styled
|
||||||
|
# to look like buttons might look like this
|
||||||
|
#
|
||||||
|
# Capybara.modfiy_selector(:button) do
|
||||||
|
# xpath { |locator| XPath::HTML.button(locator).or(XPath::css('div.btn')[XPath::string.n.is(locator)]) }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @param [Symbol] name The name of the selector to modify
|
||||||
|
# @yield A block executed in the context of the existing {Capybara::Selector}
|
||||||
|
#
|
||||||
|
def modify_selector(name, &block)
|
||||||
|
Capybara::Selector.update(name, &block)
|
||||||
|
end
|
||||||
|
|
||||||
def drivers
|
def drivers
|
||||||
@drivers ||= {}
|
@drivers ||= {}
|
||||||
end
|
end
|
||||||
|
@ -305,13 +322,13 @@ module Capybara
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# @deprecated Use default_max_wait_time instead
|
# @deprecated Use default_max_wait_time instead
|
||||||
def default_wait_time
|
def default_wait_time
|
||||||
deprecate('default_wait_time', 'default_max_wait_time', true)
|
deprecate('default_wait_time', 'default_max_wait_time', true)
|
||||||
default_max_wait_time
|
default_max_wait_time
|
||||||
end
|
end
|
||||||
|
|
||||||
# @deprecated Use default_max_wait_time= instead
|
# @deprecated Use default_max_wait_time= instead
|
||||||
def default_wait_time=(t)
|
def default_wait_time=(t)
|
||||||
deprecate('default_wait_time=', 'default_max_wait_time=')
|
deprecate('default_wait_time=', 'default_max_wait_time=')
|
||||||
|
@ -357,7 +374,7 @@ module Capybara
|
||||||
require 'capybara/queries/text_query'
|
require 'capybara/queries/text_query'
|
||||||
require 'capybara/queries/title_query'
|
require 'capybara/queries/title_query'
|
||||||
require 'capybara/queries/current_path_query'
|
require 'capybara/queries/current_path_query'
|
||||||
|
|
||||||
require 'capybara/node/finders'
|
require 'capybara/node/finders'
|
||||||
require 'capybara/node/matchers'
|
require 'capybara/node/matchers'
|
||||||
require 'capybara/node/actions'
|
require 'capybara/node/actions'
|
||||||
|
|
|
@ -49,6 +49,10 @@ module Capybara
|
||||||
all[name.to_sym] = Capybara::Selector.new(name.to_sym, &block)
|
all[name.to_sym] = Capybara::Selector.new(name.to_sym, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update(name, &block)
|
||||||
|
all[name.to_sym].instance_eval(&block)
|
||||||
|
end
|
||||||
|
|
||||||
def remove(name)
|
def remove(name)
|
||||||
all.delete(name.to_sym)
|
all.delete(name.to_sym)
|
||||||
end
|
end
|
||||||
|
@ -65,15 +69,19 @@ module Capybara
|
||||||
end
|
end
|
||||||
|
|
||||||
def xpath(&block)
|
def xpath(&block)
|
||||||
@format = :xpath
|
if block
|
||||||
@xpath = block if block
|
@format = :xpath
|
||||||
|
@xpath, @css = block, nil
|
||||||
|
end
|
||||||
@xpath
|
@xpath
|
||||||
end
|
end
|
||||||
|
|
||||||
# Same as xpath, but wrap in XPath.css().
|
# Same as xpath, but wrap in XPath.css().
|
||||||
def css(&block)
|
def css(&block)
|
||||||
@format = :css
|
if block
|
||||||
@css = block if block
|
@format = :css
|
||||||
|
@css, @xpath = block, nil
|
||||||
|
end
|
||||||
@css
|
@css
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
53
spec/selector_spec.rb
Normal file
53
spec/selector_spec.rb
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe Capybara do
|
||||||
|
describe 'Selectors' do
|
||||||
|
let :string do
|
||||||
|
Capybara.string <<-STRING
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>selectors</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="a" id="page">
|
||||||
|
<div class="b" id="content">
|
||||||
|
<h1 class="a">Totally awesome</h1>
|
||||||
|
<p>Yes it is</p>
|
||||||
|
</div>
|
||||||
|
<p class="b">Some Content</p>
|
||||||
|
<p class="b"></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
STRING
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
Capybara.add_selector :custom_selector do
|
||||||
|
css { |css_class| "div.#{css_class}" }
|
||||||
|
filter(:not_empty, boolean: true, default: true, skip_if: :all) { |node, value| value ^ (node.text == '') }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "modfiy_selector" do
|
||||||
|
it "allows modifying a selector" do
|
||||||
|
el = string.find(:custom_selector, 'a')
|
||||||
|
expect(el.tag_name).to eq 'div'
|
||||||
|
Capybara.modify_selector :custom_selector do
|
||||||
|
css { |css_class| "h1.#{css_class}" }
|
||||||
|
end
|
||||||
|
el = string.find(:custom_selector, 'a')
|
||||||
|
expect(el.tag_name).to eq 'h1'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't change existing filters" do
|
||||||
|
Capybara.modify_selector :custom_selector do
|
||||||
|
css { |css_class| "p.#{css_class}"}
|
||||||
|
end
|
||||||
|
expect(string).to have_selector(:custom_selector, 'b', count: 1)
|
||||||
|
expect(string).to have_selector(:custom_selector, 'b', not_empty: false, count: 1)
|
||||||
|
expect(string).to have_selector(:custom_selector, 'b', not_empty: :all, count: 2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue