cuprite 0.13 → 0.14.1

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