capybara 3.1.1 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|