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.
@@ -3,462 +3,434 @@
3
3
  require "uri"
4
4
  require "forwardable"
5
5
 
6
- module Capybara::Cuprite
7
- class Driver < Capybara::Driver::Base
8
- DEFAULT_MAXIMIZE_SCREEN_SIZE = [1366, 768].freeze
9
- EXTENSION = File.expand_path("javascripts/index.js", __dir__)
10
-
11
- extend Forwardable
12
-
13
- delegate %i(restart quit status_code timeout timeout=) => :browser
14
-
15
- attr_reader :app, :options, :screen_size
16
-
17
- def initialize(app, options = {})
18
- @app = app
19
- @options = options.dup
20
- @started = false
21
-
22
- @options[:extensions] ||= []
23
- @options[:extensions] << EXTENSION
24
-
25
- @screen_size = @options.delete(:screen_size)
26
- @screen_size ||= DEFAULT_MAXIMIZE_SCREEN_SIZE
27
-
28
- @options[:save_path] = Capybara.save_path.to_s if Capybara.save_path
29
-
30
- ENV["FERRUM_DEBUG"] = "true" if ENV["CUPRITE_DEBUG"]
31
- end
32
-
33
- def needs_server?
34
- true
35
- end
36
-
37
- def browser
38
- @browser ||= Browser.new(@options)
39
- end
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
- def visit(url)
42
- @started = true
43
- browser.visit(url)
44
- end
44
+ super()
45
+ end
45
46
 
46
- def current_url
47
- if Capybara::VERSION.to_f < 3.0
48
- frame_url
49
- else
50
- browser.current_url
47
+ def needs_server?
48
+ true
51
49
  end
52
- end
53
50
 
54
- def frame_url
55
- evaluate_script("window.location.href")
56
- end
51
+ def browser
52
+ @browser ||= Browser.new(@options)
53
+ end
57
54
 
58
- def html
59
- browser.body
60
- end
61
- alias_method :body, :html
55
+ def visit(url)
56
+ @started = true
57
+ browser.visit(url)
58
+ end
62
59
 
63
- def source
64
- browser.source.to_s
65
- end
60
+ def frame_url
61
+ evaluate_script("window.location.href")
62
+ end
66
63
 
67
- def title
68
- if Capybara::VERSION.to_f < 3.0
69
- frame_title
70
- else
71
- browser.title
64
+ def source
65
+ browser.source.to_s
72
66
  end
73
- end
74
67
 
75
- def frame_title
76
- evaluate_script("document.title")
77
- end
68
+ def frame_title
69
+ evaluate_script("document.title")
70
+ end
78
71
 
79
- def find_xpath(selector)
80
- find(:xpath, selector)
81
- end
72
+ def active_element
73
+ Node.new(self, browser.active_element)
74
+ end
82
75
 
83
- def find_css(selector)
84
- find(:css, selector)
85
- end
76
+ def find_xpath(selector)
77
+ find(:xpath, selector)
78
+ end
86
79
 
87
- def find(method, selector)
88
- browser.find(method, selector).map { |native| Node.new(self, native) }
89
- end
80
+ def find_css(selector)
81
+ find(:css, selector)
82
+ end
90
83
 
91
- def click(x, y)
92
- browser.mouse.click(x: x, y: y)
93
- end
84
+ def find(method, selector)
85
+ browser.find(method, selector).map { |native| Node.new(self, native) }
86
+ end
94
87
 
95
- def evaluate_script(script, *args)
96
- result = browser.evaluate(script, *native_args(args))
97
- unwrap_script_result(result)
98
- end
88
+ def click(x, y)
89
+ browser.mouse.click(x: x, y: y)
90
+ end
99
91
 
100
- def evaluate_async_script(script, *args)
101
- result = browser.evaluate_async(script, session_wait_time, *native_args(args))
102
- unwrap_script_result(result)
103
- end
92
+ def evaluate_script(script, *args)
93
+ result = browser.evaluate(script, *native_args(args))
94
+ unwrap_script_result(result)
95
+ end
104
96
 
105
- def execute_script(script, *args)
106
- browser.execute(script, *native_args(args))
107
- nil
108
- end
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
- def switch_to_frame(locator)
111
- handle = case locator
112
- when Capybara::Node::Element
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
- browser.switch_to_frame(handle)
119
- end
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
- def current_window_handle
122
- browser.window_handle
123
- end
115
+ browser.switch_to_frame(handle)
116
+ end
124
117
 
