capybara 3.1.1 → 3.2.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 +19 -0
- data/README.md +1 -1
- data/lib/capybara.rb +2 -0
- data/lib/capybara/config.rb +2 -1
- data/lib/capybara/driver/base.rb +1 -1
- data/lib/capybara/driver/node.rb +3 -3
- data/lib/capybara/node/actions.rb +90 -92
- data/lib/capybara/node/base.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +5 -5
- data/lib/capybara/node/element.rb +47 -16
- data/lib/capybara/node/finders.rb +13 -13
- data/lib/capybara/node/matchers.rb +18 -17
- data/lib/capybara/node/simple.rb +6 -2
- data/lib/capybara/queries/ancestor_query.rb +1 -1
- data/lib/capybara/queries/base_query.rb +3 -3
- data/lib/capybara/queries/current_path_query.rb +1 -1
- data/lib/capybara/queries/match_query.rb +8 -0
- data/lib/capybara/queries/selector_query.rb +97 -42
- data/lib/capybara/queries/sibling_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +12 -7
- data/lib/capybara/rack_test/browser.rb +9 -7
- data/lib/capybara/rack_test/form.rb +15 -17
- data/lib/capybara/rack_test/node.rb +12 -12
- data/lib/capybara/result.rb +26 -15
- data/lib/capybara/rspec.rb +1 -2
- data/lib/capybara/rspec/compound.rb +4 -4
- data/lib/capybara/rspec/matchers.rb +2 -2
- data/lib/capybara/selector.rb +75 -225
- data/lib/capybara/selector/css.rb +2 -2
- data/lib/capybara/selector/filter_set.rb +17 -21
- data/lib/capybara/selector/filters/base.rb +24 -1
- data/lib/capybara/selector/filters/expression_filter.rb +3 -5
- data/lib/capybara/selector/filters/node_filter.rb +4 -4
- data/lib/capybara/selector/selector.rb +221 -69
- data/lib/capybara/selenium/driver.rb +15 -88
- data/lib/capybara/selenium/node.rb +25 -28
- data/lib/capybara/server.rb +10 -54
- data/lib/capybara/server/animation_disabler.rb +43 -0
- data/lib/capybara/server/middleware.rb +55 -0
- data/lib/capybara/session.rb +29 -30
- data/lib/capybara/session/config.rb +11 -1
- data/lib/capybara/session/matchers.rb +5 -5
- data/lib/capybara/spec/session/assert_text_spec.rb +1 -1
- data/lib/capybara/spec/session/body_spec.rb +10 -12
- data/lib/capybara/spec/session/click_link_spec.rb +3 -3
- data/lib/capybara/spec/session/element/assert_match_selector_spec.rb +1 -1
- data/lib/capybara/spec/session/fill_in_spec.rb +9 -0
- data/lib/capybara/spec/session/find_field_spec.rb +1 -1
- data/lib/capybara/spec/session/find_spec.rb +8 -3
- data/lib/capybara/spec/session/has_link_spec.rb +2 -2
- data/lib/capybara/spec/session/node_spec.rb +50 -0
- data/lib/capybara/spec/session/node_wrapper_spec.rb +5 -5
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +1 -1
- data/lib/capybara/spec/session/window/windows_spec.rb +3 -5
- data/lib/capybara/spec/spec_helper.rb +4 -2
- data/lib/capybara/spec/views/with_animation.erb +46 -0
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +3 -2
- data/spec/filter_set_spec.rb +19 -2
- data/spec/result_spec.rb +33 -1
- data/spec/rspec/features_spec.rb +6 -10
- data/spec/rspec/shared_spec_matchers.rb +4 -4
- data/spec/selector_spec.rb +74 -4
- data/spec/selenium_spec_marionette.rb +2 -0
- data/spec/server_spec.rb +1 -1
- data/spec/session_spec.rb +12 -0
- data/spec/shared_selenium_session.rb +30 -0
- metadata +8 -9
- data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
- data/.yard/templates_custom/default/class/html/setup.rb +0 -17
- data/.yard/yard_extensions.rb +0 -78
- data/.yardopts +0 -1
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
class NodeWrapper
|
4
|
+
def initialize(element); @element = element end
|
5
|
+
def to_capybara_node(); @element end
|
6
|
+
end
|
7
|
+
|
3
8
|
Capybara::SpecHelper.spec "#to_capybara_node" do
|
4
9
|
before do
|
5
10
|
@session.visit('/with_html')
|
6
11
|
end
|
7
12
|
|
8
|
-
class NodeWrapper
|
9
|
-
def initialize(element); @element = element end
|
10
|
-
def to_capybara_node(); @element end
|
11
|
-
end
|
12
|
-
|
13
13
|
it "should support have_xxx expectations" do
|
14
14
|
para = NodeWrapper.new(@session.find(:css, '#first'))
|
15
15
|
expect(para).to have_link("ullamco")
|
@@ -8,7 +8,7 @@ Capybara::SpecHelper.spec '#save_and_open_screenshot' do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'opens file from the default directory', requires: [:screenshot] do
|
11
|
-
expected_file_regex =
|
11
|
+
expected_file_regex = /capybara-\d+\.png/
|
12
12
|
allow(@session.driver).to receive(:save_screenshot)
|
13
13
|
allow(Launchy).to receive(:open)
|
14
14
|
|
@@ -11,10 +11,7 @@ Capybara::SpecHelper.spec '#windows', requires: [:windows] do
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
after do
|
14
|
-
(@session.windows - [@window]).each
|
15
|
-
@session.switch_to_window w
|
16
|
-
w.close
|
17
|
-
end
|
14
|
+
(@session.windows - [@window]).each(&:close)
|
18
15
|
@session.switch_to_window(@window)
|
19
16
|
end
|
20
17
|
|
@@ -22,7 +19,8 @@ Capybara::SpecHelper.spec '#windows', requires: [:windows] do
|
|
22
19
|
expect(@session.windows.map { |window| window.instance_of?(Capybara::Window) }).to eq([true] * 3)
|
23
20
|
end
|
24
21
|
|
25
|
-
it 'should
|
22
|
+
it 'should be able to switch to windows' do
|
23
|
+
sleep 1 # give windows enough time to fully load
|
26
24
|
titles = @session.windows.map do |window|
|
27
25
|
@session.within_window(window) { @session.title }
|
28
26
|
end
|
@@ -29,11 +29,13 @@ module Capybara
|
|
29
29
|
Capybara.visible_text_only = false
|
30
30
|
Capybara.match = :smart
|
31
31
|
Capybara.enable_aria_label = false
|
32
|
+
Capybara.default_set_options = {}
|
33
|
+
Capybara.disable_animation = false
|
32
34
|
reset_threadsafe
|
33
35
|
end
|
34
36
|
|
35
37
|
def filter(requires, metadata)
|
36
|
-
if requires
|
38
|
+
if requires && metadata[:capybara_skip]
|
37
39
|
requires.any? do |require|
|
38
40
|
metadata[:capybara_skip].include?(require)
|
39
41
|
end
|
@@ -86,7 +88,7 @@ module Capybara
|
|
86
88
|
Capybara::Session.class_variable_set(:@@instance_created, false) # Work around limit on when threadsafe can be changed
|
87
89
|
Capybara.threadsafe = bool
|
88
90
|
session = session.current_session if session.respond_to?(:current_session)
|
89
|
-
session
|
91
|
+
session&.instance_variable_set(:@config, nil)
|
90
92
|
end
|
91
93
|
end
|
92
94
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
5
|
+
<title>with_animation</title>
|
6
|
+
<script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
|
7
|
+
<script src="/jquery-ui.js" type="text/javascript" charset="utf-8"></script>
|
8
|
+
<script src="/test.js" type="text/javascript" charset="utf-8"></script>
|
9
|
+
<style>
|
10
|
+
.transition.away {
|
11
|
+
width: 0%;
|
12
|
+
}
|
13
|
+
|
14
|
+
a {
|
15
|
+
display: inline-block;
|
16
|
+
width: 100%;
|
17
|
+
overflow: hidden;
|
18
|
+
}
|
19
|
+
|
20
|
+
a:not(.away) {
|
21
|
+
height: 20px;
|
22
|
+
}
|
23
|
+
|
24
|
+
a.transition {
|
25
|
+
transition: all 3s ease-in-out;
|
26
|
+
}
|
27
|
+
|
28
|
+
@keyframes animation {
|
29
|
+
0% {height: 20px; width: 100%;}
|
30
|
+
100% {height: 0px; width: 0%;}
|
31
|
+
}
|
32
|
+
|
33
|
+
a.animation.away {
|
34
|
+
animation-name: animation;
|
35
|
+
animation-duration: 3s;
|
36
|
+
animation-fill-mode: forwards;
|
37
|
+
}
|
38
|
+
</style>
|
39
|
+
</head>
|
40
|
+
|
41
|
+
<body id="with_animation">
|
42
|
+
<a href='#' class='transition' onclick='this.classList.add("away")'>transition me away</a>
|
43
|
+
<a href='#' class='animation' onclick='this.classList.add("away")'>animate me away</a>
|
44
|
+
</body>
|
45
|
+
</html>
|
46
|
+
|
data/lib/capybara/version.rb
CHANGED
data/lib/capybara/window.rb
CHANGED
@@ -120,12 +120,13 @@ module Capybara
|
|
120
120
|
res = yield if block_given?
|
121
121
|
prev_size = size
|
122
122
|
start_time = Capybara::Helpers.monotonic_time
|
123
|
-
|
123
|
+
loop do
|
124
124
|
sleep 0.05
|
125
125
|
cur_size = size
|
126
126
|
return res if cur_size == prev_size
|
127
127
|
prev_size = cur_size
|
128
|
-
|
128
|
+
break if (Capybara::Helpers.monotonic_time - start_time) >= seconds
|
129
|
+
end
|
129
130
|
raise Capybara::WindowError, "Window size not stable within #{seconds} seconds."
|
130
131
|
end
|
131
132
|
|
data/spec/filter_set_spec.rb
CHANGED
@@ -9,7 +9,7 @@ RSpec.describe Capybara::Selector::FilterSet do
|
|
9
9
|
|
10
10
|
it "allows node filters" do
|
11
11
|
fs = Capybara::Selector::FilterSet.add(:test) do
|
12
|
-
|
12
|
+
node_filter(:node_test, :boolean) { |_node, _value| true }
|
13
13
|
expression_filter(:expression_test, :boolean) { |_expr, _value| true }
|
14
14
|
end
|
15
15
|
|
@@ -19,11 +19,28 @@ RSpec.describe Capybara::Selector::FilterSet do
|
|
19
19
|
|
20
20
|
it "allows expression filters" do
|
21
21
|
fs = Capybara::Selector::FilterSet.add(:test) do
|
22
|
-
|
22
|
+
node_filter(:node_test, :boolean) { |_node, _value| true }
|
23
23
|
expression_filter(:expression_test, :boolean) { |_expr, _value| true }
|
24
24
|
end
|
25
25
|
|
26
26
|
expect(fs.expression_filters.keys).to include(:expression_test)
|
27
27
|
expect(fs.expression_filters.keys).not_to include(:node_test)
|
28
28
|
end
|
29
|
+
|
30
|
+
it "allows node filter and expression filter with the same name" do
|
31
|
+
fs = Capybara::Selector::FilterSet.add(:test) do
|
32
|
+
node_filter(:test, :boolean) { |_node, _value| true }
|
33
|
+
expression_filter(:test, :boolean) { |_expr, _value| true }
|
34
|
+
end
|
35
|
+
|
36
|
+
expect(fs.expression_filters[:test]).not_to eq fs.node_filters[:test]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "allows `filter` as an alias of `node_filter`" do
|
40
|
+
fs = Capybara::Selector::FilterSet.add(:test) do
|
41
|
+
filter(:node_test, :boolean) { |_node, _value| true }
|
42
|
+
end
|
43
|
+
|
44
|
+
expect(fs.node_filters.keys).to include(:node_test)
|
45
|
+
end
|
29
46
|
end
|
data/spec/result_spec.rb
CHANGED
@@ -70,6 +70,8 @@ RSpec.describe Capybara::Result do
|
|
70
70
|
expect(result[0, 2].map(&:text)).to eq %w[Alpha Beta]
|
71
71
|
expect(result[1..3].map(&:text)).to eq %w[Beta Gamma Delta]
|
72
72
|
expect(result[-1].text).to eq 'Delta'
|
73
|
+
expect(result[-2, 3].map(&:text)).to eq %w[Gamma Delta]
|
74
|
+
expect(result[1..7].map(&:text)).to eq %w[Beta Gamma Delta]
|
73
75
|
end
|
74
76
|
|
75
77
|
it 'works with filter blocks' do
|
@@ -97,7 +99,7 @@ RSpec.describe Capybara::Result do
|
|
97
99
|
end
|
98
100
|
|
99
101
|
# Not a great test but it indirectly tests what is needed
|
100
|
-
it "should evaluate filters lazily" do
|
102
|
+
it "should evaluate filters lazily for idx" do
|
101
103
|
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
|
102
104
|
# Not processed until accessed
|
103
105
|
expect(result.instance_variable_get('@result_cache').size).to be 0
|
@@ -118,6 +120,36 @@ RSpec.describe Capybara::Result do
|
|
118
120
|
expect(result.instance_variable_get('@result_cache').size).to eq 4
|
119
121
|
end
|
120
122
|
|
123
|
+
it "should evaluate filters lazily for range" do
|
124
|
+
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
|
125
|
+
result[0..1]
|
126
|
+
expect(result.instance_variable_get('@result_cache').size).to be 2
|
127
|
+
|
128
|
+
expect(result[0..7].size).to eq 4
|
129
|
+
expect(result.instance_variable_get('@result_cache').size).to be 4
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should evaluate filters lazily for idx and length" do
|
133
|
+
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
|
134
|
+
result[1, 2]
|
135
|
+
expect(result.instance_variable_get('@result_cache').size).to be 3
|
136
|
+
|
137
|
+
expect(result[2, 5].size).to eq 2
|
138
|
+
expect(result.instance_variable_get('@result_cache').size).to be 4
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should only need to evaluate one result for any?" do
|
142
|
+
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
|
143
|
+
result.any?
|
144
|
+
expect(result.instance_variable_get('@result_cache').size).to be 1
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should evaluate all elements when #to_a called" do
|
148
|
+
# All cached when converted to array
|
149
|
+
result.to_a
|
150
|
+
expect(result.instance_variable_get('@result_cache').size).to eq 4
|
151
|
+
end
|
152
|
+
|
121
153
|
context '#each' do
|
122
154
|
it 'lazily evaluates' do
|
123
155
|
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
|
data/spec/rspec/features_spec.rb
CHANGED
@@ -12,17 +12,13 @@ feature "Capybara's feature DSL" do
|
|
12
12
|
@in_background = true
|
13
13
|
end
|
14
14
|
|
15
|
-
def current_example(context)
|
16
|
-
RSpec.respond_to?(:current_example) ? RSpec.current_example : context.example
|
17
|
-
end
|
18
|
-
|
19
15
|
scenario "includes Capybara" do
|
20
16
|
visit('/')
|
21
17
|
expect(page).to have_content('Hello world!')
|
22
18
|
end
|
23
19
|
|
24
|
-
scenario "preserves description" do
|
25
|
-
expect(
|
20
|
+
scenario "preserves description" do |ex|
|
21
|
+
expect(ex.metadata[:full_description])
|
26
22
|
.to eq("Capybara's feature DSL preserves description")
|
27
23
|
end
|
28
24
|
|
@@ -48,12 +44,12 @@ feature "Capybara's feature DSL" do
|
|
48
44
|
expect(page).to have_content 'Hello world!'
|
49
45
|
end
|
50
46
|
|
51
|
-
scenario 'are marked in the metadata as capybara_feature' do
|
52
|
-
expect(
|
47
|
+
scenario 'are marked in the metadata as capybara_feature' do |ex|
|
48
|
+
expect(ex.metadata[:capybara_feature]).to be_truthy
|
53
49
|
end
|
54
50
|
|
55
|
-
scenario 'have a type of :feature' do
|
56
|
-
expect(
|
51
|
+
scenario 'have a type of :feature' do |ex|
|
52
|
+
expect(ex.metadata[:type]).to eq :feature
|
57
53
|
end
|
58
54
|
end
|
59
55
|
end
|
@@ -215,7 +215,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
|
|
215
215
|
it "fails if has_no_selector? returns false" do
|
216
216
|
expect do
|
217
217
|
expect("<h1>Text</h1>").not_to have_selector(:css, 'h1')
|
218
|
-
end.to raise_error(
|
218
|
+
end.to raise_error(/expected not to find visible css "h1"/)
|
219
219
|
end
|
220
220
|
end
|
221
221
|
end
|
@@ -251,7 +251,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
|
|
251
251
|
it "fails if has_no_selector? returns false" do
|
252
252
|
expect do
|
253
253
|
expect(page).not_to have_selector(:css, 'h1', text: 'test')
|
254
|
-
end.to raise_error(
|
254
|
+
end.to raise_error(/expected not to find visible css "h1" with text "test"/)
|
255
255
|
end
|
256
256
|
end
|
257
257
|
end
|
@@ -558,7 +558,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
|
|
558
558
|
it 'waits if wait time is more than timeout' do
|
559
559
|
@session.click_link("Change title")
|
560
560
|
using_wait_time 0 do
|
561
|
-
expect(@session).to have_title('changed title', wait:
|
561
|
+
expect(@session).to have_title('changed title', wait: 2)
|
562
562
|
end
|
563
563
|
end
|
564
564
|
|
@@ -603,7 +603,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
|
|
603
603
|
it 'waits if wait time is more than timeout' do
|
604
604
|
@session.click_link("Change page")
|
605
605
|
using_wait_time 0 do
|
606
|
-
expect(@session).to have_current_path('/with_html', wait:
|
606
|
+
expect(@session).to have_current_path('/with_html', wait: 2)
|
607
607
|
end
|
608
608
|
end
|
609
609
|
|
data/spec/selector_spec.rb
CHANGED
@@ -16,11 +16,14 @@ RSpec.describe Capybara do
|
|
16
16
|
<h1 class="a">Totally awesome</h1>
|
17
17
|
<p>Yes it is</p>
|
18
18
|
</div>
|
19
|
-
<p class="b">Some Content</p>
|
20
|
-
<p class="b"></p>
|
19
|
+
<p class="b c">Some Content</p>
|
20
|
+
<p class="b d"></p>
|
21
21
|
</div>
|
22
22
|
<div id="#special">
|
23
23
|
</div>
|
24
|
+
<div class="some random words" id="random_words">
|
25
|
+
Something
|
26
|
+
</div>
|
24
27
|
<input id="2checkbox" class="2checkbox" type="checkbox"/>
|
25
28
|
<input type="radio"/>
|
26
29
|
<label for="my_text_input">My Text Input</label>
|
@@ -37,7 +40,7 @@ RSpec.describe Capybara do
|
|
37
40
|
</select>
|
38
41
|
<table>
|
39
42
|
<tr><td></td></tr>
|
40
|
-
</table
|
43
|
+
</table>
|
41
44
|
</body>
|
42
45
|
</html>
|
43
46
|
STRING
|
@@ -46,12 +49,25 @@ RSpec.describe Capybara do
|
|
46
49
|
before do
|
47
50
|
Capybara.add_selector :custom_selector do
|
48
51
|
css { |css_class| "div.#{css_class}" }
|
49
|
-
|
52
|
+
node_filter(:not_empty, boolean: true, default: true, skip_if: :all) { |node, value| value ^ (node.text == '') }
|
50
53
|
end
|
51
54
|
|
52
55
|
Capybara.add_selector :custom_css_selector do
|
53
56
|
css { |selector| selector }
|
54
57
|
end
|
58
|
+
|
59
|
+
Capybara.add_selector :custom_xpath_selector do
|
60
|
+
xpath { |selector| selector }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "supports `filter` as an alias for `node_filter`" do
|
65
|
+
expect do
|
66
|
+
Capybara.add_selector :filter_alias_selector do
|
67
|
+
css { |_unused| "div" }
|
68
|
+
filter(:something) { |_node, _value| true }
|
69
|
+
end
|
70
|
+
end.not_to raise_error
|
55
71
|
end
|
56
72
|
|
57
73
|
describe "adding a selector" do
|
@@ -121,6 +137,16 @@ RSpec.describe Capybara do
|
|
121
137
|
expect(string.find(:custom_css_selector, "div", id: "#special")[:id]).to eq '#special'
|
122
138
|
expect(string.find(:custom_css_selector, "input", id: "2checkbox")[:id]).to eq '2checkbox'
|
123
139
|
end
|
140
|
+
|
141
|
+
it "accepts XPath expression for xpath based selectors" do
|
142
|
+
expect(string.find(:custom_xpath_selector, './/div', id: XPath.contains('peci'))[:id]).to eq '#special'
|
143
|
+
expect(string.find(:custom_xpath_selector, './/input', id: XPath.ends_with('box'))[:id]).to eq '2checkbox'
|
144
|
+
end
|
145
|
+
|
146
|
+
it "errors XPath expression for CSS based selectors" do
|
147
|
+
expect { string.find(:custom_css_selector, "div", id: XPath.contains('peci')) }
|
148
|
+
.to raise_error(ArgumentError, /not supported/)
|
149
|
+
end
|
124
150
|
end
|
125
151
|
|
126
152
|
context "with :class option" do
|
@@ -129,10 +155,27 @@ RSpec.describe Capybara do
|
|
129
155
|
expect(string.all(:custom_css_selector, "h1, div", class: 'a').size).to eq 2
|
130
156
|
end
|
131
157
|
|
158
|
+
it "handles negated classes" do
|
159
|
+
expect(string.all(:custom_css_selector, "div, p", class: ['b', '!c']).size).to eq 2
|
160
|
+
expect(string.all(:custom_css_selector, "div, p", class: ['!c', '!d', 'b']).size).to eq 1
|
161
|
+
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['b', '!c']).size).to eq 2
|
162
|
+
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!c', '!d', 'b']).size).to eq 1
|
163
|
+
end
|
164
|
+
|
132
165
|
it "works with 'special' characters" do
|
133
166
|
expect(string.find(:custom_css_selector, "input", class: ".special")[:id]).to eq 'file'
|
134
167
|
expect(string.find(:custom_css_selector, "input", class: "2checkbox")[:id]).to eq '2checkbox'
|
135
168
|
end
|
169
|
+
|
170
|
+
it "accepts XPath expression for xpath based selectors" do
|
171
|
+
expect(string.find(:custom_xpath_selector, './/div', class: XPath.contains('dom wor'))[:id]).to eq 'random_words'
|
172
|
+
expect(string.find(:custom_xpath_selector, './/div', class: XPath.ends_with('words'))[:id]).to eq 'random_words'
|
173
|
+
end
|
174
|
+
|
175
|
+
it "errors XPath expression for CSS based selectors" do
|
176
|
+
expect { string.find(:custom_css_selector, "div", class: XPath.contains('random')) }
|
177
|
+
.to raise_error(ArgumentError, /not supported/)
|
178
|
+
end
|
136
179
|
end
|
137
180
|
|
138
181
|
# :css, :xpath, :id, :field, :fieldset, :link, :button, :link_or_button, :fillable_field, :radio_button, :checkbox, :select,
|
@@ -208,6 +251,33 @@ RSpec.describe Capybara do
|
|
208
251
|
expect { string.find(:button, 'click me', title: 'click me') }.to raise_error(/with title click me/)
|
209
252
|
end
|
210
253
|
end
|
254
|
+
|
255
|
+
describe ":element selector" do
|
256
|
+
it "finds by any attributes" do
|
257
|
+
expect(string.find(:element, 'input', type: 'submit').value).to eq 'click me'
|
258
|
+
end
|
259
|
+
|
260
|
+
it "still works with system keys" do
|
261
|
+
expect { string.all(:element, 'input', type: 'submit', count: 1) }.not_to raise_error
|
262
|
+
end
|
263
|
+
|
264
|
+
it "includes wildcarded keys in description" do
|
265
|
+
expect { string.find(:element, 'input', not_there: 'bad', count: 1) }
|
266
|
+
.to(raise_error do |e|
|
267
|
+
expect(e).to be_a(Capybara::ElementNotFound)
|
268
|
+
expect(e.message).to include "not_there => bad"
|
269
|
+
expect(e.message).not_to include "count 1"
|
270
|
+
end)
|
271
|
+
end
|
272
|
+
|
273
|
+
it "accepts XPath::Expression" do
|
274
|
+
expect(string.find(:element, 'input', type: XPath.starts_with('subm')).value).to eq 'click me'
|
275
|
+
expect(string.find(:element, 'input', type: XPath.ends_with('ext'))[:type]).to eq 'text'
|
276
|
+
expect(string.find(:element, 'input', type: XPath.contains('ckb'))[:type]).to eq 'checkbox'
|
277
|
+
expect(string.find(:element, 'input', title: XPath.contains_word('submit'))[:type]).to eq 'submit'
|
278
|
+
expect(string.find(:element, 'input', title: XPath.contains_word('button'))[:type]).to eq 'submit'
|
279
|
+
end
|
280
|
+
end
|
211
281
|
end
|
212
282
|
end
|
213
283
|
end
|
@@ -134,11 +134,13 @@ RSpec.describe Capybara::Selenium::Driver do
|
|
134
134
|
@session.visit('/form')
|
135
135
|
@session.select('Sweden', from: 'form_region')
|
136
136
|
@session.click_button('awesome')
|
137
|
+
sleep 1
|
137
138
|
expect do
|
138
139
|
@session.accept_confirm(wait: 0.1) do
|
139
140
|
@session.refresh
|
140
141
|
sleep 2
|
141
142
|
end
|
143
|
+
sleep 1
|
142
144
|
end.to change { extract_results(@session)['post_count'] }.by(1)
|
143
145
|
end
|
144
146
|
end
|