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
@@ -9,10 +9,8 @@ RSpec.shared_context "Capybara Features", capybara_feature: true do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
# ensure shared_context is included if default shared_context_metadata_behavior is changed
|
12
|
-
|
13
|
-
|
14
|
-
config.include_context "Capybara Features", capybara_feature: true
|
15
|
-
end
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.include_context "Capybara Features", capybara_feature: true if config.respond_to?(:include_context)
|
16
14
|
end
|
17
15
|
|
18
16
|
RSpec.configure do |config|
|
@@ -1,12 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'capybara/rspec/compound'
|
4
|
+
|
3
5
|
module Capybara
|
4
6
|
module RSpecMatchers
|
5
7
|
class Matcher
|
6
|
-
if defined?(::
|
7
|
-
require 'capybara/rspec/compound'
|
8
|
-
include ::Capybara::RSpecMatchers::Compound
|
9
|
-
end
|
8
|
+
include ::Capybara::RSpecMatchers::Compound if defined?(::Capybara::RSpecMatchers::Compound)
|
10
9
|
|
11
10
|
attr_reader :failure_message, :failure_message_when_negated
|
12
11
|
|
@@ -199,10 +198,7 @@ module Capybara
|
|
199
198
|
end
|
200
199
|
|
201
200
|
class NegatedMatcher
|
202
|
-
if defined?(::
|
203
|
-
require 'capybara/rspec/compound'
|
204
|
-
include ::Capybara::RSpecMatchers::Compound
|
205
|
-
end
|
201
|
+
include ::Capybara::RSpecMatchers::Compound if defined?(::Capybara::RSpecMatchers::Compound)
|
206
202
|
|
207
203
|
def initialize(matcher)
|
208
204
|
@matcher = matcher
|
@@ -229,6 +225,24 @@ module Capybara
|
|
229
225
|
end
|
230
226
|
end
|
231
227
|
|
228
|
+
class HaveStyle < Matcher
|
229
|
+
def initialize(*args)
|
230
|
+
@args = args
|
231
|
+
end
|
232
|
+
|
233
|
+
def matches?(actual)
|
234
|
+
wrap_matches?(actual) { |el| el.assert_style(*@args) }
|
235
|
+
end
|
236
|
+
|
237
|
+
def does_not_match?(_actual)
|
238
|
+
raise ArgumentError, "The have_style matcher does not support use with not_to/should_not"
|
239
|
+
end
|
240
|
+
|
241
|
+
def description
|
242
|
+
"have style"
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
232
246
|
class BecomeClosed
|
233
247
|
def initialize(options)
|
234
248
|
@options = options
|
@@ -237,9 +251,9 @@ module Capybara
|
|
237
251
|
def matches?(window)
|
238
252
|
@window = window
|
239
253
|
@wait_time = Capybara::Queries::BaseQuery.wait(@options, window.session.config.default_max_wait_time)
|
240
|
-
|
254
|
+
timer = Capybara::Helpers.timer(expire_in: @wait_time)
|
241
255
|
while window.exists?
|
242
|
-
return false if
|
256
|
+
return false if timer.expired?
|
243
257
|
sleep 0.05
|
244
258
|
end
|
245
259
|
true
|
@@ -359,6 +373,12 @@ module Capybara
|
|
359
373
|
HaveSelector.new(:table, locator, options, &optional_filter_block)
|
360
374
|
end
|
361
375
|
|
376
|
+
# RSpec matcher for element style
|
377
|
+
# See {Capybara::Node::Matchers#has_style?}
|
378
|
+
def have_style(styles, **options)
|
379
|
+
HaveStyle.new(styles, options)
|
380
|
+
end
|
381
|
+
|
362
382
|
%w[selector css xpath text title current_path link button field checked_field unchecked_field select table].each do |matcher_type|
|
363
383
|
define_method "have_no_#{matcher_type}" do |*args, &optional_filter_block|
|
364
384
|
NegatedMatcher.new(send("have_#{matcher_type}", *args, &optional_filter_block))
|
data/lib/capybara/selector.rb
CHANGED
@@ -112,6 +112,15 @@ Capybara.add_selector(:link) do
|
|
112
112
|
href.is_a?(Regexp) ? node[:href].match(href) : true
|
113
113
|
end
|
114
114
|
|
115
|
+
expression_filter(:download, valid_values: [true, false, String]) do |expr, download|
|
116
|
+
mod = case download
|
117
|
+
when true then XPath.attr(:download)
|
118
|
+
when false then !XPath.attr(:download)
|
119
|
+
when String then XPath.attr(:download) == download
|
120
|
+
end
|
121
|
+
expr[mod]
|
122
|
+
end
|
123
|
+
|
115
124
|
describe do |**options|
|
116
125
|
desc = +""
|
117
126
|
desc << " with href #{options[:href].inspect}" if options[:href]
|
@@ -16,12 +16,85 @@ module Capybara
|
|
16
16
|
c =~ %r{[ -/:-~]} ? "\\#{c}" : format("\\%06x", c.ord)
|
17
17
|
end
|
18
18
|
|
19
|
+
def self.split(css)
|
20
|
+
Splitter.new.split(css)
|
21
|
+
end
|
22
|
+
|
19
23
|
S = '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
|
20
24
|
H = /[0-9a-fA-F]/
|
21
25
|
UNICODE = /\\#{H}{1,6}[ \t\r\n\f]?/
|
22
26
|
NONASCII = /[#{S}]/
|
23
27
|
ESCAPE = /#{UNICODE}|\\[ -~#{S}]/
|
24
|
-
NMSTART
|
28
|
+
NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/
|
29
|
+
|
30
|
+
class Splitter
|
31
|
+
def split(css)
|
32
|
+
selectors = []
|
33
|
+
StringIO.open(css) do |str|
|
34
|
+
selector = ""
|
35
|
+
while (c = str.getc)
|
36
|
+
case c
|
37
|
+
when '['
|
38
|
+
selector += parse_square(str)
|
39
|
+
when '('
|
40
|
+
selector += parse_paren(str)
|
41
|
+
when '"', "'"
|
42
|
+
selector += parse_string(c, str)
|
43
|
+
when '\\'
|
44
|
+
selector += c + str.getc
|
45
|
+
when ','
|
46
|
+
selectors << selector.strip
|
47
|
+
selector = ""
|
48
|
+
else
|
49
|
+
selector += c
|
50
|
+
end
|
51
|
+
end
|
52
|
+
selectors << selector.strip
|
53
|
+
end
|
54
|
+
selectors
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def parse_square(strio)
|
60
|
+
parse_block('[', ']', strio)
|
61
|
+
end
|
62
|
+
|
63
|
+
def parse_paren(strio)
|
64
|
+
parse_block('(', ')', strio)
|
65
|
+
end
|
66
|
+
|
67
|
+
def parse_block(start, final, strio)
|
68
|
+
block = start
|
69
|
+
while (c = strio.getc)
|
70
|
+
case c
|
71
|
+
when final
|
72
|
+
return block + c
|
73
|
+
when '\\'
|
74
|
+
block += c + strio.getc
|
75
|
+
when '"', "'"
|
76
|
+
block += parse_string(c, strio)
|
77
|
+
else
|
78
|
+
block += c
|
79
|
+
end
|
80
|
+
end
|
81
|
+
raise ArgumentError, "Invalid CSS Selector - Block end '#{final}' not found"
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse_string(quote, strio)
|
85
|
+
string = quote
|
86
|
+
while (c = strio.getc)
|
87
|
+
string += c
|
88
|
+
case c
|
89
|
+
when quote
|
90
|
+
return string
|
91
|
+
when '\\'
|
92
|
+
string += strio.getc
|
93
|
+
end
|
94
|
+
end
|
95
|
+
raise ArgumentError, 'Invalid CSS Selector - string end not found'
|
96
|
+
end
|
97
|
+
end
|
25
98
|
end
|
26
99
|
end
|
27
100
|
end
|
@@ -49,7 +49,8 @@ module Capybara
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def valid_value?(value)
|
52
|
-
|
52
|
+
return true unless @options.key?(:valid_values)
|
53
|
+
Array(@options[:valid_values]).any? { |valid| valid === value } # rubocop:disable Style/CaseEquality
|
53
54
|
end
|
54
55
|
end
|
55
56
|
end
|
@@ -12,8 +12,9 @@ module Capybara
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class IdentityExpressionFilter < ExpressionFilter
|
15
|
-
def initialize; end
|
15
|
+
def initialize(name); super(name, nil, nil); end
|
16
16
|
def default?; false; end
|
17
|
+
def matcher?; false; end
|
17
18
|
def apply_filter(expr, _name, _value); expr; end
|
18
19
|
end
|
19
20
|
end
|
@@ -223,7 +223,7 @@ module Capybara
|
|
223
223
|
def xpath(*allowed_filters, &block)
|
224
224
|
if block
|
225
225
|
@format, @expression = :xpath, block
|
226
|
-
allowed_filters.flatten.each { |ef| expression_filters[ef] = Filters::IdentityExpressionFilter.new }
|
226
|
+
allowed_filters.flatten.each { |ef| expression_filters[ef] = Filters::IdentityExpressionFilter.new(ef) }
|
227
227
|
end
|
228
228
|
format == :xpath ? @expression : nil
|
229
229
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'uri'
|
4
|
+
require 'English'
|
5
5
|
|
6
6
|
class Capybara::Selenium::Driver < Capybara::Driver::Base
|
7
7
|
DEFAULT_OPTIONS = {
|
@@ -10,18 +10,11 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
10
10
|
clear_session_storage: false
|
11
11
|
}.freeze
|
12
12
|
SPECIAL_OPTIONS = %i[browser clear_local_storage clear_session_storage].freeze
|
13
|
-
|
14
13
|
attr_reader :app, :options
|
15
14
|
|
16
15
|
def self.load_selenium
|
17
16
|
require 'selenium-webdriver'
|
18
|
-
|
19
|
-
unless defined?(::Selenium::WebDriver::Error::ElementNotInteractableError)
|
20
|
-
::Selenium::WebDriver::Error.const_set('ElementNotInteractableError', Class.new(::Selenium::WebDriver::Error::WebDriverError))
|
21
|
-
end
|
22
|
-
unless defined?(::Selenium::WebDriver::Error::ElementClickInterceptedError)
|
23
|
-
::Selenium::WebDriver::Error.const_set('ElementClickInterceptedError', Class.new(::Selenium::WebDriver::Error::WebDriverError))
|
24
|
-
end
|
17
|
+
warn "Warning: You're using an unsupported version of selenium-webdriver, please upgrade." if Gem::Version.new(Selenium::WebDriver::VERSION) < Gem::Version.new('3.5.0')
|
25
18
|
rescue LoadError => e
|
26
19
|
raise e if e.message !~ /selenium-webdriver/
|
27
20
|
raise LoadError, "Capybara's selenium driver is unable to load `selenium-webdriver`, please install the gem and add `gem 'selenium-webdriver'` to your Gemfile if you are using bundler."
|
@@ -37,10 +30,10 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
37
30
|
@processed_options = options.reject { |key, _val| SPECIAL_OPTIONS.include?(key) }
|
38
31
|
@browser = Selenium::WebDriver.for(options[:browser], @processed_options)
|
39
32
|
|
40
|
-
|
41
|
-
|
42
|
-
main = Process.pid
|
33
|
+
extend ChromeDriver if chrome?
|
34
|
+
extend MarionetteDriver if marionette?
|
43
35
|
|
36
|
+
main = Process.pid
|
44
37
|
at_exit do
|
45
38
|
# Store the exit status of the test run since it goes away after calling the at_exit proc...
|
46
39
|
@exit_status = $ERROR_INFO.status if $ERROR_INFO.is_a?(SystemExit)
|
@@ -59,6 +52,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
59
52
|
@exit_status = nil
|
60
53
|
@frame_handles = {}
|
61
54
|
@options = DEFAULT_OPTIONS.merge(options)
|
55
|
+
@node_class = ::Capybara::Selenium::Node
|
62
56
|
end
|
63
57
|
|
64
58
|
def visit(path)
|
@@ -90,11 +84,11 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
90
84
|
end
|
91
85
|
|
92
86
|
def find_xpath(selector)
|
93
|
-
browser.find_elements(:xpath, selector).map
|
87
|
+
browser.find_elements(:xpath, selector).map(&method(:build_node))
|
94
88
|
end
|
95
89
|
|
96
90
|
def find_css(selector)
|
97
|
-
browser.find_elements(:css, selector).map
|
91
|
+
browser.find_elements(:css, selector).map(&method(:build_node))
|
98
92
|
end
|
99
93
|
|
100
94
|
def wait?; true; end
|
@@ -123,13 +117,8 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
123
117
|
# Use instance variable directly so we avoid starting the browser just to reset the session
|
124
118
|
return unless @browser
|
125
119
|
|
126
|
-
if firefox? || chrome?
|
127
|
-
switch_to_window(window_handles.first)
|
128
|
-
window_handles.slice(1..-1).each { |win| close_window(win) }
|
129
|
-
end
|
130
|
-
|
131
120
|
navigated = false
|
132
|
-
|
121
|
+
timer = Capybara::Helpers.timer(expire_in: 10)
|
133
122
|
begin
|
134
123
|
unless navigated
|
135
124
|
# Only trigger a navigation if we haven't done it already, otherwise it
|
@@ -152,7 +141,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
152
141
|
|
153
142
|
# Ensure the page is empty and trigger an UnhandledAlertError for any modals that appear during unload
|
154
143
|
until find_xpath("/html/body/*").empty?
|
155
|
-
raise Capybara::ExpectationNotMet, 'Timed out waiting for Selenium session reset' if
|
144
|
+
raise Capybara::ExpectationNotMet, 'Timed out waiting for Selenium session reset' if timer.expired?
|
156
145
|
sleep 0.05
|
157
146
|
end
|
158
147
|
rescue Selenium::WebDriver::Error::UnhandledAlertError, Selenium::WebDriver::Error::UnexpectedAlertOpenError
|
@@ -212,12 +201,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
212
201
|
|
213
202
|
def resize_window_to(handle, width, height)
|
214
203
|
within_given_window(handle) do
|
215
|
-
|
216
|
-
if marionette? && (window_size(handle) == [width, height])
|
217
|
-
{}
|
218
|
-
else
|
219
|
-
browser.manage.window.resize_to(width, height)
|
220
|
-
end
|
204
|
+
browser.manage.window.resize_to(width, height)
|
221
205
|
end
|
222
206
|
end
|
223
207
|
|
@@ -228,6 +212,12 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
228
212
|
sleep 0.1 # work around for https://code.google.com/p/selenium/issues/detail?id=7405
|
229
213
|
end
|
230
214
|
|
215
|
+
def fullscreen_window(handle)
|
216
|
+
within_given_window(handle) do
|
217
|
+
browser.manage.window.full_screen
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
231
221
|
def close_window(handle)
|
232
222
|
raise ArgumentError, "Not allowed to close the primary window" if handle == window_handles.first
|
233
223
|
within_given_window(handle) do
|
@@ -299,38 +289,36 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
299
289
|
Selenium::WebDriver::Error::NoSuchWindowError
|
300
290
|
end
|
301
291
|
|
302
|
-
|
292
|
+
private
|
293
|
+
|
294
|
+
def w3c?
|
295
|
+
browser && browser.capabilities.is_a?(Selenium::WebDriver::Remote::W3C::Capabilities)
|
296
|
+
end
|
297
|
+
|
303
298
|
def marionette?
|
304
|
-
firefox? &&
|
299
|
+
firefox? && w3c?
|
305
300
|
end
|
306
301
|
|
307
|
-
# @api private
|
308
302
|
def firefox?
|
309
303
|
browser_name == :firefox
|
310
304
|
end
|
311
305
|
|
312
|
-
# @api private
|
313
306
|
def chrome?
|
314
307
|
browser_name == :chrome
|
315
308
|
end
|
316
309
|
|
317
|
-
# @api private
|
318
310
|
def edge?
|
319
311
|
browser_name == :edge
|
320
312
|
end
|
321
313
|
|
322
|
-
# @api private
|
323
314
|
def ie?
|
324
315
|
browser_name == :ie
|
325
316
|
end
|
326
317
|
|
327
|
-
# @api private
|
328
318
|
def browser_name
|
329
319
|
browser.browser
|
330
320
|
end
|
331
321
|
|
332
|
-
private
|
333
|
-
|
334
322
|
def native_args(args)
|
335
323
|
args.map { |arg| arg.is_a?(Capybara::Selenium::Node) ? arg.native : arg }
|
336
324
|
end
|
@@ -354,11 +342,7 @@ private
|
|
354
342
|
end
|
355
343
|
|
356
344
|
def modal_error
|
357
|
-
|
358
|
-
Selenium::WebDriver::Error::NoSuchAlertError
|
359
|
-
else
|
360
|
-
Selenium::WebDriver::Error::NoAlertPresentError
|
361
|
-
end
|
345
|
+
Selenium::WebDriver::Error::NoSuchAlertError
|
362
346
|
end
|
363
347
|
|
364
348
|
def within_given_window(handle)
|
@@ -406,9 +390,16 @@ private
|
|
406
390
|
when Hash
|
407
391
|
arg.each { |k, v| arg[k] = unwrap_script_result(v) }
|
408
392
|
when Selenium::WebDriver::Element
|
409
|
-
|
393
|
+
build_node(arg)
|
410
394
|
else
|
411
395
|
arg
|
412
396
|
end
|
413
397
|
end
|
398
|
+
|
399
|
+
def build_node(native_node)
|
400
|
+
::Capybara::Selenium::Node.new(self, native_node)
|
401
|
+
end
|
414
402
|
end
|
403
|
+
|
404
|
+
require 'capybara/selenium/driver_specializations/chrome_driver'
|
405
|
+
require 'capybara/selenium/driver_specializations/marionette_driver'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Capybara::Selenium::Driver::ChromeDriver
|
4
|
+
def fullscreen_window(handle)
|
5
|
+
within_given_window(handle) do
|
6
|
+
begin
|
7
|
+
super
|
8
|
+
rescue NoMethodError => e
|
9
|
+
raise unless e.message =~ /full_screen_window/
|
10
|
+
bridge = browser.send(:bridge)
|
11
|
+
result = bridge.http.call(:post, "session/#{bridge.session_id}/window/fullscreen", {})
|
12
|
+
result['value']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def resize_window_to(handle, width, height)
|
18
|
+
super
|
19
|
+
rescue Selenium::WebDriver::Error::UnknownError => e
|
20
|
+
raise unless e.message =~ /failed to change window state/
|
21
|
+
# Chromedriver doesn't wait long enough for state to change when coming out of fullscreen
|
22
|
+
# and raises unnecessary error. Wait a bit and try again.
|
23
|
+
sleep 0.5
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset!
|
28
|
+
# Use instance variable directly so we avoid starting the browser just to reset the session
|
29
|
+
return unless @browser
|
30
|
+
|
31
|
+
switch_to_window(window_handles.first)
|
32
|
+
window_handles.slice(1..-1).each { |win| close_window(win) }
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|