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
@@ -51,6 +51,17 @@ Capybara::SpecHelper.spec "node" do
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
describe "#style", requires: [:css] do
|
55
|
+
it "should return the computed style value" do
|
56
|
+
expect(@session.find(:css, '#first').style('display')).to eq('display' => 'block')
|
57
|
+
expect(@session.find(:css, '#second').style(:display)).to eq('display' => 'inline')
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return multiple style values" do
|
61
|
+
expect(@session.find(:css, '#first').style('display', :'line-height')).to eq('display' => 'block', 'line-height' => '25px')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
54
65
|
describe "#value" do
|
55
66
|
it "should allow retrieval of the value" do
|
56
67
|
expect(@session.find('//textarea[@id="normal"]').value).to eq('banana')
|
@@ -185,6 +196,7 @@ Capybara::SpecHelper.spec "node" do
|
|
185
196
|
expect(@session.find('//option', text: 'Disabled Child Option')).to be_disabled
|
186
197
|
end
|
187
198
|
end
|
199
|
+
|
188
200
|
it "should be boolean" do
|
189
201
|
@session.visit('/form')
|
190
202
|
expect(@session.find('//select[@id="form_disabled_select"]/option').disabled?).to be true
|
@@ -370,6 +382,12 @@ Capybara::SpecHelper.spec "node" do
|
|
370
382
|
expect(locations[:x].to_f).to be_within(1).of(5)
|
371
383
|
expect(locations[:y].to_f).to be_within(1).of(5)
|
372
384
|
end
|
385
|
+
|
386
|
+
it "should be able to click a table row", requires: [:js] do
|
387
|
+
@session.visit('/tables')
|
388
|
+
tr = @session.find(:css, '#agent_table tr:first-child').click
|
389
|
+
expect(tr).to have_css('label', text: 'Clicked')
|
390
|
+
end
|
373
391
|
end
|
374
392
|
|
375
393
|
describe '#double_click', requires: [:js] do
|
@@ -497,9 +515,25 @@ Capybara::SpecHelper.spec "node" do
|
|
497
515
|
end
|
498
516
|
end
|
499
517
|
|
518
|
+
describe "#evaluate_async_script", requires: %i[js es_args] do
|
519
|
+
it "should evaluate the given script in the context of the element" do
|
520
|
+
@session.visit('/with_js')
|
521
|
+
el = @session.find(:css, '#with_change_event')
|
522
|
+
expect(el.evaluate_async_script("arguments[0](this.value)")).to eq('default value')
|
523
|
+
end
|
524
|
+
|
525
|
+
it "should support returning elements after asynchronous operation" do
|
526
|
+
@session.visit('/with_js')
|
527
|
+
change = @session.find(:css, '#change') # ensure page has loaded and element is available
|
528
|
+
el = change.evaluate_async_script("var cb = arguments[0]; setTimeout(function(el){ cb(el) }, 100, this)")
|
529
|
+
expect(el).to eq(change)
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
500
533
|
describe '#reload', requires: [:js] do
|
501
534
|
context "without automatic reload" do
|
502
535
|
before { Capybara.automatic_reload = false }
|
536
|
+
|
503
537
|
it "should reload the current context of the node" do
|
504
538
|
@session.visit('/with_js')
|
505
539
|
node = @session.find(:css, '#reload-me')
|
@@ -3,11 +3,13 @@
|
|
3
3
|
Capybara::SpecHelper.spec '#save_page' do
|
4
4
|
let(:alternative_path) { File.join(Dir.pwd, "save_and_open_page_tmp") }
|
5
5
|
before do
|
6
|
+
@old_save_path = Capybara.save_path
|
7
|
+
Capybara.save_path = nil
|
6
8
|
@session.visit("/foo")
|
7
9
|
end
|
8
10
|
|
9
11
|
after do
|
10
|
-
Capybara.save_path =
|
12
|
+
Capybara.save_path = @old_save_path
|
11
13
|
Dir.glob("capybara-*.html").each do |file|
|
12
14
|
FileUtils.rm(file)
|
13
15
|
end
|
@@ -67,6 +69,7 @@ Capybara::SpecHelper.spec '#save_page' do
|
|
67
69
|
|
68
70
|
context "asset_host contains a string" do
|
69
71
|
before { Capybara.asset_host = "http://example.com" }
|
72
|
+
|
70
73
|
after { Capybara.asset_host = nil }
|
71
74
|
|
72
75
|
it "prepends base tag with value from asset_host to the head" do
|
@@ -3,11 +3,13 @@
|
|
3
3
|
Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
|
4
4
|
let(:alternative_path) { File.join(Dir.pwd, "save_screenshot_tmp") }
|
5
5
|
before do
|
6
|
+
@old_save_path = Capybara.save_path
|
7
|
+
Capybara.save_path = nil
|
6
8
|
@session.visit '/foo'
|
7
9
|
end
|
8
10
|
|
9
11
|
after do
|
10
|
-
Capybara.save_path =
|
12
|
+
Capybara.save_path = @old_save_path
|
11
13
|
FileUtils.rm_rf alternative_path
|
12
14
|
end
|
13
15
|
|
@@ -5,6 +5,7 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
|
|
5
5
|
@window = @session.current_window
|
6
6
|
@session.visit('/with_windows')
|
7
7
|
end
|
8
|
+
|
8
9
|
after do
|
9
10
|
(@session.windows - [@window]).each do |w|
|
10
11
|
@session.switch_to_window w
|
@@ -112,6 +113,7 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
|
|
112
113
|
before do
|
113
114
|
@initial_size = @session.current_window.size
|
114
115
|
end
|
116
|
+
|
115
117
|
after do
|
116
118
|
@session.current_window.resize_to(*@initial_size)
|
117
119
|
sleep 0.5
|
@@ -143,6 +145,7 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
|
|
143
145
|
before do
|
144
146
|
@initial_size = @session.current_window.size
|
145
147
|
end
|
148
|
+
|
146
149
|
after do
|
147
150
|
@session.current_window.resize_to(*@initial_size)
|
148
151
|
sleep 0.5
|
@@ -181,4 +184,21 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
|
|
181
184
|
expect(ow_height).to be > 300
|
182
185
|
end
|
183
186
|
end
|
187
|
+
|
188
|
+
describe '#fullscreen' do
|
189
|
+
before do
|
190
|
+
@initial_size = @session.current_window.size
|
191
|
+
end
|
192
|
+
|
193
|
+
after do
|
194
|
+
@session.current_window.resize_to(*@initial_size)
|
195
|
+
sleep 0.5
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should be able to fullscreen the window" do
|
199
|
+
expect do
|
200
|
+
@session.current_window.fullscreen
|
201
|
+
end.not_to raise_error
|
202
|
+
end
|
203
|
+
end
|
184
204
|
end
|
@@ -59,6 +59,7 @@ Capybara::SpecHelper.spec '#within' do
|
|
59
59
|
|
60
60
|
context "with the default selector set to CSS" do
|
61
61
|
before { Capybara.default_selector = :css }
|
62
|
+
|
62
63
|
it "should use CSS" do
|
63
64
|
@session.within("#for_bar li", text: 'With Simple HTML') do
|
64
65
|
@session.click_link('Go')
|
@@ -7,6 +7,8 @@ require "capybara/rspec" # Required here instead of in rspec_spec to avoid RSpec
|
|
7
7
|
require "capybara/spec/test_app"
|
8
8
|
require "nokogiri"
|
9
9
|
|
10
|
+
Capybara.save_path = File.join(Dir.pwd, 'save_path_tmp')
|
11
|
+
|
10
12
|
module Capybara
|
11
13
|
module SpecHelper
|
12
14
|
class << self
|
@@ -15,7 +17,7 @@ module Capybara
|
|
15
17
|
config.before { Capybara::SpecHelper.reset! }
|
16
18
|
config.after { Capybara::SpecHelper.reset! }
|
17
19
|
# Test in 3.5+ where metadata doesn't autotrigger shared context inclusion - will be only behavior in RSpec 4
|
18
|
-
config.shared_context_metadata_behavior = :apply_to_host_groups if
|
20
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups if config.respond_to?(:shared_context_metadata_behavior=)
|
19
21
|
end
|
20
22
|
|
21
23
|
def reset!
|
@@ -38,6 +38,14 @@ class TestApp < Sinatra::Base
|
|
38
38
|
redirect '/landed'
|
39
39
|
end
|
40
40
|
|
41
|
+
post '/redirect_307' do
|
42
|
+
redirect '/landed', 307
|
43
|
+
end
|
44
|
+
|
45
|
+
post '/redirect_308' do
|
46
|
+
redirect '/landed', 308
|
47
|
+
end
|
48
|
+
|
41
49
|
get '/referer_base' do
|
42
50
|
'<a href="/get_referer">direct link</a>' \
|
43
51
|
'<a href="/redirect_to_get_referer">link via redirect</a>' \
|
@@ -69,6 +77,10 @@ class TestApp < Sinatra::Base
|
|
69
77
|
"You landed"
|
70
78
|
end
|
71
79
|
|
80
|
+
post '/landed' do
|
81
|
+
"You post landed: #{params.dig(:form, 'data')}"
|
82
|
+
end
|
83
|
+
|
72
84
|
get '/with-quotes' do
|
73
85
|
%q("No," he said, "you can't do that.")
|
74
86
|
end
|
@@ -153,6 +165,12 @@ class TestApp < Sinatra::Base
|
|
153
165
|
HTML
|
154
166
|
end
|
155
167
|
|
168
|
+
get '/download.csv' do
|
169
|
+
content_type "text/csv"
|
170
|
+
'This, is, comma, separated' \
|
171
|
+
'Thomas, Walpole, was , here'
|
172
|
+
end
|
173
|
+
|
156
174
|
get '/:view' do |view|
|
157
175
|
erb view.to_sym, locals: { referrer: request.referrer }
|
158
176
|
end
|
@@ -552,6 +552,14 @@ New line after and before textarea tag
|
|
552
552
|
<p>
|
553
553
|
<input type="submit" value="Go FAR"/>
|
554
554
|
</p>
|
555
|
+
|
556
|
+
<input type="hidden" name="form[data]" value="TWTW"/>
|
557
|
+
<p>
|
558
|
+
<button formaction='/redirect_307'>Go 307</button>
|
559
|
+
</p>
|
560
|
+
<p>
|
561
|
+
<button formaction='/redirect_308'>Go 308</button>
|
562
|
+
</p>
|
555
563
|
</form>
|
556
564
|
|
557
565
|
<form action="/form" method="post">
|
@@ -1,4 +1,8 @@
|
|
1
1
|
|
2
|
+
<style>
|
3
|
+
p { display: block; }
|
4
|
+
</style>
|
5
|
+
|
2
6
|
<div id="referrer"><%= referrer %></div>
|
3
7
|
<h1>This is a test</h1>
|
4
8
|
|
@@ -13,7 +17,7 @@
|
|
13
17
|
<span class="number">42</span>
|
14
18
|
<span>Other span</span>
|
15
19
|
|
16
|
-
<p class="para" id="first" data-random="abc\def">
|
20
|
+
<p class="para" id="first" data-random="abc\def" style="line-height: 25px;">
|
17
21
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
18
22
|
tempor incididunt ut <a href="/with_simple_html" title="awesome title" class="simple">labore</a>
|
19
23
|
et dolore magna aliqua. Ut enim ad minim veniam,
|
@@ -22,7 +26,7 @@
|
|
22
26
|
<a href="/with_simple_html" aria-label="Go to simple"><img id="first_image" width="20" height="20" alt="awesome image" /></a>
|
23
27
|
</p>
|
24
28
|
|
25
|
-
<p class="para" id="second">
|
29
|
+
<p class="para" id="second" style="display: inline;">
|
26
30
|
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
27
31
|
dolore eu fugiat <a href="/redirect" id="red">Redirect</a> pariatur. Excepteur sint occaecat cupidatat non proident,
|
28
32
|
sunt in culpa qui officia
|
@@ -173,3 +177,6 @@ banana</textarea>
|
|
173
177
|
<div id="ws">
|
174
178
|
                   
