capybara 3.8.0 → 3.9.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 +25 -1
- data/lib/capybara/config.rb +1 -0
- data/lib/capybara/dsl.rb +2 -2
- data/lib/capybara/helpers.rb +1 -0
- data/lib/capybara/node/actions.rb +4 -0
- data/lib/capybara/node/base.rb +1 -0
- data/lib/capybara/node/element.rb +3 -0
- data/lib/capybara/node/finders.rb +2 -0
- data/lib/capybara/node/simple.rb +1 -0
- data/lib/capybara/queries/base_query.rb +1 -0
- data/lib/capybara/queries/match_query.rb +1 -0
- data/lib/capybara/queries/selector_query.rb +34 -37
- data/lib/capybara/queries/text_query.rb +2 -0
- data/lib/capybara/rack_test/browser.rb +1 -0
- data/lib/capybara/rack_test/driver.rb +5 -0
- data/lib/capybara/rack_test/node.rb +2 -0
- data/lib/capybara/result.rb +2 -0
- data/lib/capybara/rspec/compound.rb +2 -0
- data/lib/capybara/rspec/matchers.rb +1 -0
- data/lib/capybara/selector/builders/css_builder.rb +49 -0
- data/lib/capybara/selector/builders/xpath_builder.rb +56 -0
- data/lib/capybara/selector/filter_set.rb +1 -0
- data/lib/capybara/selector/filters/base.rb +2 -0
- data/lib/capybara/selector/regexp_disassembler.rb +66 -0
- data/lib/capybara/selector/selector.rb +25 -5
- data/lib/capybara/selector.rb +14 -27
- data/lib/capybara/selenium/driver.rb +8 -1
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +19 -1
- data/lib/capybara/selenium/driver_specializations/marionette_driver.rb +1 -0
- data/lib/capybara/selenium/node.rb +11 -0
- data/lib/capybara/selenium/nodes/chrome_node.rb +2 -0
- data/lib/capybara/selenium/nodes/marionette_node.rb +37 -20
- data/lib/capybara/server/animation_disabler.rb +1 -0
- data/lib/capybara/server.rb +4 -0
- data/lib/capybara/session/config.rb +2 -0
- data/lib/capybara/session.rb +5 -0
- data/lib/capybara/spec/session/has_css_spec.rb +16 -0
- data/lib/capybara/spec/session/has_field_spec.rb +4 -0
- data/lib/capybara/spec/session/node_spec.rb +6 -0
- data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
- data/lib/capybara/spec/session/reset_session_spec.rb +15 -1
- data/lib/capybara/spec/session/selectors_spec.rb +12 -2
- data/lib/capybara/spec/views/form.erb +15 -0
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/xpath_patches.rb +27 -0
- data/lib/capybara.rb +32 -10
- data/spec/dsl_spec.rb +15 -1
- data/spec/rack_test_spec.rb +6 -1
- data/spec/regexp_dissassembler_spec.rb +154 -0
- data/spec/selector_spec.rb +53 -18
- data/spec/selenium_spec_chrome.rb +28 -0
- data/spec/selenium_spec_firefox_remote.rb +2 -0
- data/spec/selenium_spec_marionette.rb +11 -0
- data/spec/shared_selenium_session.rb +20 -0
- data/spec/spec_helper.rb +4 -0
- metadata +7 -2
data/lib/capybara.rb
CHANGED
|
@@ -299,7 +299,7 @@ module Capybara
|
|
|
299
299
|
# @return [Capybara::Session] The currently used session
|
|
300
300
|
#
|
|
301
301
|
def current_session
|
|
302
|
-
session_pool["#{current_driver}:#{session_name}:#{app.object_id}"]
|
|
302
|
+
specified_session || session_pool["#{current_driver}:#{session_name}:#{app.object_id}"]
|
|
303
303
|
end
|
|
304
304
|
|
|
305
305
|
##
|
|
@@ -337,22 +337,25 @@ module Capybara
|
|
|
337
337
|
|
|
338
338
|
##
|
|
339
339
|
#
|
|
340
|
-
# Yield a block using a specific session name.
|
|
340
|
+
# Yield a block using a specific session name or Capybara::Session instance.
|
|
341
341
|
#
|
|
342
|
-
def using_session(
|
|
342
|
+
def using_session(name_or_session)
|
|
343
343
|
previous_session_info = {
|
|
344
|
+
specified_session: specified_session,
|
|
344
345
|
session_name: session_name,
|
|
345
346
|
current_driver: current_driver,
|
|
346
347
|
app: app
|
|
347
348
|
}
|
|
348
|
-
self.session_name =
|
|
349
|
+
self.specified_session = self.session_name = nil
|
|
350
|
+
if name_or_session.is_a? Capybara::Session
|
|
351
|
+
self.specified_session = name_or_session
|
|
352
|
+
else
|
|
353
|
+
self.session_name = name_or_session
|
|
354
|
+
end
|
|
349
355
|
yield
|
|
350
356
|
ensure
|
|
351
|
-
self.session_name = previous_session_info
|
|
352
|
-
if threadsafe
|
|
353
|
-
self.current_driver = previous_session_info[:current_driver]
|
|
354
|
-
self.app = previous_session_info[:app]
|
|
355
|
-
end
|
|
357
|
+
self.session_name, self.specified_session = previous_session_info.values_at(:session_name, :specified_session)
|
|
358
|
+
self.current_driver, self.app = previous_session_info.values_at(:current_driver, :app) if threadsafe
|
|
356
359
|
end
|
|
357
360
|
|
|
358
361
|
##
|
|
@@ -381,7 +384,25 @@ module Capybara
|
|
|
381
384
|
end
|
|
382
385
|
|
|
383
386
|
def session_pool
|
|
384
|
-
@session_pool ||=
|
|
387
|
+
@session_pool ||= Hash.new do |hash, name|
|
|
388
|
+
hash[name] = Capybara::Session.new(current_driver, app)
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def specified_session
|
|
393
|
+
if threadsafe
|
|
394
|
+
Thread.current['capybara_specified_session']
|
|
395
|
+
else
|
|
396
|
+
@specified_session
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def specified_session=(session)
|
|
401
|
+
if threadsafe
|
|
402
|
+
Thread.current['capybara_specified_session'] = session
|
|
403
|
+
else
|
|
404
|
+
@specified_session = session
|
|
405
|
+
end
|
|
385
406
|
end
|
|
386
407
|
end
|
|
387
408
|
|
|
@@ -393,6 +414,7 @@ module Capybara
|
|
|
393
414
|
module RackTest; end
|
|
394
415
|
module Selenium; end
|
|
395
416
|
|
|
417
|
+
require 'capybara/xpath_patches'
|
|
396
418
|
require 'capybara/helpers'
|
|
397
419
|
require 'capybara/session'
|
|
398
420
|
require 'capybara/window'
|
data/spec/dsl_spec.rb
CHANGED
|
@@ -9,7 +9,12 @@ end
|
|
|
9
9
|
|
|
10
10
|
Capybara::SpecHelper.run_specs TestClass.new, 'DSL', capybara_skip: %i[
|
|
11
11
|
js modals screenshot frames windows send_keys server hover about_scheme psc download css driver
|
|
12
|
-
]
|
|
12
|
+
] do |example|
|
|
13
|
+
case example.metadata[:full_description]
|
|
14
|
+
when /has_css\? should support case insensitive :class and :id options/
|
|
15
|
+
pending "Nokogiri doesn't support case insensitive CSS attribute matchers"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
13
18
|
|
|
14
19
|
RSpec.describe Capybara::DSL do
|
|
15
20
|
after do
|
|
@@ -224,6 +229,15 @@ RSpec.describe Capybara::DSL do
|
|
|
224
229
|
end
|
|
225
230
|
expect(Capybara.session_name).to eq(:default)
|
|
226
231
|
end
|
|
232
|
+
|
|
233
|
+
it 'should allow a session object' do
|
|
234
|
+
original_session = Capybara.current_session
|
|
235
|
+
new_session = Capybara::Session.new(:rack_test, proc {})
|
|
236
|
+
Capybara.using_session(new_session) do
|
|
237
|
+
expect(Capybara.current_session).to eq(new_session)
|
|
238
|
+
end
|
|
239
|
+
expect(Capybara.current_session).to eq(original_session)
|
|
240
|
+
end
|
|
227
241
|
end
|
|
228
242
|
|
|
229
243
|
describe '#session_name' do
|
data/spec/rack_test_spec.rb
CHANGED
|
@@ -19,7 +19,12 @@ skipped_tests = %i[
|
|
|
19
19
|
download
|
|
20
20
|
css
|
|
21
21
|
]
|
|
22
|
-
Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip: skipped_tests
|
|
22
|
+
Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip: skipped_tests do |example|
|
|
23
|
+
case example.metadata[:full_description]
|
|
24
|
+
when /has_css\? should support case insensitive :class and :id options/
|
|
25
|
+
pending "Nokogiri doesn't support case insensitive CSS attribute matchers"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
23
28
|
|
|
24
29
|
RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
|
|
25
30
|
context 'with rack test driver' do
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Capybara::Selector::RegexpDisassembler do
|
|
6
|
+
it 'handles strings' do
|
|
7
|
+
verify_strings(
|
|
8
|
+
/abcdef/ => %w[abcdef],
|
|
9
|
+
/abc def/ => ['abc def']
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'handles escaped characters' do
|
|
14
|
+
verify_strings(
|
|
15
|
+
/abc\\def/ => %w[abc def],
|
|
16
|
+
/\nabc/ => %w[abc],
|
|
17
|
+
%r{abc/} => %w[abc/]
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'handles wildcards' do
|
|
22
|
+
verify_strings(
|
|
23
|
+
/abc.*def/ => %w[abc def],
|
|
24
|
+
/.*def/ => %w[def],
|
|
25
|
+
/abc./ => %w[abc],
|
|
26
|
+
/abc.*/ => %w[abc],
|
|
27
|
+
/abc.def/ => %w[abc def],
|
|
28
|
+
/abc.def.ghi/ => %w[abc def ghi]
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'handles optional characters' do
|
|
33
|
+
verify_strings(
|
|
34
|
+
/abc*def/ => %w[ab def],
|
|
35
|
+
/abc*/ => %w[ab],
|
|
36
|
+
/abc?def/ => %w[ab def],
|
|
37
|
+
/abc?/ => %w[ab],
|
|
38
|
+
/abc?def?/ => %w[ab de],
|
|
39
|
+
/abc?def?g/ => %w[ab de g]
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'handles character classes' do
|
|
44
|
+
verify_strings(
|
|
45
|
+
/abc[a-z]/ => %w[abc],
|
|
46
|
+
/abc[a-z]def[0-9]g/ => %w[abc def g],
|
|
47
|
+
/[0-9]abc/ => %w[abc],
|
|
48
|
+
/[0-9]+/ => %w[],
|
|
49
|
+
/abc[0-9&&[^7]]/ => %w[abc]
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'handles posix bracket expressions' do
|
|
54
|
+
verify_strings(
|
|
55
|
+
/abc[[:alpha:]]/ => %w[abc],
|
|
56
|
+
/[[:digit:]]abc/ => %w[abc],
|
|
57
|
+
/abc[[:print:]]def/ => %w[abc def]
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'handles repitition' do
|
|
62
|
+
verify_strings(
|
|
63
|
+
/abc{3}/ => %w[abccc],
|
|
64
|
+
/abc{3}d/ => %w[abcccd],
|
|
65
|
+
/abc{0}/ => %w[ab],
|
|
66
|
+
/abc{,2}/ => %w[ab],
|
|
67
|
+
/abc{2,}/ => %w[abcc],
|
|
68
|
+
/def{1,5}/ => %w[def],
|
|
69
|
+
/abc+def/ => %w[abc def],
|
|
70
|
+
/ab(cde){,4}/ => %w[ab],
|
|
71
|
+
/(ab){,2}cd/ => %w[cd],
|
|
72
|
+
/(abc){2,3}/ => %w[abcabc],
|
|
73
|
+
/(abc){3}/ => %w[abcabcabc],
|
|
74
|
+
/ab{2,3}cd/ => %w[abb cd],
|
|
75
|
+
/(ab){2,3}cd/ => %w[abab cd]
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'handles non-greedy repetition' do
|
|
80
|
+
verify_strings(
|
|
81
|
+
/abc.*?/ => %w[abc],
|
|
82
|
+
/abc+?/ => %w[abc],
|
|
83
|
+
/abc*?cde/ => %w[ab cde],
|
|
84
|
+
/(abc)+?def/ => %w[abc def],
|
|
85
|
+
/ab(cde)*?fg/ => %w[ab fg]
|
|
86
|
+
)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'handles alternation' do
|
|
90
|
+
verify_strings(
|
|
91
|
+
/abc|def/ => [],
|
|
92
|
+
/ab(?:c|d)/ => %w[ab],
|
|
93
|
+
/ab(c|d)ef/ => %w[ab ef]
|
|
94
|
+
)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'handles grouping' do
|
|
98
|
+
verify_strings(
|
|
99
|
+
/(abc)/ => %w[abc],
|
|
100
|
+
/(abc)?/ => [],
|
|
101
|
+
/ab(cde)/ => %w[abcde],
|
|
102
|
+
/(abc)de/ => %w[abcde],
|
|
103
|
+
/ab(cde)fg/ => %w[abcdefg],
|
|
104
|
+
/ab(?<name>cd)ef/ => %w[abcdef],
|
|
105
|
+
/gh(?>ij)kl/ => %w[ghijkl],
|
|
106
|
+
/m(n.*p)q/ => %w[mn pq],
|
|
107
|
+
/(?:ab(cd)*){2,3}/ => %w[ab],
|
|
108
|
+
/(ab(cd){3})?/ => [],
|
|
109
|
+
/(ab(cd)+){2}/ => %w[abcd]
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'handles meta characters' do
|
|
114
|
+
verify_strings(
|
|
115
|
+
/abc\d/ => %w[abc],
|
|
116
|
+
/abc\wdef/ => %w[abc def],
|
|
117
|
+
/\habc/ => %w[abc]
|
|
118
|
+
)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'handles character properties' do
|
|
122
|
+
verify_strings(
|
|
123
|
+
/ab\p{Alpha}cd/ => %w[ab cd],
|
|
124
|
+
/ab\p{Blank}/ => %w[ab],
|
|
125
|
+
/\p{Digit}cd/ => %w[cd]
|
|
126
|
+
)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'handles backreferences' do
|
|
130
|
+
verify_strings(
|
|
131
|
+
/a(?<group>abc).\k<group>.+/ => %w[aabc]
|
|
132
|
+
)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it 'handles subexpressions' do
|
|
136
|
+
verify_strings(
|
|
137
|
+
/\A(?<paren>a\g<paren>*b)+\z/ => %w[a b]
|
|
138
|
+
)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it 'handles anchors' do
|
|
142
|
+
verify_strings(
|
|
143
|
+
/^abc/ => %w[abc],
|
|
144
|
+
/def$/ => %w[def],
|
|
145
|
+
/^abc$/ => %w[abc]
|
|
146
|
+
)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def verify_strings(hsh)
|
|
150
|
+
hsh.each do |regexp, expected|
|
|
151
|
+
expect(Capybara::Selector::RegexpDisassembler.new(regexp).substrings).to eq expected
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
data/spec/selector_spec.rb
CHANGED
|
@@ -11,13 +11,13 @@ RSpec.describe Capybara do
|
|
|
11
11
|
<title>selectors</title>
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
|
-
<div class="
|
|
15
|
-
<div class="
|
|
16
|
-
<h1 class="
|
|
14
|
+
<div class="aa" id="page">
|
|
15
|
+
<div class="bb" id="content">
|
|
16
|
+
<h1 class="aa">Totally awesome</h1>
|
|
17
17
|
<p>Yes it is</p>
|
|
18
18
|
</div>
|
|
19
|
-
<p class="
|
|
20
|
-
<p class="
|
|
19
|
+
<p class="bb cc">Some Content</p>
|
|
20
|
+
<p class="bb dd"></p>
|
|
21
21
|
</div>
|
|
22
22
|
<div id="#special">
|
|
23
23
|
</div>
|
|
@@ -31,6 +31,7 @@ RSpec.describe Capybara do
|
|
|
31
31
|
<input type="file" id="file" class=".special file"/>
|
|
32
32
|
<input type="hidden" id="hidden_field" value="this is hidden"/>
|
|
33
33
|
<input type="submit" value="click me" title="submit button"/>
|
|
34
|
+
<input type="button" value="don't click me" title="Other button 1"/>
|
|
34
35
|
<a href="#">link</a>
|
|
35
36
|
<fieldset></fieldset>
|
|
36
37
|
<select id="select">
|
|
@@ -84,12 +85,12 @@ RSpec.describe Capybara do
|
|
|
84
85
|
|
|
85
86
|
describe 'modify_selector' do
|
|
86
87
|
it 'allows modifying a selector' do
|
|
87
|
-
el = string.find(:custom_selector, '
|
|
88
|
+
el = string.find(:custom_selector, 'aa')
|
|
88
89
|
expect(el.tag_name).to eq 'div'
|
|
89
90
|
Capybara.modify_selector :custom_selector do
|
|
90
91
|
css { |css_class| "h1.#{css_class}" }
|
|
91
92
|
end
|
|
92
|
-
el = string.find(:custom_selector, '
|
|
93
|
+
el = string.find(:custom_selector, 'aa')
|
|
93
94
|
expect(el.tag_name).to eq 'h1'
|
|
94
95
|
end
|
|
95
96
|
|
|
@@ -97,9 +98,9 @@ RSpec.describe Capybara do
|
|
|
97
98
|
Capybara.modify_selector :custom_selector do
|
|
98
99
|
css { |css_class| "p.#{css_class}" }
|
|
99
100
|
end
|
|
100
|
-
expect(string).to have_selector(:custom_selector, '
|
|
101
|
-
expect(string).to have_selector(:custom_selector, '
|
|
102
|
-
expect(string).to have_selector(:custom_selector, '
|
|
101
|
+
expect(string).to have_selector(:custom_selector, 'bb', count: 1)
|
|
102
|
+
expect(string).to have_selector(:custom_selector, 'bb', not_empty: false, count: 1)
|
|
103
|
+
expect(string).to have_selector(:custom_selector, 'bb', not_empty: :all, count: 2)
|
|
103
104
|
end
|
|
104
105
|
end
|
|
105
106
|
|
|
@@ -147,19 +148,28 @@ RSpec.describe Capybara do
|
|
|
147
148
|
expect { string.find(:custom_css_selector, 'div', id: XPath.contains('peci')) }
|
|
148
149
|
.to raise_error(ArgumentError, /not supported/)
|
|
149
150
|
end
|
|
151
|
+
|
|
152
|
+
it 'accepts Regexp for xpath based selectors' do
|
|
153
|
+
expect(string.find(:custom_xpath_selector, './/div', id: /peci/)[:id]).to eq '#special'
|
|
154
|
+
expect(string.find(:custom_xpath_selector, './/div', id: /pEcI/i)[:id]).to eq '#special'
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'accepts Regexp for css based selectors' do
|
|
158
|
+
expect(string.find(:custom_css_selector, 'div', id: /sp.*al/)[:id]).to eq '#special'
|
|
159
|
+
end
|
|
150
160
|
end
|
|
151
161
|
|
|
152
162
|
context 'with :class option' do
|
|
153
163
|
it 'works with compound css selectors' do
|
|
154
|
-
expect(string.all(:custom_css_selector, 'div, h1', class: '
|
|
155
|
-
expect(string.all(:custom_css_selector, 'h1, div', class: '
|
|
164
|
+
expect(string.all(:custom_css_selector, 'div, h1', class: 'aa').size).to eq 2
|
|
165
|
+
expect(string.all(:custom_css_selector, 'h1, div', class: 'aa').size).to eq 2
|
|
156
166
|
end
|
|
157
167
|
|
|
158
168
|
it 'handles negated classes' do
|
|
159
|
-
expect(string.all(:custom_css_selector, 'div, p', class: ['
|
|
160
|
-
expect(string.all(:custom_css_selector, 'div, p', class: ['!
|
|
161
|
-
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['
|
|
162
|
-
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!
|
|
169
|
+
expect(string.all(:custom_css_selector, 'div, p', class: ['bb', '!cc']).size).to eq 2
|
|
170
|
+
expect(string.all(:custom_css_selector, 'div, p', class: ['!cc', '!dd', 'bb']).size).to eq 1
|
|
171
|
+
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['bb', '!cc']).size).to eq 2
|
|
172
|
+
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!cc', '!dd', 'bb']).size).to eq 1
|
|
163
173
|
end
|
|
164
174
|
|
|
165
175
|
it "works with 'special' characters" do
|
|
@@ -176,6 +186,15 @@ RSpec.describe Capybara do
|
|
|
176
186
|
expect { string.find(:custom_css_selector, 'div', class: XPath.contains('random')) }
|
|
177
187
|
.to raise_error(ArgumentError, /not supported/)
|
|
178
188
|
end
|
|
189
|
+
|
|
190
|
+
it 'accepts Regexp for XPath based selectors' do
|
|
191
|
+
expect(string.find(:custom_xpath_selector, './/div', class: /dom wor/)[:id]).to eq 'random_words'
|
|
192
|
+
expect(string.find(:custom_xpath_selector, './/div', class: /dOm WoR/i)[:id]).to eq 'random_words'
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it 'accepts Regexp for CSS base selectors' do
|
|
196
|
+
expect(string.find(:custom_css_selector, 'div', class: /random/)[:id]).to eq 'random_words'
|
|
197
|
+
end
|
|
179
198
|
end
|
|
180
199
|
|
|
181
200
|
# :css, :xpath, :id, :field, :fieldset, :link, :button, :link_or_button, :fillable_field, :radio_button, :checkbox, :select,
|
|
@@ -206,10 +225,14 @@ RSpec.describe Capybara do
|
|
|
206
225
|
expect(string.find(:field, 'form[my_text_input]')[:id]).to eq 'my_text_input'
|
|
207
226
|
end
|
|
208
227
|
|
|
209
|
-
it 'finds by id' do
|
|
228
|
+
it 'finds by id string' do
|
|
210
229
|
expect(string.find(:field, id: 'my_text_input')[:name]).to eq 'form[my_text_input]'
|
|
211
230
|
end
|
|
212
231
|
|
|
232
|
+
it 'finds by id regexp' do
|
|
233
|
+
expect(string.find(:field, id: /my_text_inp/)[:name]).to eq 'form[my_text_input]'
|
|
234
|
+
end
|
|
235
|
+
|
|
213
236
|
it 'finds by name' do
|
|
214
237
|
expect(string.find(:field, name: 'form[my_text_input]')[:id]).to eq 'my_text_input'
|
|
215
238
|
end
|
|
@@ -257,6 +280,18 @@ RSpec.describe Capybara do
|
|
|
257
280
|
expect(string.find(:element, 'input', type: 'submit').value).to eq 'click me'
|
|
258
281
|
end
|
|
259
282
|
|
|
283
|
+
it 'supports regexp matching' do
|
|
284
|
+
expect(string.find(:element, 'input', type: /sub/).value).to eq 'click me'
|
|
285
|
+
expect(string.find(:element, 'input', title: /sub\w.*button/).value).to eq 'click me'
|
|
286
|
+
expect(string.find(:element, 'input', title: /sub.* b.*ton/).value).to eq 'click me'
|
|
287
|
+
expect(string.find(:element, 'input', title: /sub.*mit.*/).value).to eq 'click me'
|
|
288
|
+
expect(string.find(:element, 'input', title: /^submit button$/).value).to eq 'click me'
|
|
289
|
+
expect(string.find(:element, 'input', title: /^(?:submit|other) button$/).value).to eq 'click me'
|
|
290
|
+
expect(string.find(:element, 'input', title: /SuB.*mIt/i).value).to eq 'click me'
|
|
291
|
+
expect(string.find(:element, 'input', title: /^Su.*Bm.*It/i).value).to eq 'click me'
|
|
292
|
+
expect(string.find(:element, 'input', title: /^Ot.*he.*r b.*\d/i).value).to eq "don't click me"
|
|
293
|
+
end
|
|
294
|
+
|
|
260
295
|
it 'still works with system keys' do
|
|
261
296
|
expect { string.all(:element, 'input', type: 'submit', count: 1) }.not_to raise_error
|
|
262
297
|
end
|
|
@@ -289,7 +324,7 @@ RSpec.describe Capybara do
|
|
|
289
324
|
expect(string.find(:element, 'input', type: XPath.ends_with('ext'))[:type]).to eq 'text'
|
|
290
325
|
expect(string.find(:element, 'input', type: XPath.contains('ckb'))[:type]).to eq 'checkbox'
|
|
291
326
|
expect(string.find(:element, 'input', title: XPath.contains_word('submit'))[:type]).to eq 'submit'
|
|
292
|
-
expect(string.find(:element, 'input', title: XPath.contains_word('button'))[:type]).to eq '
|
|
327
|
+
expect(string.find(:element, 'input', title: XPath.contains_word('button 1'))[:type]).to eq 'button'
|
|
293
328
|
end
|
|
294
329
|
end
|
|
295
330
|
end
|
|
@@ -84,4 +84,32 @@ RSpec.describe 'Capybara::Session with chrome' do
|
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
|
+
|
|
88
|
+
describe 'filling in Chrome-specific date and time fields with keystrokes' do
|
|
89
|
+
let(:datetime) { Time.new(1983, 6, 19, 6, 30) }
|
|
90
|
+
|
|
91
|
+
before do
|
|
92
|
+
@session = TestSessions::Chrome
|
|
93
|
+
@session.visit('/form')
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'should fill in a date input with a String' do
|
|
97
|
+
@session.fill_in('form_date', with: '06/19/1983')
|
|
98
|
+
@session.click_button('awesome')
|
|
99
|
+
expect(Date.parse(extract_results(@session)['date'])).to eq datetime.to_date
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'should fill in a time input with a String' do
|
|
103
|
+
@session.fill_in('form_time', with: '06:30A')
|
|
104
|
+
@session.click_button('awesome')
|
|
105
|
+
results = extract_results(@session)['time']
|
|
106
|
+
expect(Time.parse(results).strftime('%r')).to eq datetime.strftime('%r')
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'should fill in a datetime input with a String' do
|
|
110
|
+
@session.fill_in('form_datetime', with: "06/19/1983\t06:30A")
|
|
111
|
+
@session.click_button('awesome')
|
|
112
|
+
expect(Time.parse(extract_results(@session)['datetime'])).to eq datetime
|
|
113
|
+
end
|
|
114
|
+
end
|
|
87
115
|
end
|
|
@@ -69,6 +69,8 @@ Capybara::SpecHelper.run_specs TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVE
|
|
|
69
69
|
'if files are already set'
|
|
70
70
|
when 'Capybara::Session selenium_firefox_remote #attach_file with multipart form should fire change once when uploading multiple files from empty'
|
|
71
71
|
pending "FF < 62 doesn't support setting all files at once" if marionette_lt?(62, @session)
|
|
72
|
+
when 'Capybara::Session selenium_firefox_remote #reset_session! removes ALL cookies'
|
|
73
|
+
pending "Geckodriver doesn't provide a way to remove cookies outside the current domain"
|
|
72
74
|
end
|
|
73
75
|
end
|
|
74
76
|
|
|
@@ -65,6 +65,8 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumMarionette, 'selenium', cap
|
|
|
65
65
|
skip 'Broken in FF 63 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if marionette_gte?(63, @session)
|
|
66
66
|
when 'Capybara::Session selenium #click_link can download a file'
|
|
67
67
|
skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
|
|
68
|
+
when 'Capybara::Session selenium #reset_session! removes ALL cookies'
|
|
69
|
+
pending "Geckodriver doesn't provide a way to remove cookies outside the current domain"
|
|
68
70
|
end
|
|
69
71
|
end
|
|
70
72
|
|
|
@@ -169,4 +171,13 @@ RSpec.describe Capybara::Selenium::Node do
|
|
|
169
171
|
expect(session).to have_link('Has been alt control meta')
|
|
170
172
|
end
|
|
171
173
|
end
|
|
174
|
+
|
|
175
|
+
context '#send_keys' do
|
|
176
|
+
it 'should process space' do
|
|
177
|
+
session = TestSessions::SeleniumMarionette
|
|
178
|
+
session.visit('/form')
|
|
179
|
+
session.find(:css, '#address1_city').send_keys('ocean', [:shift, :space, 'side'])
|
|
180
|
+
expect(session.find(:css, '#address1_city').value).to eq 'ocean SIDE'
|
|
181
|
+
end
|
|
182
|
+
end
|
|
172
183
|
end
|
|
@@ -334,6 +334,20 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
|
334
334
|
end
|
|
335
335
|
end
|
|
336
336
|
|
|
337
|
+
describe 'Capybara#Node#attach_file' do
|
|
338
|
+
it 'can attach a directory' do
|
|
339
|
+
pending "Geckodriver doesn't support uploading a directory" if marionette?(session)
|
|
340
|
+
pending "Selenium remote doesn't support transferring a directory" if remote?(session)
|
|
341
|
+
pending "Headless Chrome doesn't support directory upload - https://bugs.chromium.org/p/chromedriver/issues/detail?id=2521&q=directory%20upload&colspec=ID%20Status%20Pri%20Owner%20Summary" if chrome?(session) && ENV['HEADLESS']
|
|
342
|
+
|
|
343
|
+
session.visit('/form')
|
|
344
|
+
@test_file_dir = File.expand_path('./fixtures', File.dirname(__FILE__))
|
|
345
|
+
session.attach_file('Directory Upload', @test_file_dir)
|
|
346
|
+
session.click_button('Upload Multiple')
|
|
347
|
+
expect(session.body).to include('5 | ') # number of files
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
337
351
|
context 'Windows' do
|
|
338
352
|
it "can't close the primary window" do
|
|
339
353
|
expect do
|
|
@@ -431,6 +445,12 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
|
431
445
|
expect(session).to have_selector(:element, :circle)
|
|
432
446
|
expect(session).to have_selector(:element, :linearGradient, visible: :all)
|
|
433
447
|
end
|
|
448
|
+
|
|
449
|
+
it 'can query attributes with strange characters' do
|
|
450
|
+
session.visit('/form')
|
|
451
|
+
expect(session).to have_selector(:element, "{custom}": true)
|
|
452
|
+
expect(session).to have_selector(:element, "{custom}": 'abcdef')
|
|
453
|
+
end
|
|
434
454
|
end
|
|
435
455
|
end
|
|
436
456
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: capybara
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Thomas Walpole
|
|
@@ -10,7 +10,7 @@ autorequire:
|
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain:
|
|
12
12
|
- gem-public_cert.pem
|
|
13
|
-
date: 2018-
|
|
13
|
+
date: 2018-10-03 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: addressable
|
|
@@ -301,12 +301,15 @@ files:
|
|
|
301
301
|
- lib/capybara/rspec/matcher_proxies.rb
|
|
302
302
|
- lib/capybara/rspec/matchers.rb
|
|
303
303
|
- lib/capybara/selector.rb
|
|
304
|
+
- lib/capybara/selector/builders/css_builder.rb
|
|
305
|
+
- lib/capybara/selector/builders/xpath_builder.rb
|
|
304
306
|
- lib/capybara/selector/css.rb
|
|
305
307
|
- lib/capybara/selector/filter.rb
|
|
306
308
|
- lib/capybara/selector/filter_set.rb
|
|
307
309
|
- lib/capybara/selector/filters/base.rb
|
|
308
310
|
- lib/capybara/selector/filters/expression_filter.rb
|
|
309
311
|
- lib/capybara/selector/filters/node_filter.rb
|
|
312
|
+
- lib/capybara/selector/regexp_disassembler.rb
|
|
310
313
|
- lib/capybara/selector/selector.rb
|
|
311
314
|
- lib/capybara/selenium/driver.rb
|
|
312
315
|
- lib/capybara/selenium/driver_specializations/chrome_driver.rb
|
|
@@ -452,6 +455,7 @@ files:
|
|
|
452
455
|
- lib/capybara/spec/views/within_frames.erb
|
|
453
456
|
- lib/capybara/version.rb
|
|
454
457
|
- lib/capybara/window.rb
|
|
458
|
+
- lib/capybara/xpath_patches.rb
|
|
455
459
|
- spec/basic_node_spec.rb
|
|
456
460
|
- spec/capybara_spec.rb
|
|
457
461
|
- spec/css_splitter_spec.rb
|
|
@@ -466,6 +470,7 @@ files:
|
|
|
466
470
|
- spec/minitest_spec_spec.rb
|
|
467
471
|
- spec/per_session_config_spec.rb
|
|
468
472
|
- spec/rack_test_spec.rb
|
|
473
|
+
- spec/regexp_dissassembler_spec.rb
|
|
469
474
|
- spec/result_spec.rb
|
|
470
475
|
- spec/rspec/features_spec.rb
|
|
471
476
|
- spec/rspec/scenarios_spec.rb
|