cuprite 0.12 → 0.15.1
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/LICENSE +1 -1
- data/README.md +14 -12
- data/lib/capybara/cuprite/browser.rb +196 -155
- data/lib/capybara/cuprite/cookie.rb +32 -32
- data/lib/capybara/cuprite/driver.rb +335 -363
- data/lib/capybara/cuprite/errors.rb +9 -8
- data/lib/capybara/cuprite/javascripts/index.js +47 -27
- data/lib/capybara/cuprite/node.rb +218 -224
- data/lib/capybara/cuprite/options.rb +14 -0
- data/lib/capybara/cuprite/page.rb +148 -154
- data/lib/capybara/cuprite/version.rb +1 -1
- data/lib/capybara/cuprite.rb +3 -0
- metadata +19 -145
@@ -3,462 +3,434 @@
|
|
3
3
|
require "uri"
|
4
4
|
require "forwardable"
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
6
|
+
# rubocop:disable Metrics/ClassLength
|
7
|
+
module Capybara
|
8
|
+
module Cuprite
|
9
|
+
class Driver < Capybara::Driver::Base
|
10
|
+
DEFAULT_MAXIMIZE_SCREEN_SIZE = [1366, 768].freeze
|
11
|
+
EXTENSION = File.expand_path("javascripts/index.js", __dir__)
|
12
|
+
|
13
|
+
extend Forwardable
|
14
|
+
|
15
|
+
delegate %i[restart quit status_code timeout timeout= current_url title body
|
16
|
+
window_handles close_window switch_to_window within_window window_handle
|
17
|
+
back forward refresh wait_for_reload viewport_size device_pixel_ratio] => :browser
|
18
|
+
delegate %i[send_keys] => :active_element
|
19
|
+
alias html body
|
20
|
+
alias current_window_handle window_handle
|
21
|
+
alias go_back back
|
22
|
+
alias go_forward forward
|
23
|
+
|
24
|
+
attr_reader :app, :options, :screen_size
|
25
|
+
|
26
|
+
def initialize(app, options = {})
|
27
|
+
@app = app
|
28
|
+
@options = options.dup
|
29
|
+
@started = false
|
30
|
+
|
31
|
+
@options[:extensions] ||= []
|
32
|
+
@options[:extensions] << EXTENSION
|
33
|
+
|
34
|
+
@screen_size = @options.delete(:screen_size)
|
35
|
+
@screen_size ||= DEFAULT_MAXIMIZE_SCREEN_SIZE
|
36
|
+
@options[:save_path] ||= File.expand_path(Capybara.save_path) if Capybara.save_path
|
37
|
+
|
38
|
+
# It's set for debug() to make devtools tab open correctly.
|
39
|
+
@options[:browser_options] ||= {}
|
40
|
+
unless @options[:browser_options][:"remote-allow-origins"]
|
41
|
+
@options[:browser_options].merge!("remote-allow-origins": "*")
|
42
|
+
end
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
browser.visit(url)
|
44
|
-
end
|
44
|
+
super()
|
45
|
+
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
frame_url
|
49
|
-
else
|
50
|
-
browser.current_url
|
47
|
+
def needs_server?
|
48
|
+
true
|
51
49
|
end
|
52
|
-
end
|
53
50
|
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
def browser
|
52
|
+
@browser ||= Browser.new(@options)
|
53
|
+
end
|
57
54
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
def visit(url)
|
56
|
+
@started = true
|
57
|
+
browser.visit(url)
|
58
|
+
end
|
62
59
|
|
63
|
-
|
64
|
-
|
65
|
-
|
60
|
+
def frame_url
|
61
|
+
evaluate_script("window.location.href")
|
62
|
+
end
|
66
63
|
|
67
|
-
|
68
|
-
|
69
|
-
frame_title
|
70
|
-
else
|
71
|
-
browser.title
|
64
|
+
def source
|
65
|
+
browser.source.to_s
|
72
66
|
end
|
73
|
-
end
|
74
67
|
|
75
|
-
|
76
|
-
|
77
|
-
|
68
|
+
def frame_title
|
69
|
+
evaluate_script("document.title")
|
70
|
+
end
|
78
71
|
|
79
|
-
|
80
|
-
|
81
|
-
|
72
|
+
def active_element
|
73
|
+
Node.new(self, browser.active_element)
|
74
|
+
end
|
82
75
|
|
83
|
-
|
84
|
-
|
85
|
-
|
76
|
+
def find_xpath(selector)
|
77
|
+
find(:xpath, selector)
|
78
|
+
end
|
86
79
|
|
87
|
-
|
88
|
-
|
89
|
-
|
80
|
+
def find_css(selector)
|
81
|
+
find(:css, selector)
|
82
|
+
end
|
90
83
|
|
91
|
-
|
92
|
-
|
93
|
-
|
84
|
+
def find(method, selector)
|
85
|
+
browser.find(method, selector).map { |native| Node.new(self, native) }
|
86
|
+
end
|
94
87
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
end
|
88
|
+
def click(x, y)
|
89
|
+
browser.mouse.click(x: x, y: y)
|
90
|
+
end
|
99
91
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
92
|
+
def evaluate_script(script, *args)
|
93
|
+
result = browser.evaluate(script, *native_args(args))
|
94
|
+
unwrap_script_result(result)
|
95
|
+
end
|
104
96
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
97
|
+
def evaluate_async_script(script, *args)
|
98
|
+
result = browser.evaluate_async(script, session_wait_time, *native_args(args))
|
99
|
+
unwrap_script_result(result)
|
100
|
+
end
|
109
101
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
locator.native.description["frameId"]
|
114
|
-
when :parent, :top
|
115
|
-
locator
|
102
|
+
def execute_script(script, *args)
|
103
|
+
browser.execute(script, *native_args(args))
|
104
|
+
nil
|
116
105
|
end
|
117
106
|
|
118
|
-
|
119
|
-
|
107
|
+
def switch_to_frame(locator)
|
108
|
+
handle = case locator
|
109
|
+
when Capybara::Node::Element
|
110
|
+
locator.native.description["frameId"]
|
111
|
+
when :parent, :top
|
112
|
+
locator
|
113
|
+
end
|
120
114
|
|
121
|
-
|
122
|
-
|
123
|
-
end
|
115
|
+
browser.switch_to_frame(handle)
|
116
|
+
end
|
124
117
|
|
125
|
-
|
126
|
-
|
127
|
-
|
118
|
+
def open_new_window
|
119
|
+
target = browser.default_context.create_target
|
120
|
+
target.maybe_sleep_if_new_window
|
121
|
+
target.page = Page.new(target.client, context_id: target.context_id, target_id: target.id)
|
122
|
+
target.page
|
123
|
+
end
|
128
124
|
|
129
|
-
|
130
|
-
|
131
|
-
|
125
|
+
def no_such_window_error
|
126
|
+
Ferrum::NoSuchPageError
|
127
|
+
end
|
132
128
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
129
|
+
def reset!
|
130
|
+
@zoom_factor = nil
|
131
|
+
@paper_size = nil
|
132
|
+
browser.url_blacklist = @options[:url_blacklist]
|
133
|
+
browser.url_whitelist = @options[:url_whitelist]
|
134
|
+
browser.reset
|
135
|
+
@started = false
|
136
|
+
end
|
139
137
|
|
140
|
-
|
141
|
-
|
142
|
-
end
|
138
|
+
def save_screenshot(path, options = {})
|
139
|
+
options[:scale] = @zoom_factor if @zoom_factor
|
143
140
|
|
144
|
-
|
145
|
-
|
146
|
-
|
141
|
+
if pdf?(path, options)
|
142
|
+
options[:paperWidth] = @paper_size[:width].to_f if @paper_size
|
143
|
+
options[:paperHeight] = @paper_size[:height].to_f if @paper_size
|
144
|
+
browser.pdf(path: path, **options)
|
145
|
+
else
|
146
|
+
browser.screenshot(path: path, **options)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
alias render save_screenshot
|
147
150
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
+
def render_base64(format = :png, options = {})
|
152
|
+
if pdf?(nil, options)
|
153
|
+
options[:paperWidth] = @paper_size[:width].to_f if @paper_size
|
154
|
+
options[:paperHeight] = @paper_size[:height].to_f if @paper_size
|
155
|
+
browser.pdf(encoding: :base64, **options)
|
156
|
+
else
|
157
|
+
browser.screenshot(format: format, encoding: :base64, **options)
|
158
|
+
end
|
159
|
+
end
|
151
160
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
browser.url_blacklist = @options[:url_blacklist]
|
156
|
-
browser.url_whitelist = @options[:url_whitelist]
|
157
|
-
browser.reset
|
158
|
-
@started = false
|
159
|
-
end
|
161
|
+
def zoom_factor=(value)
|
162
|
+
@zoom_factor = value.to_f
|
163
|
+
end
|
160
164
|
|
161
|
-
|
162
|
-
options[:scale] = @zoom_factor if @zoom_factor
|
165
|
+
attr_writer :paper_size
|
163
166
|
|
164
|
-
|
165
|
-
|
166
|
-
options[:paperHeight] = @paper_size[:height].to_f if @paper_size
|
167
|
-
browser.pdf(path: path, **options)
|
168
|
-
else
|
169
|
-
browser.screenshot(path: path, **options)
|
167
|
+
def resize(width, height)
|
168
|
+
browser.resize(width: width, height: height)
|
170
169
|
end
|
171
|
-
|
172
|
-
alias_method :render, :save_screenshot
|
170
|
+
alias resize_window resize
|
173
171
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
browser.pdf(encoding: :base64, **options)
|
179
|
-
else
|
180
|
-
browser.screenshot(format: format, encoding: :base64, **options)
|
172
|
+
def resize_window_to(handle, width, height)
|
173
|
+
within_window(handle) do
|
174
|
+
resize(width, height)
|
175
|
+
end
|
181
176
|
end
|
182
|
-
end
|
183
177
|
|
184
|
-
|
185
|
-
|
186
|
-
|
178
|
+
def maximize_window(handle)
|
179
|
+
resize_window_to(handle, *screen_size)
|
180
|
+
end
|
187
181
|
|
188
|
-
|
189
|
-
|
190
|
-
|
182
|
+
def window_size(handle)
|
183
|
+
within_window(handle) do
|
184
|
+
evaluate_script("[window.innerWidth, window.innerHeight]")
|
185
|
+
end
|
186
|
+
end
|
191
187
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
188
|
+
def fullscreen_window(handle)
|
189
|
+
within_window(handle) do
|
190
|
+
browser.resize(fullscreen: true)
|
191
|
+
end
|
192
|
+
end
|
196
193
|
|
197
|
-
|
198
|
-
|
199
|
-
resize(width, height)
|
194
|
+
def scroll_to(left, top)
|
195
|
+
browser.mouse.scroll_to(left, top)
|
200
196
|
end
|
201
|
-
end
|
202
197
|
|
203
|
-
|
204
|
-
|
205
|
-
end
|
198
|
+
def network_traffic(type = nil)
|
199
|
+
traffic = browser.network.traffic
|
206
200
|
|
207
|
-
|
208
|
-
|
209
|
-
|
201
|
+
case type.to_s
|
202
|
+
when "all"
|
203
|
+
traffic
|
204
|
+
when "blocked"
|
205
|
+
traffic.select(&:blocked?)
|
206
|
+
else
|
207
|
+
# when request isn't blocked
|
208
|
+
traffic.reject(&:blocked?)
|
209
|
+
end
|
210
210
|
end
|
211
|
-
end
|
212
211
|
|
213
|
-
|
214
|
-
|
215
|
-
browser.resize(fullscreen: true)
|
212
|
+
def clear_network_traffic
|
213
|
+
browser.network.clear(:traffic)
|
216
214
|
end
|
217
|
-
end
|
218
215
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
def network_traffic(type = nil)
|
224
|
-
traffic = browser.network.traffic
|
216
|
+
def set_proxy(host, port, user = nil, password = nil, bypass = nil)
|
217
|
+
@options.merge!(proxy: { host: host, port: port, user: user, password: password, bypass: bypass })
|
218
|
+
end
|
225
219
|
|
226
|
-
|
227
|
-
|
228
|
-
traffic
|
229
|
-
when "blocked"
|
230
|
-
traffic.select(&:blocked?)
|
231
|
-
else
|
232
|
-
# when request isn't blocked
|
233
|
-
traffic.reject(&:blocked?)
|
220
|
+
def headers
|
221
|
+
browser.headers.get
|
234
222
|
end
|
235
|
-
end
|
236
223
|
|
237
|
-
|
238
|
-
|
239
|
-
|
224
|
+
def headers=(headers)
|
225
|
+
browser.headers.set(headers)
|
226
|
+
end
|
240
227
|
|
241
|
-
|
242
|
-
|
243
|
-
server = type ? "#{type}=#{ip}:#{port}" : "#{ip}:#{port}"
|
244
|
-
@options[:browser_options].merge!("proxy-server" => server)
|
245
|
-
@options[:browser_options].merge!("proxy-bypass-list" => bypass) if bypass
|
246
|
-
browser.network.authorize(type: :proxy, user: user, password: password) do |request|
|
247
|
-
request.continue
|
228
|
+
def add_headers(headers)
|
229
|
+
browser.headers.add(headers)
|
248
230
|
end
|
249
|
-
end
|
250
231
|
|
251
|
-
|
252
|
-
|
253
|
-
|
232
|
+
def add_header(name, value, permanent: true)
|
233
|
+
browser.headers.add({ name => value }, permanent: permanent)
|
234
|
+
end
|
254
235
|
|
255
|
-
|
256
|
-
|
257
|
-
|
236
|
+
def response_headers
|
237
|
+
browser.network.response&.headers
|
238
|
+
end
|
258
239
|
|
259
|
-
|
260
|
-
|
261
|
-
|
240
|
+
def cookies
|
241
|
+
browser.cookies.all
|
242
|
+
end
|
262
243
|
|
263
|
-
|
264
|
-
|
265
|
-
|
244
|
+
def set_cookie(name, value, options = {})
|
245
|
+
options = options.dup
|
246
|
+
options[:name] ||= name
|
247
|
+
options[:value] ||= value
|
248
|
+
options[:domain] ||= default_domain
|
249
|
+
browser.cookies.set(**options)
|
250
|
+
end
|
266
251
|
|
267
|
-
|
268
|
-
|
269
|
-
|
252
|
+
def remove_cookie(name, **options)
|
253
|
+
options[:domain] = default_domain if options.empty?
|
254
|
+
browser.cookies.remove(**options.merge(name: name))
|
255
|
+
end
|
270
256
|
|
271
|
-
|
272
|
-
|
273
|
-
|
257
|
+
def clear_cookies
|
258
|
+
browser.cookies.clear
|
259
|
+
end
|
274
260
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
options[:value] ||= value
|
279
|
-
options[:domain] ||= default_domain
|
280
|
-
browser.cookies.set(**options)
|
281
|
-
end
|
261
|
+
def wait_for_network_idle(**options)
|
262
|
+
browser.network.wait_for_idle(**options)
|
263
|
+
end
|
282
264
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
end
|
265
|
+
def clear_memory_cache
|
266
|
+
browser.network.clear(:cache)
|
267
|
+
end
|
287
268
|
|
288
|
-
|
289
|
-
|
290
|
-
|
269
|
+
def basic_authorize(user, password)
|
270
|
+
browser.network.authorize(user: user, password: password) do |request, _index, _total|
|
271
|
+
request.continue
|
272
|
+
end
|
273
|
+
end
|
274
|
+
alias authorize basic_authorize
|
291
275
|
|
292
|
-
|
293
|
-
|
294
|
-
end
|
276
|
+
def debug_url
|
277
|
+
response = JSON.parse(Net::HTTP.get(URI(build_remote_debug_url(path: "/json"))))
|
295
278
|
|
296
|
-
|
297
|
-
|
298
|
-
end
|
279
|
+
devtools_frontend_path = response[0]&.[]("devtoolsFrontendUrl")
|
280
|
+
raise "Could not generate debug url for remote debugging session" unless devtools_frontend_path
|
299
281
|
|
300
|
-
|
301
|
-
browser.network.authorize(user: user, password: password) do |request|
|
302
|
-
request.continue
|
282
|
+
build_remote_debug_url(path: devtools_frontend_path)
|
303
283
|
end
|
304
|
-
end
|
305
|
-
alias_method :authorize, :basic_authorize
|
306
|
-
|
307
|
-
def debug_url
|
308
|
-
"http://#{browser.process.host}:#{browser.process.port}"
|
309
|
-
end
|
310
284
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
285
|
+
def debug(binding = nil)
|
286
|
+
if @options[:inspector]
|
287
|
+
Process.spawn(browser.process.path, debug_url)
|
288
|
+
|
289
|
+
if binding.respond_to?(:pry)
|
290
|
+
Pry.start(binding)
|
291
|
+
elsif binding.respond_to?(:irb)
|
292
|
+
binding.irb
|
293
|
+
else
|
294
|
+
pause
|
295
|
+
end
|
319
296
|
else
|
320
|
-
|
297
|
+
raise Error, "To use the remote debugging, you have to launch " \
|
298
|
+
"the driver with `inspector: ENV['INSPECTOR']` " \
|
299
|
+
"configuration option and run your test suite passing " \
|
300
|
+
"env variable"
|
321
301
|
end
|
322
|
-
else
|
323
|
-
raise Error, "To use the remote debugging, you have to launch " \
|
324
|
-
"the driver with `inspector: ENV['INSPECTOR']` " \
|
325
|
-
"configuration option and run your test suite passing " \
|
326
|
-
"env variable"
|
327
302
|
end
|
328
|
-
end
|
329
|
-
|
330
|
-
def pause
|
331
|
-
# STDIN is not necessarily connected to a keyboard. It might even be closed.
|
332
|
-
# So we need a method other than keypress to continue.
|
333
303
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
thread = Thread.new { IO.copy_stream(STDIN, write); write.close }
|
304
|
+
def pause
|
305
|
+
# STDIN is not necessarily connected to a keyboard. It might even be closed.
|
306
|
+
# So we need a method other than keypress to continue.
|
338
307
|
|
339
|
-
|
308
|
+
# In jRuby - STDIN returns immediately from select
|
309
|
+
# see https://github.com/jruby/jruby/issues/1783
|
310
|
+
read, write = IO.pipe
|
311
|
+
thread = Thread.new do
|
312
|
+
IO.copy_stream($stdin, write)
|
313
|
+
write.close
|
314
|
+
end
|
340
315
|
|
341
|
-
|
342
|
-
old_trap = trap("SIGCONT") { signal = true; STDERR.puts "\nSignal SIGCONT received" }
|
343
|
-
keyboard = IO.select([read], nil, nil, 1) until keyboard || signal # wait for data on STDIN or signal SIGCONT received
|
316
|
+
warn "Cuprite execution paused. Press enter (or run 'kill -CONT #{Process.pid}') to continue."
|
344
317
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
318
|
+
signal = false
|
319
|
+
old_trap = trap("SIGCONT") do
|
320
|
+
signal = true
|
321
|
+
warn "\nSignal SIGCONT received"
|
322
|
+
end
|
323
|
+
keyboard = read.wait_readable(1) until keyboard || signal # wait for data on STDIN or signal SIGCONT received
|
324
|
+
|
325
|
+
unless signal
|
326
|
+
begin
|
327
|
+
input = read.read_nonblock(80) # clear out the read buffer
|
328
|
+
puts unless input&.end_with?("\n")
|
329
|
+
rescue EOFError, IO::WaitReadable
|
330
|
+
# Ignore problems reading from STDIN.
|
331
|
+
end
|
350
332
|
end
|
333
|
+
ensure
|
334
|
+
thread.kill
|
335
|
+
read.close
|
336
|
+
trap("SIGCONT", old_trap) # Restore the previous signal handler, if there was one.
|
337
|
+
warn "Continuing"
|
351
338
|
end
|
352
|
-
ensure
|
353
|
-
thread.kill
|
354
|
-
read.close
|
355
|
-
trap("SIGCONT", old_trap) # Restore the previous signal handler, if there was one.
|
356
|
-
STDERR.puts "Continuing"
|
357
|
-
end
|
358
|
-
|
359
|
-
def wait?
|
360
|
-
true
|
361
|
-
end
|
362
|
-
|
363
|
-
def invalid_element_errors
|
364
|
-
[Capybara::Cuprite::ObsoleteNode,
|
365
|
-
Capybara::Cuprite::MouseEventFailed,
|
366
|
-
Ferrum::NoExecutionContextError,
|
367
|
-
Ferrum::NodeNotFoundError]
|
368
|
-
end
|
369
339
|
|
370
|
-
|
371
|
-
|
372
|
-
|
340
|
+
def wait?
|
341
|
+
true
|
342
|
+
end
|
373
343
|
|
374
|
-
|
375
|
-
|
376
|
-
|
344
|
+
def invalid_element_errors
|
345
|
+
[Capybara::Cuprite::ObsoleteNode,
|
346
|
+
Capybara::Cuprite::MouseEventFailed,
|
347
|
+
Ferrum::CoordinatesNotFoundError,
|
348
|
+
Ferrum::NoExecutionContextError,
|
349
|
+
Ferrum::NodeNotFoundError]
|
350
|
+
end
|
377
351
|
|
378
|
-
|
379
|
-
|
380
|
-
|
352
|
+
def accept_modal(type, options = {})
|
353
|
+
case type
|
354
|
+
when :alert, :confirm
|
355
|
+
browser.accept_confirm
|
356
|
+
when :prompt
|
357
|
+
browser.accept_prompt(options[:with])
|
358
|
+
end
|
381
359
|
|
382
|
-
|
383
|
-
browser.wait_for_reload(*args)
|
384
|
-
end
|
360
|
+
yield if block_given?
|
385
361
|
|
386
|
-
|
387
|
-
case type
|
388
|
-
when :alert, :confirm
|
389
|
-
browser.accept_confirm
|
390
|
-
when :prompt
|
391
|
-
browser.accept_prompt(options[:with])
|
362
|
+
browser.find_modal(options)
|
392
363
|
end
|
393
364
|
|
394
|
-
|
365
|
+
def dismiss_modal(type, options = {})
|
366
|
+
case type
|
367
|
+
when :confirm
|
368
|
+
browser.dismiss_confirm
|
369
|
+
when :prompt
|
370
|
+
browser.dismiss_prompt
|
371
|
+
end
|
395
372
|
|
396
|
-
|
397
|
-
end
|
373
|
+
yield if block_given?
|
398
374
|
|
399
|
-
|
400
|
-
case type
|
401
|
-
when :confirm
|
402
|
-
browser.dismiss_confirm
|
403
|
-
when :prompt
|
404
|
-
browser.dismiss_prompt
|
375
|
+
browser.find_modal(options)
|
405
376
|
end
|
406
377
|
|
407
|
-
|
408
|
-
|
409
|
-
browser.find_modal(options)
|
410
|
-
end
|
378
|
+
private
|
411
379
|
|
412
|
-
|
380
|
+
def build_remote_debug_url(path:)
|
381
|
+
"http://#{browser.process.host}:#{browser.process.port}#{path}"
|
382
|
+
end
|
413
383
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
384
|
+
def default_domain
|
385
|
+
if @started
|
386
|
+
URI.parse(browser.current_url).host
|
387
|
+
else
|
388
|
+
URI.parse(default_cookie_host).host || "127.0.0.1"
|
389
|
+
end
|
419
390
|
end
|
420
|
-
end
|
421
391
|
|
422
|
-
|
423
|
-
|
424
|
-
|
392
|
+
def native_args(args)
|
393
|
+
args.map { |arg| arg.is_a?(Capybara::Cuprite::Node) ? arg.node : arg }
|
394
|
+
end
|
425
395
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
396
|
+
def session_wait_time
|
397
|
+
if respond_to?(:session_options)
|
398
|
+
session_options.default_max_wait_time
|
399
|
+
else
|
400
|
+
begin
|
401
|
+
Capybara.default_max_wait_time
|
402
|
+
rescue StandardError
|
403
|
+
Capybara.default_wait_time
|
404
|
+
end
|
434
405
|
end
|
435
406
|
end
|
436
|
-
end
|
437
407
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
408
|
+
def default_cookie_host
|
409
|
+
if respond_to?(:session_options)
|
410
|
+
session_options.app_host
|
411
|
+
else
|
412
|
+
Capybara.app_host
|
413
|
+
end || ""
|
414
|
+
end
|
445
415
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
416
|
+
def unwrap_script_result(arg)
|
417
|
+
case arg
|
418
|
+
when Array
|
419
|
+
arg.map { |e| unwrap_script_result(e) }
|
420
|
+
when Hash
|
421
|
+
arg.each { |k, v| arg[k] = unwrap_script_result(v) }
|
422
|
+
when Ferrum::Node
|
423
|
+
Node.new(self, arg)
|
424
|
+
else
|
425
|
+
arg
|
426
|
+
end
|
456
427
|
end
|
457
|
-
end
|
458
428
|
|
459
|
-
|
460
|
-
|
461
|
-
|
429
|
+
def pdf?(path, options)
|
430
|
+
(path && File.extname(path).delete(".") == "pdf") ||
|
431
|
+
options[:format].to_s == "pdf"
|
432
|
+
end
|
462
433
|
end
|
463
434
|
end
|
464
435
|
end
|
436
|
+
# rubocop:enable Metrics/ClassLength
|