cuprite 0.12 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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