125
- def window_handles
126
- browser.window_handles
127
- end
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
- def close_window(handle)
130
- browser.close_window(handle)
131
- end
125
+ def no_such_window_error
126
+ Ferrum::NoSuchPageError
127
+ end
132
128
 
133
- def open_new_window
134
- target = browser.default_context.create_target
135
- target.maybe_sleep_if_new_window
136
- target.page = Page.new(target.id, browser)
137
- target.page
138
- end
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
- def switch_to_window(handle)
141
- browser.switch_to_window(handle)
142
- end
138
+ def save_screenshot(path, options = {})
139
+ options[:scale] = @zoom_factor if @zoom_factor
143
140
 
144
- def within_window(name, &block)
145
- browser.within_window(name, &block)
146
- end
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
- def no_such_window_error
149
- Ferrum::NoSuchPageError
150
- end
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
- def reset!
153
- @zoom_factor = nil
154
- @paper_size = nil
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
- def save_screenshot(path, options = {})
162
- options[:scale] = @zoom_factor if @zoom_factor
165
+ attr_writer :paper_size
163
166
 
164
- if pdf?(path, options)
165
- options[:paperWidth] = @paper_size[:width].to_f if @paper_size
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
- end
172
- alias_method :render, :save_screenshot
170
+ alias resize_window resize
173
171
 
174
- def render_base64(format = :png, options = {})
175
- if pdf?(nil, options)
176
- options[:paperWidth] = @paper_size[:width].to_f if @paper_size
177
- options[:paperHeight] = @paper_size[:height].to_f if @paper_size
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
- def zoom_factor=(value)
185
- @zoom_factor = value.to_f
186
- end
178
+ def maximize_window(handle)
179
+ resize_window_to(handle, *screen_size)
180
+ end
187
181
 
188
- def paper_size=(value)
189
- @paper_size = value
190
- end
182
+ def window_size(handle)
183
+ within_window(handle) do
184
+ evaluate_script("[window.innerWidth, window.innerHeight]")
185
+ end
186
+ end
191
187
 
192
- def resize(width, height)
193
- browser.resize(width: width, height: height)
194
- end
195
- alias_method :resize_window, :resize
188
+ def fullscreen_window(handle)
189
+ within_window(handle) do
190
+ browser.resize(fullscreen: true)
191
+ end
192
+ end
196
193
 
197
- def resize_window_to(handle, width, height)
198
- within_window(handle) do
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
- def maximize_window(handle)
204
- resize_window_to(handle, *screen_size)
205
- end
198
+ def network_traffic(type = nil)
199
+ traffic = browser.network.traffic
206
200
 
207
- def window_size(handle)
208
- within_window(handle) do
209
- evaluate_script("[window.innerWidth, window.innerHeight]")
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
- def fullscreen_window(handle)
214
- within_window(handle) do
215
- browser.resize(fullscreen: true)
212
+ def clear_network_traffic
213
+ browser.network.clear(:traffic)
216
214
  end
217
- end
218
215
 
219
- def scroll_to(left, top)
220
- browser.mouse.scroll_to(left, top)
221
- end
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
- case type.to_s
227
- when "all"
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
- def clear_network_traffic
238
- browser.network.clear(:traffic)
239
- end
224
+ def headers=(headers)
225
+ browser.headers.set(headers)
226
+ end
240
227
 
241
- def set_proxy(ip, port, type = nil, user = nil, password = nil, bypass = nil)
242
- @options[:browser_options] ||= {}
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
- def headers
252
- browser.headers.get
253
- end
232
+ def add_header(name, value, permanent: true)
233
+ browser.headers.add({ name => value }, permanent: permanent)
234
+ end
254
235
 
255
- def headers=(headers)
256
- browser.headers.set(headers)
257
- end
236
+ def response_headers
237
+ browser.network.response&.headers
238
+ end
258
239
 
259
- def add_headers(headers)
260
- browser.headers.add(headers)
261
- end
240
+ def cookies
241
+ browser.cookies.all
242
+ end
262
243
 
