capybara 3.2.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +22 -1
- data/README.md +1 -1
- data/lib/capybara.rb +2 -0
- data/lib/capybara/driver/base.rb +5 -1
- data/lib/capybara/driver/node.rb +4 -0
- data/lib/capybara/helpers.rb +25 -0
- data/lib/capybara/minitest.rb +7 -1
- data/lib/capybara/minitest/spec.rb +8 -1
- data/lib/capybara/node/base.rb +3 -3
- data/lib/capybara/node/element.rb +52 -0
- data/lib/capybara/node/matchers.rb +33 -0
- data/lib/capybara/queries/selector_query.rb +4 -4
- data/lib/capybara/queries/style_query.rb +41 -0
- data/lib/capybara/rack_test/browser.rb +7 -1
- data/lib/capybara/rack_test/node.rb +4 -0
- data/lib/capybara/rspec/compound.rb +67 -65
- data/lib/capybara/rspec/features.rb +2 -4
- data/lib/capybara/rspec/matchers.rb +30 -10
- data/lib/capybara/selector.rb +9 -0
- data/lib/capybara/selector/css.rb +74 -1
- data/lib/capybara/selector/filters/base.rb +2 -1
- data/lib/capybara/selector/filters/expression_filter.rb +2 -1
- data/lib/capybara/selector/selector.rb +1 -1
- data/lib/capybara/selenium/driver.rb +34 -43
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +35 -0
- data/lib/capybara/selenium/driver_specializations/marionette_driver.rb +31 -0
- data/lib/capybara/selenium/node.rb +17 -20
- data/lib/capybara/selenium/nodes/marionette_node.rb +31 -0
- data/lib/capybara/server.rb +8 -29
- data/lib/capybara/server/checker.rb +38 -0
- data/lib/capybara/spec/public/test.js +5 -0
- data/lib/capybara/spec/session/all_spec.rb +4 -0
- data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
- data/lib/capybara/spec/session/click_button_spec.rb +10 -0
- data/lib/capybara/spec/session/click_link_spec.rb +11 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +2 -0
- data/lib/capybara/spec/session/find_link_spec.rb +18 -0
- data/lib/capybara/spec/session/find_spec.rb +1 -0
- data/lib/capybara/spec/session/first_spec.rb +1 -0
- data/lib/capybara/spec/session/has_css_spec.rb +0 -6
- data/lib/capybara/spec/session/has_style_spec.rb +25 -0
- data/lib/capybara/spec/session/node_spec.rb +34 -0
- data/lib/capybara/spec/session/save_page_spec.rb +4 -1
- data/lib/capybara/spec/session/save_screenshot_spec.rb +3 -1
- data/lib/capybara/spec/session/text_spec.rb +1 -0
- data/lib/capybara/spec/session/title_spec.rb +1 -0
- data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -0
- data/lib/capybara/spec/session/window/window_spec.rb +20 -0
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -0
- data/lib/capybara/spec/session/window/within_window_spec.rb +1 -0
- data/lib/capybara/spec/session/within_spec.rb +1 -0
- data/lib/capybara/spec/spec_helper.rb +3 -1
- data/lib/capybara/spec/test_app.rb +18 -0
- data/lib/capybara/spec/views/form.erb +8 -0
- data/lib/capybara/spec/views/tables.erb +1 -1
- data/lib/capybara/spec/views/with_html.erb +9 -2
- data/lib/capybara/spec/views/with_js.erb +4 -0
- data/lib/capybara/spec/views/with_namespace.erb +20 -0
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +11 -0
- data/spec/css_splitter_spec.rb +38 -0
- data/spec/dsl_spec.rb +1 -1
- data/spec/minitest_spec.rb +7 -1
- data/spec/minitest_spec_spec.rb +8 -1
- data/spec/rack_test_spec.rb +10 -0
- data/spec/rspec/shared_spec_matchers.rb +2 -0
- data/spec/selenium_spec_chrome.rb +28 -0
- data/spec/selenium_spec_chrome_remote.rb +2 -2
- data/spec/selenium_spec_marionette.rb +21 -1
- data/spec/server_spec.rb +0 -1
- data/spec/shared_selenium_session.rb +16 -1
- metadata +18 -19
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'capybara/selenium/nodes/marionette_node'
|
4
|
+
|
5
|
+
module Capybara::Selenium::Driver::MarionetteDriver
|
6
|
+
def resize_window_to(handle, width, height)
|
7
|
+
within_given_window(handle) do
|
8
|
+
# Don't set the size if already set - See https://github.com/mozilla/geckodriver/issues/643
|
9
|
+
if window_size(handle) == [width, height]
|
10
|
+
{}
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset!
|
18
|
+
# Use instance variable directly so we avoid starting the browser just to reset the session
|
19
|
+
return unless @browser
|
20
|
+
|
21
|
+
switch_to_window(window_handles.first)
|
22
|
+
window_handles.slice(1..-1).each { |win| close_window(win) }
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def build_node(native_node)
|
29
|
+
::Capybara::Selenium::MarionetteNode.new(self, native_node)
|
30
|
+
end
|
31
|
+
end
|
@@ -28,6 +28,12 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
def style(styles)
|
32
|
+
styles.each_with_object({}) do |style, result|
|
33
|
+
result[style] = native.css_value(style)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
31
37
|
##
|
32
38
|
#
|
33
39
|
# Set the value of the form element to the given value.
|
@@ -91,6 +97,7 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
91
97
|
e.message =~ /Other element would receive the click/
|
92
98
|
scroll_to_center
|
93
99
|
end
|
100
|
+
|
94
101
|
raise e
|
95
102
|
end
|
96
103
|
|
@@ -133,18 +140,7 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
133
140
|
alias :checked? :selected?
|
134
141
|
|
135
142
|
def disabled?
|
136
|
-
|
137
|
-
|
138
|
-
# workaround for selenium-webdriver/geckodriver reporting elements as enabled when they are nested in disabling elements
|
139
|
-
if driver.marionette?
|
140
|
-
if %w[option optgroup].include? tag_name
|
141
|
-
find_xpath("parent::*[self::optgroup or self::select]")[0].disabled?
|
142
|
-
else
|
143
|
-
!find_xpath("parent::fieldset[@disabled] | ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]").empty?
|
144
|
-
end
|
145
|
-
else
|
146
|
-
false
|
147
|
-
end
|
143
|
+
!native.enabled?
|
148
144
|
end
|
149
145
|
|
150
146
|
def content_editable?
|
@@ -167,9 +163,15 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
167
163
|
path = find_xpath(XPath.ancestor_or_self).reverse
|
168
164
|
|
169
165
|
result = []
|
166
|
+
default_ns = path.last[:namespaceURI]
|
170
167
|
while (node = path.shift)
|
171
168
|
parent = path.first
|
172
|
-
selector = node
|
169
|
+
selector = node[:tagName]
|
170
|
+
if node[:namespaceURI] != default_ns
|
171
|
+
selector = XPath.child.where((XPath.local_name == selector) & (XPath.namespace_uri == node[:namespaceURI])).to_s
|
172
|
+
selector
|
173
|
+
end
|
174
|
+
|
173
175
|
if parent
|
174
176
|
siblings = parent.find_xpath(selector)
|
175
177
|
selector += "[#{siblings.index(node) + 1}]" unless siblings.size == 1
|
@@ -265,17 +267,12 @@ private
|
|
265
267
|
arguments[0].dispatchEvent(new InputEvent('input'));
|
266
268
|
arguments[0].dispatchEvent(new Event('change', { bubbles: true }));
|
267
269
|
}
|
268
|
-
|
270
|
+
JS
|
269
271
|
end
|
270
272
|
|
271
273
|
def set_file(value) # rubocop:disable Naming/AccessorMethodName
|
272
274
|
path_names = value.to_s.empty? ? [] : value
|
273
|
-
|
274
|
-
native.clear
|
275
|
-
Array(path_names).each { |p| native.send_keys(p) }
|
276
|
-
else
|
277
|
-
native.send_keys(Array(path_names).join("\n"))
|
278
|
-
end
|
275
|
+
native.send_keys(Array(path_names).join("\n"))
|
279
276
|
end
|
280
277
|
|
281
278
|
def set_content_editable(value) # rubocop:disable Naming/AccessorMethodName
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Capybara::Selenium::MarionetteNode < Capybara::Selenium::Node
|
4
|
+
def click(keys = [], **options)
|
5
|
+
super
|
6
|
+
rescue ::Selenium::WebDriver::Error::ElementNotInteractableError
|
7
|
+
if tag_name == "tr"
|
8
|
+
warn "You are attempting to click a table row which has issues in geckodriver/marionette - see https://github.com/mozilla/geckodriver/issues/1228. " \
|
9
|
+
"Your test should probably be clicking on a table cell like a user would. Clicking the first cell in the row instead."
|
10
|
+
return find_css('th:first-child,td:first-child')[0].click
|
11
|
+
end
|
12
|
+
raise
|
13
|
+
end
|
14
|
+
|
15
|
+
def disabled?
|
16
|
+
return true if super
|
17
|
+
|
18
|
+
# workaround for selenium-webdriver/geckodriver reporting elements as enabled when they are nested in disabling elements
|
19
|
+
if %w[option optgroup].include? tag_name
|
20
|
+
find_xpath("parent::*[self::optgroup or self::select]")[0].disabled?
|
21
|
+
else
|
22
|
+
!find_xpath("parent::fieldset[@disabled] | ancestor::*[not(self::legend) or preceding-sibling::legend][parent::fieldset[@disabled]]").empty?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_file(value) # rubocop:disable Naming/AccessorMethodName
|
27
|
+
path_names = value.to_s.empty? ? [] : value
|
28
|
+
native.clear
|
29
|
+
Array(path_names).each { |p| native.send_keys(p) }
|
30
|
+
end
|
31
|
+
end
|
data/lib/capybara/server.rb
CHANGED
@@ -5,6 +5,7 @@ require 'net/http'
|
|
5
5
|
require 'rack'
|
6
6
|
require 'capybara/server/middleware'
|
7
7
|
require 'capybara/server/animation_disabler'
|
8
|
+
require 'capybara/server/checker'
|
8
9
|
|
9
10
|
module Capybara
|
10
11
|
class Server
|
@@ -23,10 +24,10 @@ module Capybara
|
|
23
24
|
@server_thread = nil # suppress warnings
|
24
25
|
@host = deprecated_options[1] || host
|
25
26
|
@reportable_errors = deprecated_options[2] || reportable_errors
|
26
|
-
@using_ssl = false
|
27
27
|
@port = deprecated_options[0] || port
|
28
28
|
@port ||= Capybara::Server.ports[port_key]
|
29
29
|
@port ||= find_available_port(host)
|
30
|
+
@checker = Checker.new(@host, @port)
|
30
31
|
end
|
31
32
|
|
32
33
|
def reset_error!
|
@@ -38,22 +39,12 @@ module Capybara
|
|
38
39
|
end
|
39
40
|
|
40
41
|
def using_ssl?
|
41
|
-
@
|
42
|
+
@checker.ssl?
|
42
43
|
end
|
43
44
|
|
44
45
|
def responsive?
|
45
46
|
return false if @server_thread&.join(0)
|
46
|
-
|
47
|
-
begin
|
48
|
-
res = if !using_ssl?
|
49
|
-
http_connect
|
50
|
-
else
|
51
|
-
https_connect
|
52
|
-
end
|
53
|
-
rescue EOFError, Net::ReadTimeout
|
54
|
-
res = https_connect
|
55
|
-
@using_ssl = true
|
56
|
-
end
|
47
|
+
res = @checker.request { |http| http.get('/__identify__') }
|
57
48
|
|
58
49
|
if res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPRedirection)
|
59
50
|
return res.body == app.object_id.to_s
|
@@ -63,11 +54,9 @@ module Capybara
|
|
63
54
|
end
|
64
55
|
|
65
56
|
def wait_for_pending_requests
|
66
|
-
|
57
|
+
timer = Capybara::Helpers.timer(expire_in: 60)
|
67
58
|
while pending_requests?
|
68
|
-
|
69
|
-
raise "Requests did not finish in 60 seconds"
|
70
|
-
end
|
59
|
+
raise "Requests did not finish in 60 seconds" if timer.expired?
|
71
60
|
sleep 0.01
|
72
61
|
end
|
73
62
|
end
|
@@ -80,11 +69,9 @@ module Capybara
|
|
80
69
|
Capybara.server.call(middleware, port, host)
|
81
70
|
end
|
82
71
|
|
83
|
-
|
72
|
+
timer = Capybara::Helpers.timer(expire_in: 60)
|
84
73
|
until responsive?
|
85
|
-
|
86
|
-
raise "Rack application timed out during boot"
|
87
|
-
end
|
74
|
+
raise "Rack application timed out during boot" if timer.expired?
|
88
75
|
@server_thread.join(0.1)
|
89
76
|
end
|
90
77
|
end
|
@@ -94,14 +81,6 @@ module Capybara
|
|
94
81
|
|
95
82
|
private
|
96
83
|
|
97
|
-
def http_connect
|
98
|
-
Net::HTTP.start(host, port, read_timeout: 2) { |http| http.get('/__identify__') }
|
99
|
-
end
|
100
|
-
|
101
|
-
def https_connect
|
102
|
-
Net::HTTP.start(host, port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) { |http| http.get('/__identify__') }
|
103
|
-
end
|
104
|
-
|
105
84
|
def middleware
|
106
85
|
@middleware ||= Middleware.new(app, @reportable_errors, @extra_middleware)
|
107
86
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Capybara
|
4
|
+
class Server
|
5
|
+
class Checker
|
6
|
+
def initialize(host, port)
|
7
|
+
@host, @port = host, port
|
8
|
+
@ssl = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def request(&block)
|
12
|
+
ssl? ? https_request(&block) : http_request(&block)
|
13
|
+
rescue EOFError, Net::ReadTimeout
|
14
|
+
res = https_request(&block)
|
15
|
+
@ssl = true
|
16
|
+
res
|
17
|
+
end
|
18
|
+
|
19
|
+
def ssl?
|
20
|
+
@ssl
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def http_request(&block)
|
26
|
+
Net::HTTP.start(@host, @port, read_timeout: 2, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def https_request(&block)
|
30
|
+
Net::HTTP.start(@host, @port, ssl_options, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def ssl_options
|
34
|
+
{ use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -63,6 +63,11 @@ $(function() {
|
|
63
63
|
$('title').text('changed title')
|
64
64
|
}, 400)
|
65
65
|
});
|
66
|
+
$('#change-size').click(function() {
|
67
|
+
setTimeout(function() {
|
68
|
+
document.getElementById('change').style.fontSize = '50px';
|
69
|
+
}, 500)
|
70
|
+
});
|
66
71
|
$('#click-test').on({
|
67
72
|
click: function(e) {
|
68
73
|
var desc = "";
|
@@ -59,6 +59,7 @@ Capybara::SpecHelper.spec "#all" do
|
|
59
59
|
|
60
60
|
context "with css as default selector" do
|
61
61
|
before { Capybara.default_selector = :css }
|
62
|
+
|
62
63
|
it "should find the first element using the given locator" do
|
63
64
|
expect(@session.all('h1').first.text).to eq('This is a test')
|
64
65
|
expect(@session.all("input[id='test_field']").first.value).to eq('monkey')
|
@@ -102,6 +103,7 @@ Capybara::SpecHelper.spec "#all" do
|
|
102
103
|
expect { @session.all(:css, 'h1, p', count: 5) }.to raise_error(Capybara::ExpectationNotMet)
|
103
104
|
end
|
104
105
|
end
|
106
|
+
|
105
107
|
context ':minimum' do
|
106
108
|
it 'should succeed when the number of elements founds matches the expectation' do
|
107
109
|
expect { @session.all(:css, 'h1, p', minimum: 0) }.not_to raise_error
|
@@ -110,6 +112,7 @@ Capybara::SpecHelper.spec "#all" do
|
|
110
112
|
expect { @session.all(:css, 'h1, p', minimum: 5) }.to raise_error(Capybara::ExpectationNotMet)
|
111
113
|
end
|
112
114
|
end
|
115
|
+
|
113
116
|
context ':maximum' do
|
114
117
|
it 'should succeed when the number of elements founds matches the expectation' do
|
115
118
|
expect { @session.all(:css, 'h1, p', maximum: 4) }.not_to raise_error
|
@@ -118,6 +121,7 @@ Capybara::SpecHelper.spec "#all" do
|
|
118
121
|
expect { @session.all(:css, 'h1, p', maximum: 0) }.to raise_error(Capybara::ExpectationNotMet)
|
119
122
|
end
|
120
123
|
end
|
124
|
+
|
121
125
|
context ':between' do
|
122
126
|
it 'should succeed when the number of elements founds matches the expectation' do
|
123
127
|
expect { @session.all(:css, 'h1, p', between: 2..7) }.not_to raise_error
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Capybara::SpecHelper.spec '#assert_style', requires: [:css] do
|
4
|
+
it "should not raise if the elements style contains the given properties" do
|
5
|
+
@session.visit('/with_html')
|
6
|
+
expect do
|
7
|
+
@session.find(:css, '#first').assert_style(display: 'block')
|
8
|
+
end.not_to raise_error
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should raise error if the elements style doesn't contain the given properties" do
|
12
|
+
@session.visit('/with_html')
|
13
|
+
expect do
|
14
|
+
@session.find(:css, '#first').assert_style(display: 'inline')
|
15
|
+
end.to raise_error(Capybara::ExpectationNotMet, 'Expected node to have styles {"display"=>"inline"}. Actual styles were {"display"=>"block"}')
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should wait for style", requires: %i[css js] do
|
19
|
+
@session.visit('/with_js')
|
20
|
+
el = @session.find(:css, '#change')
|
21
|
+
@session.click_link("Change size")
|
22
|
+
expect do
|
23
|
+
el.assert_style({ 'font-size': '50px' }, wait: 3)
|
24
|
+
end.not_to raise_error
|
25
|
+
end
|
26
|
+
end
|
@@ -396,6 +396,16 @@ Capybara::SpecHelper.spec '#click_button' do
|
|
396
396
|
expect(@session.current_url).to match(%r{/landed$})
|
397
397
|
end
|
398
398
|
|
399
|
+
it "should follow temporary redirects that maintain method" do
|
400
|
+
@session.click_button('Go 307')
|
401
|
+
expect(@session).to have_content('You post landed: TWTW')
|
402
|
+
end
|
403
|
+
|
404
|
+
it "should follow permanent redirects that maintain method" do
|
405
|
+
@session.click_button('Go 308')
|
406
|
+
expect(@session).to have_content('You post landed: TWTW')
|
407
|
+
end
|
408
|
+
|
399
409
|
it "should post pack to the same URL when no action given" do
|
400
410
|
@session.visit('/postback')
|
401
411
|
@session.click_button('With no action')
|
@@ -203,4 +203,15 @@ Capybara::SpecHelper.spec '#click_link' do
|
|
203
203
|
el = @session.find(:link, 'Normal Anchor')
|
204
204
|
expect(@session.click_link('Normal Anchor')).to eq el
|
205
205
|
end
|
206
|
+
|
207
|
+
it "can download a file", requires: [:download] do
|
208
|
+
# This requires the driver used for the test to be configured
|
209
|
+
# to download documents with the mime type "text/csv"
|
210
|
+
download_file = File.join(Capybara.save_path, 'download.csv')
|
211
|
+
expect(File).not_to exist(download_file)
|
212
|
+
@session.click_link('Download Me')
|
213
|
+
sleep 2
|
214
|
+
expect(File).to exist(download_file)
|
215
|
+
FileUtils.rm_rf download_file
|
216
|
+
end
|
206
217
|
end
|
@@ -188,7 +188,9 @@ Capybara::SpecHelper.spec "#fill_in" do
|
|
188
188
|
|
189
189
|
context "with ignore_hidden_fields" do
|
190
190
|
before { Capybara.ignore_hidden_elements = true }
|
191
|
+
|
191
192
|
after { Capybara.ignore_hidden_elements = false }
|
193
|
+
|
192
194
|
it "should not find a hidden field" do
|
193
195
|
msg = "Unable to find visible field \"Super Secret\" that is not disabled"
|
194
196
|
expect do
|
@@ -49,4 +49,22 @@ Capybara::SpecHelper.spec '#find_link' do
|
|
49
49
|
expect(@session.find_link(href: '#anchor').text).to eq "Normal Anchor"
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
53
|
+
context "download filter" do
|
54
|
+
it "finds a download link" do
|
55
|
+
expect(@session.find_link("Download Me", download: true).text).to eq "Download Me"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "doesn't find a download link if download is false" do
|
59
|
+
expect { @session.find_link("Download Me", download: false) }.to raise_error Capybara::ElementNotFound
|
60
|
+
end
|
61
|
+
|
62
|
+
it "finds a renaming download link" do
|
63
|
+
expect(@session.find_link(download: "other.csv").text).to eq "Download Other"
|
64
|
+
end
|
65
|
+
|
66
|
+
it "raises if passed an invalid value" do
|
67
|
+
expect { @session.find_link(download: 37) }.to raise_error ArgumentError
|
68
|
+
end
|
69
|
+
end
|
52
70
|
end
|
@@ -206,6 +206,7 @@ Capybara::SpecHelper.spec '#find' do
|
|
206
206
|
|
207
207
|
context "with css as default selector" do
|
208
208
|
before { Capybara.default_selector = :css }
|
209
|
+
|
209
210
|
it "should find the first element using the given locator" do
|
210
211
|
expect(@session.find('h1').text).to eq('This is a test')
|
211
212
|
expect(@session.find("input[id='test_field']").value).to eq('monkey')
|
@@ -51,6 +51,7 @@ Capybara::SpecHelper.spec '#first' do
|
|
51
51
|
|
52
52
|
context "with css as default selector" do
|
53
53
|
before { Capybara.default_selector = :css }
|
54
|
+
|
54
55
|
it "should find the first element using the given locator" do
|
55
56
|
expect(@session.first('h1').text).to eq('This is a test')
|
56
57
|
expect(@session.first("input[id='test_field']").value).to eq('monkey')
|
@@ -115,12 +115,6 @@ Capybara::SpecHelper.spec '#has_css?' do
|
|
115
115
|
end
|
116
116
|
|
117
117
|
it "should allow escapes in the CSS selector" do
|
118
|
-
if (defined?(TestClass) && @session.is_a?(TestClass)) || @session.driver.is_a?(Capybara::RackTest::Driver)
|
119
|
-
# Nokogiri doesn't unescape CSS selectors when converting from CSS to XPath
|
120
|
-
# See: https://github.com/teamcapybara/capybara/issues/1866
|
121
|
-
# Also: https://github.com/sparklemotion/nokogiri/pull/1646
|
122
|
-
pending "Current Nokogiri doesn't handle escapes in CSS attribute selectors correctly"
|
123
|
-
end
|
124
118
|
expect(@session).to have_css('p[data-random="abc\\\\def"]')
|
125
119
|
expect(@session).to have_css("p[data-random='#{Capybara::Selector::CSS.escape('abc\def')}']")
|
126
120
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Capybara::SpecHelper.spec '#has_style?', requires: [:css] do
|
4
|
+
before do
|
5
|
+
@session.visit('/with_html')
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be true if the element has the given style" do
|
9
|
+
expect(@session.find(:css, '#first')).to have_style(display: 'block')
|
10
|
+
expect(@session.find(:css, '#first').has_style?(display: 'block')).to be true
|
11
|
+
expect(@session.find(:css, '#second')).to have_style('display' => 'inline')
|
12
|
+
expect(@session.find(:css, '#second').has_style?('display' => 'inline')).to be true
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be false if the element does not have the given style" do
|
16
|
+
expect(@session.find(:css, '#first').has_style?('display' => 'inline')).to be false
|
17
|
+
expect(@session.find(:css, '#second').has_style?(display: 'block')).to be false
|
18
|
+
end
|
19
|
+
|
20
|
+
it "allows Regexp for value matching" do
|
21
|
+
expect(@session.find(:css, '#first')).to have_style(display: /^bl/)
|
22
|
+
expect(@session.find(:css, '#first').has_style?('display' => /^bl/)).to be true
|
23
|
+
expect(@session.find(:css, '#first').has_style?(display: /^in/)).to be false
|
24
|
+
end
|
25
|
+
end
|