|
175
179
|
</div>
|
180
|
+
|
181
|
+
<a href="/download.csv" download>Download Me</a>
|
182
|
+
<a href="/download.csv" download="other.csv">Download Other</a>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
2
|
+
<head>
|
3
|
+
<title>Namespace</title>
|
4
|
+
</head>
|
5
|
+
<body id="body">
|
6
|
+
<div>
|
7
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
|
8
|
+
viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice"
|
9
|
+
style="width:100%; height:100%; position:absolute; top:0; left:0; z-index:-1;">
|
10
|
+
<linearGradient id="gradient">
|
11
|
+
<stop class="begin" offset="0%"/>
|
12
|
+
<stop class="end" offset="100%"/>
|
13
|
+
</linearGradient>
|
14
|
+
<rect x="0" y="0" width="100" height="100" style="fill:url(#gradient)" />
|
15
|
+
<rect x="150" y="150" width="25" height="25" style="fill:url(#gradient)" />
|
16
|
+
<circle cx="50" cy="50" r="30" style="fill:url(#gradient)" />
|
17
|
+
</svg>
|
18
|
+
<div>
|
19
|
+
</body>
|
20
|
+
</html>
|
data/lib/capybara/version.rb
CHANGED
data/lib/capybara/window.rb
CHANGED
@@ -101,6 +101,17 @@ module Capybara
|
|
101
101
|
wait_for_stable_size { @driver.maximize_window(handle) }
|
102
102
|
end
|
103
103
|
|
104
|
+
##
|
105
|
+
# Fullscreen window.
|
106
|
+
#
|
107
|
+
# If a particular driver doesn't have concept of fullscreen it may not support this method.
|
108
|
+
#
|
109
|
+
# @macro about_current
|
110
|
+
#
|
111
|
+
def fullscreen
|
112
|
+
@driver.fullscreen_window(handle)
|
113
|
+
end
|
114
|
+
|
104
115
|
def eql?(other)
|
105
116
|
other.is_a?(self.class) && @session == other.session && @handle == other.handle
|
106
117
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Capybara::Selector::CSS::Splitter do
|
6
|
+
let :splitter do
|
7
|
+
::Capybara::Selector::CSS::Splitter.new
|
8
|
+
end
|
9
|
+
|
10
|
+
context "split not needed" do
|
11
|
+
it "normal CSS selector" do
|
12
|
+
css = 'div[id="abc"]'
|
13
|
+
expect(splitter.split(css)).to eq [css]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "comma in strings" do
|
17
|
+
css = 'div[id="a,bc"]'
|
18
|
+
expect(splitter.split(css)).to eq [css]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "comma in pseudo-selector" do
|
22
|
+
css = 'div.class1:not(.class1, .class2)'
|
23
|
+
expect(splitter.split(css)).to eq [css]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "split needed" do
|
28
|
+
it "root level comma" do
|
29
|
+
css = 'div.class1, span, p.class2'
|
30
|
+
expect(splitter.split(css)).to eq ['div.class1', 'span', 'p.class2']
|
31
|
+
end
|
32
|
+
|
33
|
+
it "root level comma when quotes and pseudo selectors" do
|
34
|
+
css = 'div.class1[id="abc\\"def,ghi"]:not(.class3, .class4), span[id=\'a"c\\\'de\'], section, #abc\\,def'
|
35
|
+
expect(splitter.split(css)).to eq ['div.class1[id="abc\\"def,ghi"]:not(.class3, .class4)', 'span[id=\'a"c\\\'de\']', 'section', '#abc\\,def']
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/dsl_spec.rb
CHANGED
@@ -8,7 +8,7 @@ class TestClass
|
|
8
8
|
end
|
9
9
|
|
10
10
|
Capybara::SpecHelper.run_specs TestClass.new, "DSL", capybara_skip: %i[
|
11
|
-
js modals screenshot frames windows send_keys server hover about_scheme psc
|
11
|
+
js modals screenshot frames windows send_keys server hover about_scheme psc download css
|
12
12
|
]
|
13
13
|
|
14
14
|
RSpec.describe Capybara::DSL do
|
data/spec/minitest_spec.rb
CHANGED
@@ -112,6 +112,12 @@ class MinitestTest < Minitest::Test
|
|
112
112
|
assert_matches_xpath(find(:select, 'form_title'), './/select[@id="form_title"]')
|
113
113
|
refute_matches_xpath(find(:select, 'form_title'), './/select[@id="form_other_title"]')
|
114
114
|
end
|
115
|
+
|
116
|
+
def test_assert_style
|
117
|
+
skip "Rack test doesn't support style" if Capybara.current_driver == :rack_test
|
118
|
+
visit('/with_html')
|
119
|
+
assert_style(find(:css, '#second'), display: 'inline')
|
120
|
+
end
|
115
121
|
end
|
116
122
|
|
117
123
|
RSpec.describe 'capybara/minitest' do
|
@@ -126,6 +132,6 @@ RSpec.describe 'capybara/minitest' do
|
|
126
132
|
reporter.start
|
127
133
|
MinitestTest.run reporter, {}
|
128
134
|
reporter.report
|
129
|
-
expect(output.string).to include("
|
135
|
+
expect(output.string).to include("18 runs, 44 assertions, 0 failures, 0 errors, 1 skips")
|
130
136
|
end
|
131
137
|
end
|