263
- def add_header(name, value, permanent: true)
264
- browser.headers.add({ name => value }, permanent: permanent)
265
- end
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
- def response_headers
268
- browser.network.response&.headers
269
- end
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
- def cookies
272
- browser.cookies.all
273
- end
257
+ def clear_cookies
258
+ browser.cookies.clear
259
+ end
274
260
 
275
- def set_cookie(name, value, options = {})
276
- options = options.dup
277
- options[:name] ||= name
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
- def remove_cookie(name, **options)
284
- options[:domain] = default_domain if options.empty?
285
- browser.cookies.remove(**options.merge(name: name))
286
- end
265
+ def clear_memory_cache
266
+ browser.network.clear(:cache)
267
+ end
287
268
 
288
- def clear_cookies
289
- browser.cookies.clear
290
- end
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
- def wait_for_network_idle(**options)
293
- browser.network.wait_for_idle(**options)
294
- end
276
+ def debug_url
277
+ response = JSON.parse(Net::HTTP.get(URI(build_remote_debug_url(path: "/json"))))
295
278
 
296
- def clear_memory_cache
297
- browser.network.clear(:cache)
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
- def basic_authorize(user, password)
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
- def debug(binding = nil)
312
- if @options[:inspector]
313
- Process.spawn(browser.process.path, debug_url)
314
-
315
- if binding&.respond_to?(:pry)
316
- Pry.start(binding)
317
- elsif binding&.respond_to?(:irb)
318
- binding.irb
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
- pause
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
- # In jRuby - STDIN returns immediately from select
335
- # see https://github.com/jruby/jruby/issues/1783
336
- read, write = IO.pipe
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
- STDERR.puts "Cuprite execution paused. Press enter (or run 'kill -CONT #{Process.pid}') to continue."
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
- signal = false
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
- unless signal
346
- begin
347
- input = read.read_nonblock(80) # clear out the read buffer
348
- puts unless input&.end_with?("\n")
349
- rescue EOFError, IO::WaitReadable # Ignore problems reading from STDIN.
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
- def go_back
371
- browser.back
372
- end
340
+ def wait?
341
+ true
342
+ end
373
343
 
374
- def go_forward
375
- browser.forward
376
- end
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
- def refresh
379
- browser.refresh
380
- end
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
- def wait_for_reload(*args)
383
- browser.wait_for_reload(*args)
384
- end
360
+ yield if block_given?
385
361
 
386
- def accept_modal(type, options = {})
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
- yield if block_given?
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
- browser.find_modal(options)
397
- end
373
+ yield if block_given?
398
374
 
399
- def dismiss_modal(type, options = {})
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
- yield if block_given?
408
-
409
- browser.find_modal(options)
410
- end
378
+ private
411
379
 
412
- private
380
+ def build_remote_debug_url(path:)
381
+ "http://#{browser.process.host}:#{browser.process.port}#{path}"
382
+ end
413
383
 
414
- def default_domain
415
- if @started
416
- URI.parse(browser.current_url).host
417
- else
418
- URI.parse(default_cookie_host).host || "127.0.0.1"
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
- def native_args(args)
423
- args.map { |arg| arg.is_a?(Capybara::Cuprite::Node) ? arg.node : arg }
424
- end
392
+ def native_args(args)
393
+ args.map { |arg| arg.is_a?(Capybara::Cuprite::Node) ? arg.node : arg }
394
+ end
425
395
 
426
- def session_wait_time
427
- if respond_to?(:session_options)
428
- session_options.default_max_wait_time
429
- else
430
- begin
431
- Capybara.default_max_wait_time
432
- rescue
433
- Capybara.default_wait_time
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
- def default_cookie_host
439
- if respond_to?(:session_options)
440
- session_options.app_host
441
- else
442
- Capybara.app_host
443
- end || ""
444
- end
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
- def unwrap_script_result(arg)
447
- case arg
448
- when Array
449
- arg.map { |e| unwrap_script_result(e) }
450
- when Hash
451
- arg.each { |k, v| arg[k] = unwrap_script_result(v) }
452
- when Ferrum::Node
453
- Node.new(self, arg)
454
- else
455
- arg
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
- def pdf?(path, options)
460
- (path && File.extname(path).delete(".") == "pdf") ||
461
- options[:format].to_s == "pdf"
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