cuprite 0.13 → 0.14

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.
@@ -1,214 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "forwardable"
4
-
5
- module Capybara::Cuprite
6
- class Browser < Ferrum::Browser
7
- extend Forwardable
8
-
9
- delegate %i[send_keys select set hover trigger before_click switch_to_frame
10
- find_modal accept_confirm dismiss_confirm accept_prompt
11
- dismiss_prompt reset_modals] => :page
12
-
13
- attr_reader :url_blacklist, :url_whitelist
14
-
15
- def initialize(options = nil)
16
- options ||= {}
17
- self.url_blacklist = options[:url_blacklist]
18
- self.url_whitelist = options[:url_whitelist]
19
-
20
- super
21
- @page = false
22
- end
23
-
24
- def page
25
- raise Ferrum::NoSuchPageError if @page.nil?
26
- @page ||= attach_page
27
- end
28
-
29
- def reset
30
- super
31
- @page = attach_page
32
- end
33
-
34
- def quit
35
- super
36
- @page = false
37
- end
38
-
39
- def url_whitelist=(patterns)
40
- @url_whitelist = prepare_wildcards(patterns)
41
- page.network.intercept if @client && !@url_whitelist.empty?
42
- end
43
-
44
- def url_blacklist=(patterns)
45
- @url_blacklist = prepare_wildcards(patterns)
46
- page.network.intercept if @client && !@url_blacklist.empty?
47
- end
48
-
49
- def visit(*args)
50
- goto(*args)
51
- end
52
-
53
- def status_code
54
- network.status
55
- end
56
-
57
- def find(method, selector)
58
- find_all(method, selector)
59
- end
60
-
61
- def property(node, name)
62
- node.property(name)
63
- end
64
-
65
- def find_within(node, method, selector)
66
- resolved = page.command("DOM.resolveNode", nodeId: node.node_id)
67
- object_id = resolved.dig("object", "objectId")
68
- find_all(method, selector, { "objectId" => object_id })
69
- end
70
-
71
- def window_handle
72
- page.target_id
73
- end
74
-
75
- def window_handles
76
- targets.keys
77
- end
78
-
79
- def within_window(locator = nil, &block)
80
- original = window_handle
81
-
82
- if Capybara::VERSION.to_f < 3.0
83
- target_id = window_handles.find do |target_id|
84
- page = attach_page(target_id)
85
- locator == page.frame_name
86
- end
87
- locator = target_id if target_id
88
- end
89
-
90
- if window_handles.include?(locator)
91
- switch_to_window(locator)
92
- yield
93
- else
94
- raise Ferrum::NoSuchPageError
95
- end
96
- ensure
97
- switch_to_window(original)
98
- end
99
-
100
- def switch_to_window(target_id)
101
- target = targets[target_id]
102
- raise Ferrum::NoSuchPageError unless target
103
- @page = attach_page(target.id)
104
- end
105
-
106
- def close_window(target_id)
107
- target = targets[target_id]
108
- raise Ferrum::NoSuchPageError unless target
109
- @page = nil if @page.target_id == target.id
110
- target.page.close
111
- end
112
-
113
- def browser_error
114
- evaluate("_cuprite.browserError()")
115
- end
116
-
117
- def source
118
- raise NotImplementedError
119
- end
120
-
121
- def drag(node, other)
122
- raise NotImplementedError
123
- end
124
-
125
- def drag_by(node, x, y)
126
- raise NotImplementedError
127
- end
128
-
129
- def select_file(node, value)
130
- node.select_file(value)
131
- end
132
-
133
- def parents(node)
134
- evaluate_on(node: node, expression: "_cuprite.parents(this)", by_value: false)
135
- end
136
-
137
- def visible_text(node)
138
- evaluate_on(node: node, expression: "_cuprite.visibleText(this)")
139
- end
140
-
141
- def delete_text(node)
142
- evaluate_on(node: node, expression: "_cuprite.deleteText(this)")
143
- end
144
-
145
- def attributes(node)
146
- value = evaluate_on(node: node, expression: "_cuprite.getAttributes(this)")
147
- JSON.parse(value)
148
- end
149
-
150
- def attribute(node, name)
151
- evaluate_on(node: node, expression: %Q(_cuprite.getAttribute(this, "#{name}")))
152
- end
153
-
154
- def value(node)
155
- evaluate_on(node: node, expression: "_cuprite.value(this)")
156
- end
157
-
158
- def visible?(node)
159
- evaluate_on(node: node, expression: "_cuprite.isVisible(this)")
160
- end
161
-
162
- def disabled?(node)
163
- evaluate_on(node: node, expression: "_cuprite.isDisabled(this)")
164
- end
165
-
166
- def path(node)
167
- evaluate_on(node: node, expression: "_cuprite.path(this)")
168
- end
169
-
170
- def all_text(node)
171
- node.text
172
- end
173
-
174
- private
175
-
176
- def find_all(method, selector, within = nil)
177
- begin
178
- nodes = if within
179
- evaluate("_cuprite.find(arguments[0], arguments[1], arguments[2])", method, selector, within)
180
- else
181
- evaluate("_cuprite.find(arguments[0], arguments[1])", method, selector)
182
- end
183
-
184
- nodes.map { |n| n.node? ? n : next }.compact
185
- rescue Ferrum::JavaScriptError => e
186
- if e.class_name == "InvalidSelector"
187
- raise InvalidSelector.new(e.response, method, selector)
188
- end
189
- raise
190
- end
191
- end
192
-
193
- def prepare_wildcards(wc)
194
- Array(wc).map do |wildcard|
195
- if wildcard.is_a?(Regexp)
196
- wildcard
197
- else
198
- wildcard = wildcard.gsub("*", ".*")
199
- Regexp.new(wildcard, Regexp::IGNORECASE)
200
- end
201
- end
202
- end
203
-
204
- def attach_page(target_id = nil)
205
- target = targets[target_id] if target_id
206
- target ||= default_context.default_target
207
- return target.page if target.attached?
208
-
209
- target.maybe_sleep_if_new_window
210
- target.page = Page.new(target.id, self)
211
- target.page
212
- end
213
- end
214
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Capybara::Cuprite
4
- class Cookie
5
- def initialize(attributes)
6
- @attributes = attributes
7
- end
8
-
9
- def name
10
- @attributes["name"]
11
- end
12
-
13
- def value
14
- @attributes["value"]
15
- end
16
-
17
- def domain
18
- @attributes["domain"]
19
- end
20
-
21
- def path
22
- @attributes["path"]
23
- end
24
-
25
- def size
26
- @attributes["size"]
27
- end
28
-
29
- def secure?
30
- @attributes["secure"]
31
- end
32
-
33
- def httponly?
34
- @attributes["httpOnly"]
35
- end
36
-
37
- def session?
38
- @attributes["session"]
39
- end
40
-
41
- def expires
42
- if @attributes["expires"] > 0
43
- Time.at(@attributes["expires"])
44
- end
45
- end
46
- end
47
- end
@@ -1,465 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "uri"
4
- require "forwardable"
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
40
-
41
- def visit(url)
42
- @started = true
43
- browser.visit(url)
44
- end
45
-
46
- def current_url
47
- if Capybara::VERSION.to_f < 3.0
48
- frame_url
49
- else
50
- browser.current_url
51
- end
52
- end
53
-
54
- def frame_url
55
- evaluate_script("window.location.href")
56
- end
57
-
58
- def html
59
- browser.body
60
- end
61
- alias_method :body, :html
62
-
63
- def source
64
- browser.source.to_s
65
- end
66
-
67
- def title
68
- if Capybara::VERSION.to_f < 3.0
69
- frame_title
70
- else
71
- browser.title
72
- end
73
- end
74
-
75
- def frame_title
76
- evaluate_script("document.title")
77
- end
78
-
79
- def find_xpath(selector)
80
- find(:xpath, selector)
81
- end
82
-
83
- def find_css(selector)
84
- find(:css, selector)
85
- end
86
-
87
- def find(method, selector)
88
- browser.find(method, selector).map { |native| Node.new(self, native) }
89
- end
90
-
91
- def click(x, y)
92
- browser.mouse.click(x: x, y: y)
93
- end
94
-
95
- def evaluate_script(script, *args)
96
- result = browser.evaluate(script, *native_args(args))
97
- unwrap_script_result(result)
98
- end
99
-
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
104
-
105
- def execute_script(script, *args)
106
- browser.execute(script, *native_args(args))
107
- nil
108
- end
109
-
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
116
- end
117
-
118
- browser.switch_to_frame(handle)
119
- end
120
-
121
- def current_window_handle
122
- browser.window_handle
123
- end
124
-
125
- def window_handles
126
- browser.window_handles
127
- end
128
-
129
- def close_window(handle)
130
- browser.close_window(handle)
131
- end
132
-
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
139
-
140
- def switch_to_window(handle)
141
- browser.switch_to_window(handle)
142
- end
143
-
144
- def within_window(name, &block)
145
- browser.within_window(name, &block)
146
- end
147
-
148
- def no_such_window_error
149
- Ferrum::NoSuchPageError
150
- end
151
-
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
160
-
161
- def save_screenshot(path, options = {})
162
- options[:scale] = @zoom_factor if @zoom_factor
163
-
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)
170
- end
171
- end
172
- alias_method :render, :save_screenshot
173
-
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)
181
- end
182
- end
183
-
184
- def zoom_factor=(value)
185
- @zoom_factor = value.to_f
186
- end
187
-
188
- def paper_size=(value)
189
- @paper_size = value
190
- end
191
-
192
- def resize(width, height)
193
- browser.resize(width: width, height: height)
194
- end
195
- alias_method :resize_window, :resize
196
-
197
- def resize_window_to(handle, width, height)
198
- within_window(handle) do
199
- resize(width, height)
200
- end
201
- end
202
-
203
- def maximize_window(handle)
204
- resize_window_to(handle, *screen_size)
205
- end
206
-
207
- def window_size(handle)
208
- within_window(handle) do
209
- evaluate_script("[window.innerWidth, window.innerHeight]")
210
- end
211
- end
212
-
213
- def fullscreen_window(handle)
214
- within_window(handle) do
215
- browser.resize(fullscreen: true)
216
- end
217
- end
218
-
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
225
-
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?)
234
- end
235
- end
236
-
237
- def clear_network_traffic
238
- browser.network.clear(:traffic)
239
- end
240
-
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
248
- end
249
- end
250
-
251
- def headers
252
- browser.headers.get
253
- end
254
-
255
- def headers=(headers)
256
- browser.headers.set(headers)
257
- end
258
-
259
- def add_headers(headers)
260
- browser.headers.add(headers)
261
- end
262
-
263
- def add_header(name, value, permanent: true)
264
- browser.headers.add({ name => value }, permanent: permanent)
265
- end
266
-
267
- def response_headers
268
- browser.network.response&.headers
269
- end
270
-
271
- def cookies
272
- browser.cookies.all
273
- end
274
-
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
282
-
283
- def remove_cookie(name, **options)
284
- options[:domain] = default_domain if options.empty?
285
- browser.cookies.remove(**options.merge(name: name))
286
- end
287
-
288
- def clear_cookies
289
- browser.cookies.clear
290
- end
291
-
292
- def wait_for_network_idle(**options)
293
- browser.network.wait_for_idle(**options)
294
- end
295
-
296
- def clear_memory_cache
297
- browser.network.clear(:cache)
298
- end
299
-
300
- def basic_authorize(user, password)
301
- browser.network.authorize(user: user, password: password) do |request|
302
- request.continue
303
- 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
-
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
319
- else
320
- pause
321
- 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
- 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
-
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 }
338
-
339
- STDERR.puts "Cuprite execution paused. Press enter (or run 'kill -CONT #{Process.pid}') to continue."
340
-
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
344
-
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.
350
- end
351
- 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::CoordinatesNotFoundError,
367
- Ferrum::NoExecutionContextError,
368
- Ferrum::NodeNotFoundError]
369
- end
370
-
371
- def go_back
372
- browser.back
373
- end
374
-
375
- def go_forward
376
- browser.forward
377
- end
378
-
379
- def refresh
380
- browser.refresh
381
- end
382
-
383
- def wait_for_reload(*args)
384
- browser.wait_for_reload(*args)
385
- end
386
-
387
- def accept_modal(type, options = {})
388
- case type
389
- when :alert, :confirm
390
- browser.accept_confirm
391
- when :prompt
392
- browser.accept_prompt(options[:with])
393
- end
394
-
395
- yield if block_given?
396
-
397
- browser.find_modal(options)
398
- end
399
-
400
- def dismiss_modal(type, options = {})
401
- case type
402
- when :confirm
403
- browser.dismiss_confirm
404
- when :prompt
405
- browser.dismiss_prompt
406
- end
407
-
408
- yield if block_given?
409
-
410
- browser.find_modal(options)
411
- end
412
-
413
- private
414
-
415
- def default_domain
416
- if @started
417
- URI.parse(browser.current_url).host
418
- else
419
- URI.parse(default_cookie_host).host || "127.0.0.1"
420
- end
421
- end
422
-
423
- def native_args(args)
424
- args.map { |arg| arg.is_a?(Capybara::Cuprite::Node) ? arg.node : arg }
425
- end
426
-
427
- def session_wait_time
428
- if respond_to?(:session_options)
429
- session_options.default_max_wait_time
430
- else
431
- begin
432
- Capybara.default_max_wait_time
433
- rescue
434
- Capybara.default_wait_time
435
- end
436
- end
437
- end
438
-
439
- def default_cookie_host
440
- if respond_to?(:session_options)
441
- session_options.app_host
442
- else
443
- Capybara.app_host
444
- end || ""
445
- end
446
-
447
- def unwrap_script_result(arg)
448
- case arg
449
- when Array
450
- arg.map { |e| unwrap_script_result(e) }
451
- when Hash
452
- arg.each { |k, v| arg[k] = unwrap_script_result(v) }
453
- when Ferrum::Node
454
- Node.new(self, arg)
455
- else
456
- arg
457
- end
458
- end
459
-
460
- def pdf?(path, options)
461
- (path && File.extname(path).delete(".") == "pdf") ||
462
- options[:format].to_s == "pdf"
463
- end
464
- end
465
- end