capybara 3.9.0 → 3.10.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 +15 -0
- data/License.txt +1 -1
- data/README.md +1 -1
- data/lib/capybara.rb +1 -2
- data/lib/capybara/helpers.rb +3 -2
- data/lib/capybara/minitest.rb +1 -1
- data/lib/capybara/minitest/spec.rb +1 -0
- data/lib/capybara/node/finders.rb +20 -15
- data/lib/capybara/node/matchers.rb +43 -10
- data/lib/capybara/queries/current_path_query.rb +2 -2
- data/lib/capybara/queries/selector_query.rb +9 -2
- data/lib/capybara/rack_test/browser.rb +14 -13
- data/lib/capybara/rack_test/form.rb +32 -27
- data/lib/capybara/result.rb +8 -11
- data/lib/capybara/rspec/compound.rb +16 -26
- data/lib/capybara/rspec/matcher_proxies.rb +28 -11
- data/lib/capybara/rspec/matchers.rb +67 -45
- data/lib/capybara/selector.rb +22 -25
- data/lib/capybara/selector/builders/css_builder.rb +3 -4
- data/lib/capybara/selector/builders/xpath_builder.rb +4 -6
- data/lib/capybara/selector/regexp_disassembler.rb +43 -44
- data/lib/capybara/selector/selector.rb +16 -11
- data/lib/capybara/selenium/driver.rb +28 -21
- data/lib/capybara/selenium/nodes/marionette_node.rb +6 -12
- data/lib/capybara/server.rb +1 -3
- data/lib/capybara/server/animation_disabler.rb +2 -2
- data/lib/capybara/session.rb +1 -1
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +29 -0
- data/lib/capybara/spec/session/click_button_spec.rb +6 -0
- data/lib/capybara/spec/session/click_link_spec.rb +1 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +1 -1
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
- data/lib/capybara/spec/session/html_spec.rb +7 -0
- data/lib/capybara/spec/session/node_spec.rb +5 -1
- data/lib/capybara/spec/session/refresh_spec.rb +4 -0
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +4 -0
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +4 -0
- data/lib/capybara/spec/session/window/window_spec.rb +4 -0
- data/lib/capybara/spec/session/window/windows_spec.rb +4 -0
- data/lib/capybara/spec/views/form.erb +2 -2
- data/lib/capybara/version.rb +1 -1
- data/spec/minitest_spec.rb +5 -1
- data/spec/minitest_spec_spec.rb +5 -1
- data/spec/regexp_dissassembler_spec.rb +5 -3
- data/spec/rspec_spec.rb +20 -0
- data/spec/selector_spec.rb +89 -3
- data/spec/selenium_spec_chrome.rb +3 -7
- data/spec/selenium_spec_marionette.rb +1 -4
- metadata +20 -6
- data/lib/capybara/xpath_patches.rb +0 -27
@@ -26,16 +26,14 @@ module Capybara
|
|
26
26
|
|
27
27
|
def class_conditions(classes)
|
28
28
|
case classes
|
29
|
-
when XPath::Expression
|
30
|
-
|
31
|
-
when Regexp
|
32
|
-
XPath.attr(:class)[regexp_to_xpath_conditions(classes)]
|
29
|
+
when XPath::Expression, Regexp
|
30
|
+
attribute_conditions(class: classes)
|
33
31
|
else
|
34
32
|
Array(classes).map do |klass|
|
35
|
-
if klass.start_with?('!')
|
33
|
+
if klass.start_with?('!') && !klass.start_with?('!!!')
|
36
34
|
!XPath.attr(:class).contains_word(klass.slice(1..-1))
|
37
35
|
else
|
38
|
-
XPath.attr(:class).contains_word(klass)
|
36
|
+
XPath.attr(:class).contains_word(klass.sub(/^!!/, ''))
|
39
37
|
end
|
40
38
|
end.reduce(:&)
|
41
39
|
end
|
@@ -1,66 +1,65 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'regexp_parser'
|
4
|
+
|
3
5
|
module Capybara
|
4
6
|
class Selector
|
5
7
|
# @api private
|
6
8
|
class RegexpDisassembler
|
7
9
|
def initialize(regexp)
|
8
10
|
@regexp = regexp
|
9
|
-
@regexp_source = regexp.source
|
10
11
|
end
|
11
12
|
|
12
13
|
def substrings
|
13
14
|
@substrings ||= begin
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
source.gsub!(/\\p\{[[:alpha:]]+\}?/, '.') # replace character properties with wildcard
|
18
|
-
source.gsub!(/\[\[:[a-z]+:\]\]/, '.') # replace posix classes with wildcard
|
19
|
-
while source.gsub!(/\[(?:[^\[\]]+)\]/, '.'); end # replace character classes with wildcard
|
20
|
-
source.gsub!(/\(\?<?[=!][^)]*\)/, '') # remove lookahead/lookbehind assertions
|
21
|
-
source.gsub!(/\(\?(?:<[^>]+>|>|:)/, '(') # replace named, atomic, and non-matching groups with unnamed matching groups
|
22
|
-
|
23
|
-
while source.gsub!(GROUP_REGEX) { |_m| simplify_group(Regexp.last_match) }; end
|
24
|
-
source.gsub!(/.[*?]\??/, '.') # replace optional character with wildcard
|
25
|
-
source.gsub!(/(.)\+\??/, '\1.') # replace one or more with character plus wildcard
|
26
|
-
source.gsub!(/(?<char>.)#{COUNTED_REP_REGEX.source}/) do |_m| # repeat counted characters
|
27
|
-
(Regexp.last_match[:char] * Regexp.last_match[:min_rep].to_i).tap { |str| str << '.' if Regexp.last_match[:max_rep] }
|
28
|
-
end
|
29
|
-
return [] if source.include?('|') # can't handle alternation here
|
30
|
-
|
31
|
-
strs = source.match(/\A\^?(.*?)\$?\Z/).captures[0].split('.').reject(&:empty?).uniq
|
32
|
-
strs = strs.map(&:upcase) if @regexp.casefold?
|
33
|
-
strs
|
15
|
+
strs = extract_strings(Regexp::Parser.parse(@regexp), [+''])
|
16
|
+
strs.map!(&:upcase) if @regexp.casefold?
|
17
|
+
strs.reject(&:empty?).uniq
|
34
18
|
end
|
35
19
|
end
|
36
20
|
|
37
21
|
private
|
38
22
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
matches[:group][1..-2]
|
50
|
-
end
|
23
|
+
def min_repeat(exp)
|
24
|
+
exp.quantifier&.min || 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def fixed_repeat?(exp)
|
28
|
+
min_repeat(exp) == (exp.quantifier&.max || 1)
|
29
|
+
end
|
30
|
+
|
31
|
+
def optional?(exp)
|
32
|
+
min_repeat(exp).zero?
|
51
33
|
end
|
52
34
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
)
|
62
|
-
|
63
|
-
|
35
|
+
def extract_strings(expression, strings)
|
36
|
+
expression.each do |exp|
|
37
|
+
if optional?(exp)
|
38
|
+
strings.push(+'')
|
39
|
+
next
|
40
|
+
end
|
41
|
+
|
42
|
+
if %i[meta set].include?(exp.type)
|
43
|
+
strings.push(+'')
|
44
|
+
next
|
45
|
+
end
|
46
|
+
|
47
|
+
if exp.terminal?
|
48
|
+
case exp.type
|
49
|
+
when :literal
|
50
|
+
strings.last << (exp.text * min_repeat(exp))
|
51
|
+
when :escape
|
52
|
+
strings.last << (exp.char * min_repeat(exp))
|
53
|
+
else
|
54
|
+
strings.push(+'')
|
55
|
+
end
|
56
|
+
else
|
57
|
+
min_repeat(exp).times { extract_strings(exp, strings) }
|
58
|
+
end
|
59
|
+
strings.push(+'') unless fixed_repeat?(exp)
|
60
|
+
end
|
61
|
+
strings
|
62
|
+
end
|
64
63
|
end
|
65
64
|
end
|
66
65
|
end
|
@@ -217,7 +217,7 @@ module Capybara
|
|
217
217
|
# Define a selector by an xpath expression
|
218
218
|
#
|
219
219
|
# @overload xpath(*expression_filters, &block)
|
220
|
-
# @param [Array<Symbol>] expression_filters ([]) Names of filters that
|
220
|
+
# @param [Array<Symbol>] expression_filters ([]) Names of filters that are implemented via this expression, if not specified the names of any keyword parameters in the block will be used
|
221
221
|
# @yield [locator, options] The block to use to generate the XPath expression
|
222
222
|
# @yieldparam [String] locator The locator string passed to the query
|
223
223
|
# @yieldparam [Hash] options The options hash passed to the query
|
@@ -227,11 +227,7 @@ module Capybara
|
|
227
227
|
# @return [#call] The block that will be called to generate the XPath expression
|
228
228
|
#
|
229
229
|
def xpath(*allowed_filters, &block)
|
230
|
-
|
231
|
-
@format, @expression = :xpath, block
|
232
|
-
allowed_filters.flatten.each { |ef| expression_filters[ef] = Filters::IdentityExpressionFilter.new(ef) }
|
233
|
-
end
|
234
|
-
format == :xpath ? @expression : nil
|
230
|
+
expression(:xpath, allowed_filters, &block)
|
235
231
|
end
|
236
232
|
|
237
233
|
##
|
@@ -249,11 +245,7 @@ module Capybara
|
|
249
245
|
# @return [#call] The block that will be called to generate the CSS selector
|
250
246
|
#
|
251
247
|
def css(*allowed_filters, &block)
|
252
|
-
|
253
|
-
@format, @expression = :css, block
|
254
|
-
allowed_filters.flatten.each { |ef| expression_filters[ef] = nil }
|
255
|
-
end
|
256
|
-
format == :css ? @expression : nil
|
248
|
+
expression(:css, allowed_filters, &block)
|
257
249
|
end
|
258
250
|
|
259
251
|
##
|
@@ -459,6 +451,19 @@ module Capybara
|
|
459
451
|
def find_by_class_attr(classes)
|
460
452
|
Array(classes).map { |klass| XPath.attr(:class).contains_word(klass) }.reduce(:&)
|
461
453
|
end
|
454
|
+
|
455
|
+
def parameter_names(block)
|
456
|
+
block.parameters.select { |(type, _name)| %i[key keyreq].include? type }.map { |(_type, name)| name }
|
457
|
+
end
|
458
|
+
|
459
|
+
def expression(type, allowed_filters, &block)
|
460
|
+
if block
|
461
|
+
@format, @expression = type, block
|
462
|
+
allowed_filters = parameter_names(block) if allowed_filters.empty?
|
463
|
+
allowed_filters.flatten.each { |ef| expression_filters[ef] = Filters::IdentityExpressionFilter.new(ef) }
|
464
|
+
end
|
465
|
+
format == type ? @expression : nil
|
466
|
+
end
|
462
467
|
end
|
463
468
|
end
|
464
469
|
|
@@ -107,33 +107,17 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
107
107
|
navigated = false
|
108
108
|
timer = Capybara::Helpers.timer(expire_in: 10)
|
109
109
|
begin
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
clear_browser_state
|
114
|
-
@browser.navigate.to('about:blank')
|
115
|
-
end
|
110
|
+
# Only trigger a navigation if we haven't done it already, otherwise it
|
111
|
+
# can trigger an endless series of unload modals
|
112
|
+
reset_browser_state unless navigated
|
116
113
|
navigated = true
|
117
|
-
|
118
114
|
# Ensure the page is empty and trigger an UnhandledAlertError for any modals that appear during unload
|
119
|
-
|
120
|
-
raise Capybara::ExpectationNotMet, 'Timed out waiting for Selenium session reset' if timer.expired?
|
121
|
-
|
122
|
-
sleep 0.05
|
123
|
-
end
|
115
|
+
wait_for_empty_page(timer)
|
124
116
|
rescue Selenium::WebDriver::Error::UnhandledAlertError, Selenium::WebDriver::Error::UnexpectedAlertOpenError
|
125
117
|
# This error is thrown if an unhandled alert is on the page
|
126
118
|
# Firefox appears to automatically dismiss this alert, chrome does not
|
127
119
|
# We'll try to accept it
|
128
|
-
|
129
|
-
@browser.switch_to.alert.accept
|
130
|
-
sleep 0.25 # allow time for the modal to be handled
|
131
|
-
rescue modal_error
|
132
|
-
# The alert is now gone.
|
133
|
-
# If navigation has not occurred attempt again and accept alert
|
134
|
-
# since FF may have dismissed the alert at first attempt.
|
135
|
-
navigate_with_accept('about:blank') if current_url != 'about:blank'
|
136
|
-
end
|
120
|
+
accept_unhandled_reset_alert
|
137
121
|
# try cleaning up the browser again
|
138
122
|
retry
|
139
123
|
end
|
@@ -382,6 +366,29 @@ private
|
|
382
366
|
exit @exit_status if @exit_status # Force exit with stored status
|
383
367
|
end
|
384
368
|
end
|
369
|
+
|
370
|
+
def reset_browser_state
|
371
|
+
clear_browser_state
|
372
|
+
@browser.navigate.to('about:blank')
|
373
|
+
end
|
374
|
+
|
375
|
+
def wait_for_empty_page(timer)
|
376
|
+
until find_xpath('/html/body/*').empty?
|
377
|
+
raise Capybara::ExpectationNotMet, 'Timed out waiting for Selenium session reset' if timer.expired?
|
378
|
+
|
379
|
+
sleep 0.05
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
def accept_unhandled_reset_alert
|
384
|
+
@browser.switch_to.alert.accept
|
385
|
+
sleep 0.25 # allow time for the modal to be handled
|
386
|
+
rescue modal_error
|
387
|
+
# The alert is now gone.
|
388
|
+
# If navigation has not occurred attempt again and accept alert
|
389
|
+
# since FF may have dismissed the alert at first attempt.
|
390
|
+
navigate_with_accept('about:blank') if current_url != 'about:blank'
|
391
|
+
end
|
385
392
|
end
|
386
393
|
|
387
394
|
require 'capybara/selenium/driver_specializations/chrome_driver'
|
@@ -36,16 +36,11 @@ class Capybara::Selenium::MarionetteNode < Capybara::Selenium::Node
|
|
36
36
|
return super if browser_version >= 62.0
|
37
37
|
|
38
38
|
# Workaround lack of support for multiple upload by uploading one at a time
|
39
|
-
path_names = value.to_s.empty? ? [] : value
|
40
|
-
|
41
|
-
|
42
|
-
if (fd = bridge.file_detector)
|
43
|
-
local_file = fd.call([path])
|
44
|
-
path = upload(local_file) if local_file
|
45
|
-
end
|
46
|
-
end
|
47
|
-
native.send_keys(path)
|
39
|
+
path_names = value.to_s.empty? ? [] : Array(value)
|
40
|
+
if (fd = bridge.file_detector) && !driver.browser.respond_to?(:upload)
|
41
|
+
path_names.map! { |path| upload(fd.call([path])) || path }
|
48
42
|
end
|
43
|
+
path_names.each { |path| native.send_keys(path) }
|
49
44
|
end
|
50
45
|
|
51
46
|
def send_keys(*args)
|
@@ -101,9 +96,8 @@ private
|
|
101
96
|
end
|
102
97
|
|
103
98
|
def upload(local_file)
|
104
|
-
unless
|
105
|
-
|
106
|
-
end
|
99
|
+
return nil unless local_file
|
100
|
+
raise ArgumentError, "You may only upload files: #{local_file.inspect}" unless File.file?(local_file)
|
107
101
|
|
108
102
|
result = bridge.http.call(:post, "session/#{bridge.session_id}/file", file: Selenium::WebDriver::Zipper.zip_file(local_file))
|
109
103
|
result['value']
|
data/lib/capybara/server.rb
CHANGED
@@ -48,9 +48,7 @@ module Capybara
|
|
48
48
|
|
49
49
|
res = @checker.request { |http| http.get('/__identify__') }
|
50
50
|
|
51
|
-
if res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPRedirection)
|
52
|
-
return res.body == app.object_id.to_s
|
53
|
-
end
|
51
|
+
return res.body == app.object_id.to_s if res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPRedirection)
|
54
52
|
rescue SystemCallError, Net::ReadTimeout, OpenSSL::SSL::SSLError
|
55
53
|
false
|
56
54
|
end
|
@@ -16,7 +16,7 @@ module Capybara
|
|
16
16
|
|
17
17
|
def initialize(app)
|
18
18
|
@app = app
|
19
|
-
@disable_markup = DISABLE_MARKUP_TEMPLATE
|
19
|
+
@disable_markup = format(DISABLE_MARKUP_TEMPLATE, selector: AnimationDisabler.selector_for(Capybara.disable_animation))
|
20
20
|
end
|
21
21
|
|
22
22
|
def call(env)
|
@@ -46,7 +46,7 @@ module Capybara
|
|
46
46
|
DISABLE_MARKUP_TEMPLATE = <<~HTML
|
47
47
|
<script defer>(typeof jQuery !== 'undefined') && (jQuery.fx.off = true);</script>
|
48
48
|
<style>
|
49
|
-
|
49
|
+
%<selector>s {
|
50
50
|
transition: none !important;
|
51
51
|
animation-duration: 0s !important;
|
52
52
|
animation-delay: 0s !important;
|
data/lib/capybara/session.rb
CHANGED
@@ -49,7 +49,7 @@ module Capybara
|
|
49
49
|
has_no_table? has_table? unselect has_select? has_no_select?
|
50
50
|
has_selector? has_no_selector? click_on has_no_checked_field?
|
51
51
|
has_no_unchecked_field? query assert_selector assert_no_selector
|
52
|
-
assert_all_of_selectors assert_none_of_selectors
|
52
|
+
assert_all_of_selectors assert_none_of_selectors assert_any_of_selectors
|
53
53
|
refute_selector assert_text assert_no_text
|
54
54
|
].freeze
|
55
55
|
# @api private
|
@@ -19,6 +19,10 @@ Capybara::SpecHelper.spec '#assert_all_of_selectors' do
|
|
19
19
|
@session.assert_all_of_selectors('p a#foo', 'h2#h2two', 'h2#h2one')
|
20
20
|
end
|
21
21
|
|
22
|
+
it 'should support filter block' do
|
23
|
+
expect { @session.assert_all_of_selectors(:css, 'h2#h2one', 'h2#h2two') { |n| n[:id] == 'h2one' } }.to raise_error(Capybara::ElementNotFound, /custom filter block/)
|
24
|
+
end
|
25
|
+
|
22
26
|
context 'should respect scopes' do
|
23
27
|
it 'when used with `within`' do
|
24
28
|
@session.within "//p[@id='first']" do
|
@@ -109,3 +113,28 @@ Capybara::SpecHelper.spec '#assert_none_of_selectors' do
|
|
109
113
|
end
|
110
114
|
end
|
111
115
|
end
|
116
|
+
|
117
|
+
Capybara::SpecHelper.spec '#assert_any_of_selectors' do
|
118
|
+
before do
|
119
|
+
@session.visit('/with_html')
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should be true if any of the given selectors are on the page' do
|
123
|
+
@session.assert_any_of_selectors(:css, 'a#foo', 'h2#h2three')
|
124
|
+
@session.assert_any_of_selectors(:css, 'h2#h2three', 'a#foo')
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should be false if none of the given selectors are on the page' do
|
128
|
+
expect { @session.assert_any_of_selectors(:css, 'h2#h2three', 'h4#h4four') }.to raise_error(Capybara::ElementNotFound)
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should use default selector' do
|
132
|
+
Capybara.default_selector = :css
|
133
|
+
expect { @session.assert_any_of_selectors('h2#h2three', 'h5#h5five') }.to raise_error(Capybara::ElementNotFound)
|
134
|
+
@session.assert_any_of_selectors('p a#foo', 'h2#h2two', 'h2#h2one')
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should support filter block' do
|
138
|
+
expect { @session.assert_any_of_selectors(:css, 'h2#h2one', 'h2#h2two') { |_n| false } }.to raise_error(Capybara::ElementNotFound, /custom filter block/)
|
139
|
+
end
|
140
|
+
end
|
@@ -376,6 +376,12 @@ Capybara::SpecHelper.spec '#click_button' do
|
|
376
376
|
expect(@results['no_value']).not_to be_nil
|
377
377
|
end
|
378
378
|
|
379
|
+
it 'should send button in document order' do
|
380
|
+
@session.click_button('outside_button')
|
381
|
+
@results = extract_results(@session)
|
382
|
+
expect(@results.keys).to eq %w[for_form2 outside_button which_form post_count]
|
383
|
+
end
|
384
|
+
|
379
385
|
it 'should not send image buttons that were not clicked' do
|
380
386
|
@session.click_button('Click me!')
|
381
387
|
@results = extract_results(@session)
|
@@ -211,7 +211,7 @@ Capybara::SpecHelper.spec '#click_link' do
|
|
211
211
|
download_file = File.join(Capybara.save_path, 'download.csv')
|
212
212
|
expect(File).not_to exist(download_file)
|
213
213
|
@session.click_link('Download Me')
|
214
|
-
sleep 2
|
214
|
+
sleep 2 # allow time for file to download
|
215
215
|
expect(File).to exist(download_file)
|
216
216
|
FileUtils.rm_rf download_file
|
217
217
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Capybara::SpecHelper.spec '#have_any_of_selectors' do
|
4
|
+
before do
|
5
|
+
@session.visit('/with_html')
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should be true if any of the given selectors are on the page' do
|
9
|
+
expect(@session).to have_any_of_selectors(:css, 'p a#foo', 'h2#blah', 'h2#h2two')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should be false if none of the given selectors are not on the page' do
|
13
|
+
expect do
|
14
|
+
expect(@session).to have_any_of_selectors(:css, 'span a#foo', 'h2#h2nope', 'h2#h2one_no')
|
15
|
+
end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should use default selector' do
|
19
|
+
Capybara.default_selector = :css
|
20
|
+
expect(@session).to have_any_of_selectors('p a#foo', 'h2#h2two', 'a#not_on_page')
|
21
|
+
expect do
|
22
|
+
expect(@session).to have_any_of_selectors('p a#blah', 'h2#h2three')
|
23
|
+
end.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
24
|
+
end
|
25
|
+
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Note: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
|
4
|
+
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
5
|
+
# using Capybara provided assertions with builtin waiting behavior.
|
6
|
+
|
3
7
|
Capybara::SpecHelper.spec '#html' do
|
4
8
|
it 'should return the unmodified page body' do
|
5
9
|
@session.visit('/')
|
@@ -8,6 +12,7 @@ Capybara::SpecHelper.spec '#html' do
|
|
8
12
|
|
9
13
|
it 'should return the current state of the page', requires: [:js] do
|
10
14
|
@session.visit('/with_js')
|
15
|
+
sleep 1
|
11
16
|
expect(@session.html).to include('I changed it')
|
12
17
|
expect(@session.html).not_to include('This is text')
|
13
18
|
end
|
@@ -21,6 +26,7 @@ Capybara::SpecHelper.spec '#source' do
|
|
21
26
|
|
22
27
|
it 'should return the current state of the page', requires: [:js] do
|
23
28
|
@session.visit('/with_js')
|
29
|
+
sleep 1
|
24
30
|
expect(@session.source).to include('I changed it')
|
25
31
|
expect(@session.source).not_to include('This is text')
|
26
32
|
end
|
@@ -34,6 +40,7 @@ Capybara::SpecHelper.spec '#body' do
|
|
34
40
|
|
35
41
|
it 'should return the current state of the page', requires: [:js] do
|
36
42
|
@session.visit('/with_js')
|
43
|
+
sleep 1
|
37
44
|
expect(@session.body).to include('I changed it')
|
38
45
|
expect(@session.body).not_to include('This is text')
|
39
46
|
end
|