apparition 0.0.4 → 0.0.5
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/README.md +2 -2
- data/lib/capybara/apparition/browser.rb +30 -8
- data/lib/capybara/apparition/console.rb +7 -5
- data/lib/capybara/apparition/cookie.rb +4 -3
- data/lib/capybara/apparition/cookie_jar.rb +41 -0
- data/lib/capybara/apparition/dev_tools_protocol/session.rb +17 -2
- data/lib/capybara/apparition/driver.rb +28 -14
- data/lib/capybara/apparition/{chrome_client.rb → driver/chrome_client.rb} +2 -2
- data/lib/capybara/apparition/{launcher.rb → driver/launcher.rb} +0 -0
- data/lib/capybara/apparition/{response.rb → driver/response.rb} +0 -0
- data/lib/capybara/apparition/{web_socket_client.rb → driver/web_socket_client.rb} +0 -0
- data/lib/capybara/apparition/errors.rb +0 -1
- data/lib/capybara/apparition/node.rb +43 -53
- data/lib/capybara/apparition/page.rb +142 -52
- data/lib/capybara/apparition/{frame.rb → page/frame.rb} +0 -0
- data/lib/capybara/apparition/{frame_manager.rb → page/frame_manager.rb} +1 -1
- data/lib/capybara/apparition/{keyboard.rb → page/keyboard.rb} +0 -0
- data/lib/capybara/apparition/{mouse.rb → page/mouse.rb} +11 -9
- data/lib/capybara/apparition/version.rb +1 -1
- metadata +25 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2df57d16d5cfa6f966f3b8de2146a63ca23877e4dddc2f81a12170ae37f5ec5d
|
4
|
+
data.tar.gz: b7b06eacc056f6b627b31ad091a7db9af5508b3f14ae69e7d9f1bedce6e8e63a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd65552a378369a1d27852736c1cf2e1c51fb852a2c3e7c90b7c536f58608846bec86b471f009ef6eb9f9cbb803773d99c8af9b01575a0e5b2de953f1e0093f2
|
7
|
+
data.tar.gz: 77f8e17427d5621179b1707182e6df8bf3fc2bc52cb9f5f25e42ed31c6db945bd28b00c8f20ea09c2cf55e76476cf0fe467fd0b5aa8eece8f13a08611d9408e5
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
Apparition is a driver for [Capybara](https://github.com/jnicklas/capybara). It allows you to
|
6
6
|
run your Capybara tests in the Chrome browser via CDP (no selenium or chromedriver needed) in a headless or
|
7
7
|
headed configuration. It started as a fork of Poltergeist and attempts to maintain as much compatibility
|
8
|
-
with the Poltergeist API as possible
|
8
|
+
with the Poltergeist API as possible. Implementing the `capybara-webkit` specific driver methods has also begun.
|
9
9
|
|
10
10
|
## Getting help ##
|
11
11
|
|
@@ -217,7 +217,7 @@ Include as much information as possible. For example:
|
|
217
217
|
|
218
218
|
* Specific steps to reproduce where possible (failing tests are even
|
219
219
|
better)
|
220
|
-
* The output obtained from running Apparition with `:debug` turned on
|
220
|
+
* The output obtained from running Apparition with `:debug` turned on or ENV['DEBUG'] set
|
221
221
|
* Screenshots
|
222
222
|
* Stack traces if there are any Ruby on JavaScript exceptions generated
|
223
223
|
* The Apparition, Capybara, and Chrome version numbers used
|
@@ -9,7 +9,7 @@ require 'time'
|
|
9
9
|
|
10
10
|
module Capybara::Apparition
|
11
11
|
class Browser
|
12
|
-
attr_reader :client, :paper_size, :zoom_factor, :console
|
12
|
+
attr_reader :client, :paper_size, :zoom_factor, :console, :proxy_auth
|
13
13
|
extend Forwardable
|
14
14
|
|
15
15
|
delegate %i[visit current_url status_code
|
@@ -27,7 +27,9 @@ module Capybara::Apparition
|
|
27
27
|
@context_id = nil
|
28
28
|
@js_errors = true
|
29
29
|
@ignore_https_errors = false
|
30
|
+
@logger = logger
|
30
31
|
@console = Console.new(logger)
|
32
|
+
@proxy_auth = nil
|
31
33
|
|
32
34
|
initialize_handlers
|
33
35
|
|
@@ -102,7 +104,7 @@ module Capybara::Apparition
|
|
102
104
|
def close_window(handle)
|
103
105
|
@current_page_handle = nil if @current_page_handle == handle
|
104
106
|
win_target = @targets.delete(handle)
|
105
|
-
warn
|
107
|
+
warn 'Window was already closed unexpectedly' if win_target.nil?
|
106
108
|
win_target&.close
|
107
109
|
end
|
108
110
|
|
@@ -205,9 +207,21 @@ module Capybara::Apparition
|
|
205
207
|
end
|
206
208
|
|
207
209
|
def cookies
|
208
|
-
|
209
|
-
|
210
|
-
|
210
|
+
CookieJar.new(
|
211
|
+
# current_page.command('Network.getCookies')['cookies'].map { |c| Cookie.new(c) }
|
212
|
+
self
|
213
|
+
)
|
214
|
+
end
|
215
|
+
|
216
|
+
def all_cookies
|
217
|
+
CookieJar.new(
|
218
|
+
# current_page.command('Network.getAllCookies')['cookies'].map { |c| Cookie.new(c) }
|
219
|
+
self
|
220
|
+
)
|
221
|
+
end
|
222
|
+
|
223
|
+
def get_raw_cookies
|
224
|
+
current_page.command('Network.getAllCookies')['cookies'].map { |c| Cookie.new(c) }
|
211
225
|
end
|
212
226
|
|
213
227
|
def set_cookie(cookie)
|
@@ -231,6 +245,14 @@ module Capybara::Apparition
|
|
231
245
|
current_page.command('Emulation.setDocumentCookieDisabled', disabled: !flag)
|
232
246
|
end
|
233
247
|
|
248
|
+
def set_proxy_auth(user, password)
|
249
|
+
@proxy_auth = if user.nil? && password.nil?
|
250
|
+
nil
|
251
|
+
else
|
252
|
+
{ username: user, password: password }
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
234
256
|
def set_http_auth(user = nil, password = nil)
|
235
257
|
current_page.credentials = if user.nil? && password.nil?
|
236
258
|
nil
|
@@ -311,8 +333,8 @@ module Capybara::Apparition
|
|
311
333
|
current_target.page
|
312
334
|
end
|
313
335
|
|
314
|
-
def console_messages
|
315
|
-
console.messages
|
336
|
+
def console_messages(type = nil)
|
337
|
+
console.messages(type)
|
316
338
|
end
|
317
339
|
|
318
340
|
private
|
@@ -326,7 +348,7 @@ module Capybara::Apparition
|
|
326
348
|
end
|
327
349
|
|
328
350
|
def log(message)
|
329
|
-
logger&.puts message if ENV['DEBUG']
|
351
|
+
@logger&.puts message if ENV['DEBUG']
|
330
352
|
end
|
331
353
|
|
332
354
|
def check_render_options!(options, path = nil)
|
@@ -7,17 +7,19 @@ module Capybara::Apparition
|
|
7
7
|
@messages = []
|
8
8
|
end
|
9
9
|
|
10
|
-
def log(type, message)
|
11
|
-
@messages << OpenStruct.new(type: type, message: message)
|
12
|
-
@logger&.puts message
|
10
|
+
def log(type, message, **options)
|
11
|
+
@messages << OpenStruct.new(type: type, message: message, **options)
|
12
|
+
@logger&.puts "#{type}: #{message}"
|
13
13
|
end
|
14
14
|
|
15
15
|
def clear
|
16
16
|
@messages.clear
|
17
17
|
end
|
18
18
|
|
19
|
-
def messages
|
20
|
-
@messages
|
19
|
+
def messages(type = nil)
|
20
|
+
return @messages if type.nil?
|
21
|
+
|
22
|
+
@messages.select { |msg| msg.type == type }
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
@@ -48,9 +48,10 @@ module Capybara::Apparition
|
|
48
48
|
Time.at @attributes['expires'] unless [nil, 0, -1].include? @attributes['expires']
|
49
49
|
end
|
50
50
|
|
51
|
-
def ==(
|
52
|
-
return super unless
|
53
|
-
|
51
|
+
def ==(other)
|
52
|
+
return super unless other.is_a? String
|
53
|
+
|
54
|
+
value == other
|
54
55
|
end
|
55
56
|
end
|
56
57
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'capybara/apparition/cookie'
|
4
|
+
|
5
|
+
module Capybara::Apparition
|
6
|
+
class CookieJar
|
7
|
+
def initialize(browser)
|
8
|
+
@browser = browser
|
9
|
+
end
|
10
|
+
|
11
|
+
# def find(name, domain = nil, path = '/')
|
12
|
+
def find(name, domain = URI.parse(@browser.current_url).host, path = URI.parse(@browser.current_url).path)
|
13
|
+
# sort by path length because more specific take precendence
|
14
|
+
cookies.sort_by { |c| -c.path.length }.find do |cookie|
|
15
|
+
cookie.name.casecmp(name).zero? &&
|
16
|
+
(domain.nil? || match_domain?(cookie, domain)) &&
|
17
|
+
(path.nil? || match_path?(cookie, path))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
alias_method :[], :find
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def match_domain?(cookie, domain)
|
25
|
+
domain = '.' + domain
|
26
|
+
cookie_domain = cookie.domain
|
27
|
+
cookie_domain = '.' + cookie_domain unless cookie_domain.start_with?('.')
|
28
|
+
# cookie_domain.downcase.end_with? domain.downcase
|
29
|
+
domain.downcase.end_with? cookie_domain.downcase
|
30
|
+
end
|
31
|
+
|
32
|
+
def match_path?(cookie, path)
|
33
|
+
# cookie.path.start_with? path
|
34
|
+
path.start_with? cookie.path
|
35
|
+
end
|
36
|
+
|
37
|
+
def cookies
|
38
|
+
@browser.get_raw_cookies
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -14,16 +14,31 @@ module Capybara::Apparition
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def command(name, **params)
|
17
|
-
|
17
|
+
send_cmd(name, params).result
|
18
|
+
end
|
19
|
+
|
20
|
+
def commands(*names)
|
21
|
+
responses = names.map { |name| send_cmd(name) }
|
22
|
+
responses.map(&:result)
|
18
23
|
end
|
19
24
|
|
20
25
|
def async_command(name, **params)
|
21
|
-
|
26
|
+
send_cmd(name, params).discard_result
|
27
|
+
end
|
28
|
+
|
29
|
+
def async_commands(*names)
|
30
|
+
names.map { |name| async_command(name) }
|
22
31
|
end
|
23
32
|
|
24
33
|
def on(event_name, &block)
|
25
34
|
connection.on(event_name, @session_id, &block)
|
26
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def send_cmd(name, **params)
|
40
|
+
@browser.command_for_session(@session_id, name, params)
|
41
|
+
end
|
27
42
|
end
|
28
43
|
end
|
29
44
|
end
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'uri'
|
4
4
|
require 'forwardable'
|
5
|
-
require 'capybara/apparition/chrome_client'
|
6
|
-
require 'capybara/apparition/launcher'
|
5
|
+
require 'capybara/apparition/driver/chrome_client'
|
6
|
+
require 'capybara/apparition/driver/launcher'
|
7
7
|
|
8
8
|
module Capybara::Apparition
|
9
9
|
class Driver < Capybara::Driver::Base
|
@@ -20,7 +20,7 @@ module Capybara::Apparition
|
|
20
20
|
scroll_to
|
21
21
|
network_traffic clear_network_traffic
|
22
22
|
headers headers= add_headers
|
23
|
-
cookies remove_cookie clear_cookies cookies_enabled=
|
23
|
+
cookies all_cookies remove_cookie clear_cookies cookies_enabled=
|
24
24
|
clear_memory_cache
|
25
25
|
go_back go_forward refresh
|
26
26
|
console_messages] => :browser
|
@@ -196,13 +196,20 @@ module Capybara::Apparition
|
|
196
196
|
end
|
197
197
|
end
|
198
198
|
|
199
|
-
def set_proxy(host, port, type = nil,
|
200
|
-
|
201
|
-
|
199
|
+
def set_proxy(host, port, type = nil, user_ = nil, password_ = nil, user: nil, password: nil, bypass: [])
|
200
|
+
if user_ || password_
|
201
|
+
warn '#set_proxy: Passing `user` and `password` as positional arguments is deprecated. ' \
|
202
|
+
'Please pass as keyword arguments.'
|
203
|
+
user ||= user_
|
204
|
+
password ||= password_
|
205
|
+
end
|
206
|
+
|
207
|
+
# TODO: Look at implementing via the CDP Fetch domain when available
|
202
208
|
@options[:browser] ||= {}
|
203
|
-
@options[:browser]
|
209
|
+
@options[:browser]['proxy-server'] = "#{type + '=' if type}#{host}:#{port}"
|
204
210
|
bypass = Array(bypass).join(';')
|
205
|
-
@options[:browser]
|
211
|
+
@options[:browser]['proxy-bypass-list'] = bypass unless bypass.empty?
|
212
|
+
browser.set_proxy_auth(user, password) if user || password
|
206
213
|
end
|
207
214
|
|
208
215
|
def add_header(name, value, options = {})
|
@@ -216,7 +223,7 @@ module Capybara::Apparition
|
|
216
223
|
end
|
217
224
|
end
|
218
225
|
|
219
|
-
def set_cookie(name, value=nil, options = {})
|
226
|
+
def set_cookie(name, value = nil, options = {})
|
220
227
|
name, value, options = parse_raw_cookie(name) if value.nil?
|
221
228
|
|
222
229
|
options[:name] ||= name
|
@@ -232,10 +239,12 @@ module Capybara::Apparition
|
|
232
239
|
browser.set_cookie(options)
|
233
240
|
end
|
234
241
|
|
242
|
+
def proxy_authorize(user = nil, password = nil)
|
243
|
+
browser.set_proxy_aauth(user, password)
|
244
|
+
end
|
245
|
+
|
235
246
|
def basic_authorize(user = nil, password = nil)
|
236
247
|
browser.set_http_auth(user, password)
|
237
|
-
# credentials = ["#{user}:#{password}"].pack('m*').strip
|
238
|
-
# add_header('Authorization', "Basic #{credentials}")
|
239
248
|
end
|
240
249
|
alias_method :authenticate, :basic_authorize
|
241
250
|
|
@@ -336,7 +345,7 @@ module Capybara::Apparition
|
|
336
345
|
end
|
337
346
|
|
338
347
|
def within_frame(frame_selector)
|
339
|
-
warn
|
348
|
+
warn 'Driver#within_frame is deprecated, please use Session#within_frame'
|
340
349
|
|
341
350
|
frame = case frame_selector
|
342
351
|
when Capybara::Apparition::Node
|
@@ -347,7 +356,7 @@ module Capybara::Apparition
|
|
347
356
|
find_css("iframe[name='#{frame_selector}']")[0]
|
348
357
|
else
|
349
358
|
raise TypeError, 'Unknown frame selector'
|
350
|
-
command(
|
359
|
+
# command('FrameFocus')
|
351
360
|
end
|
352
361
|
|
353
362
|
switch_to_frame(frame)
|
@@ -358,6 +367,10 @@ module Capybara::Apparition
|
|
358
367
|
end
|
359
368
|
end
|
360
369
|
|
370
|
+
def error_messages
|
371
|
+
console_messages('error')
|
372
|
+
end
|
373
|
+
|
361
374
|
private
|
362
375
|
|
363
376
|
def parse_raw_cookie(raw)
|
@@ -385,7 +398,8 @@ module Capybara::Apparition
|
|
385
398
|
raise Capybara::ModalNotFound if modal_text.nil? || (expect_text && !modal_text.match(expect_regexp))
|
386
399
|
rescue Capybara::ModalNotFound => e
|
387
400
|
if timer.expired?
|
388
|
-
raise e, 'Timed out waiting for modal dialog. Unable to find modal dialog.'
|
401
|
+
raise e, 'Timed out waiting for modal dialog. Unable to find modal dialog.' unless found_text
|
402
|
+
|
389
403
|
raise e, 'Unable to find modal dialog' \
|
390
404
|
"#{" with #{expect_text}" if expect_text}" \
|
391
405
|
"#{", did find modal with #{found_text}" if found_text}"
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'capybara/apparition/errors'
|
4
|
-
require 'capybara/apparition/web_socket_client'
|
5
|
-
require 'capybara/apparition/response'
|
4
|
+
require 'capybara/apparition/driver/web_socket_client'
|
5
|
+
require 'capybara/apparition/driver/response'
|
6
6
|
|
7
7
|
module Capybara::Apparition
|
8
8
|
class ChromeClient
|
File without changes
|
File without changes
|
File without changes
|
@@ -46,7 +46,7 @@ module Capybara::Apparition
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def all_text
|
49
|
-
text = evaluate_on('
|
49
|
+
text = evaluate_on('() => this.textContent')
|
50
50
|
text.to_s.gsub(/[\u200b\u200e\u200f]/, '')
|
51
51
|
.gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
|
52
52
|
.gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
|
@@ -64,20 +64,21 @@ module Capybara::Apparition
|
|
64
64
|
.tr("\u00a0", ' ')
|
65
65
|
end
|
66
66
|
|
67
|
-
|
68
|
-
|
67
|
+
# capybara-webkit method
|
68
|
+
def text
|
69
|
+
warn 'Node#text is deprecated, please use Node#visible_text instead'
|
69
70
|
visible_text
|
70
71
|
end
|
71
72
|
|
72
73
|
def property(name)
|
73
|
-
evaluate_on('
|
74
|
+
evaluate_on('name => this[name]', value: name)
|
74
75
|
end
|
75
76
|
|
76
77
|
def attribute(name)
|
77
78
|
if %w[checked selected].include?(name.to_s)
|
78
79
|
property(name)
|
79
80
|
else
|
80
|
-
evaluate_on('
|
81
|
+
evaluate_on('name => this.getAttribute(name)', value: name)
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
@@ -95,6 +96,10 @@ module Capybara::Apparition
|
|
95
96
|
evaluate_on GET_VALUE_JS
|
96
97
|
end
|
97
98
|
|
99
|
+
def style(styles)
|
100
|
+
evaluate_on GET_STYLES_JS, value: styles
|
101
|
+
end
|
102
|
+
|
98
103
|
def set(value, **_options)
|
99
104
|
if tag_name == 'input'
|
100
105
|
case self[:type]
|
@@ -137,7 +142,7 @@ module Capybara::Apparition
|
|
137
142
|
end
|
138
143
|
|
139
144
|
def tag_name
|
140
|
-
@tag_name ||= evaluate_on('
|
145
|
+
@tag_name ||= evaluate_on('() => this.tagName').downcase
|
141
146
|
end
|
142
147
|
|
143
148
|
def visible?
|
@@ -169,7 +174,7 @@ module Capybara::Apparition
|
|
169
174
|
begin
|
170
175
|
new_pos = element_click_pos(options)
|
171
176
|
puts "Element moved from #{pos} to #{new_pos}" unless pos == new_pos
|
172
|
-
rescue WrongWorld
|
177
|
+
rescue WrongWorld # rubocop:disable Lint/HandleExceptions
|
173
178
|
end
|
174
179
|
end
|
175
180
|
# Wait a short time to see if click triggers page load
|
@@ -204,19 +209,25 @@ module Capybara::Apparition
|
|
204
209
|
mouseenter: ['MouseEvent'],
|
205
210
|
mouseleave: ['MouseEvent'],
|
206
211
|
mousemove: ['MouseEvent', { bubbles: true, cancelable: true }],
|
207
|
-
|
212
|
+
mouseover: ['MouseEvent', { bubbles: true, cancelable: true }],
|
213
|
+
mouseout: ['MouseEvent', { bubbles: true, cancelable: true }],
|
214
|
+
context_menu: ['MouseEvent', { bubble: true, cancelable: true }],
|
215
|
+
submit: ['Event', { bubbles: true, cancelable: true }],
|
216
|
+
change: ['Event', { bubbles: true, cacnelable: false }],
|
217
|
+
input: ['InputEvent', { bubbles: true, cacnelable: false }],
|
218
|
+
wheel: ['WheelEvent', { bubbles: true, cancelable: true }]
|
208
219
|
}.freeze
|
209
220
|
|
210
|
-
def trigger(name, **options)
|
211
|
-
raise ArgumentError, 'Unknown event' unless EVENTS.key?(name.to_sym)
|
221
|
+
def trigger(name, event_type = nil, **options)
|
222
|
+
raise ArgumentError, 'Unknown event' unless EVENTS.key?(name.to_sym) || event_type
|
212
223
|
|
213
|
-
event_type, opts = *EVENTS[name.to_sym], {}
|
224
|
+
event_type, opts = *EVENTS[name.to_sym], {} if event_type.nil?
|
214
225
|
|
215
226
|
evaluate_on DISPATCH_EVENT_JS, { value: event_type }, { value: name }, value: opts.merge(options)
|
216
227
|
end
|
217
228
|
|
218
229
|
def ==(other)
|
219
|
-
evaluate_on('
|
230
|
+
evaluate_on('el => this == el', objectId: other.id)
|
220
231
|
rescue ObsoleteNode
|
221
232
|
false
|
222
233
|
end
|
@@ -328,8 +339,9 @@ module Capybara::Apparition
|
|
328
339
|
|
329
340
|
def scroll_by(x, y)
|
330
341
|
evaluate_on <<~JS, { value: x }, value: y
|
331
|
-
|
342
|
+
(x, y) => this.scrollBy(x,y)
|
332
343
|
JS
|
344
|
+
self
|
333
345
|
end
|
334
346
|
|
335
347
|
def scroll_to(element, location, position = nil)
|
@@ -350,7 +362,7 @@ module Capybara::Apparition
|
|
350
362
|
obsolete_checked_function = <<~JS
|
351
363
|
function(){
|
352
364
|
if (!this.ownerDocument.contains(this)) { throw 'ObsoleteNode' };
|
353
|
-
|
365
|
+
return (#{page_function.strip}).apply(this, arguments);
|
354
366
|
}
|
355
367
|
JS
|
356
368
|
response = @page.command('Runtime.callFunctionOn',
|
@@ -371,7 +383,7 @@ module Capybara::Apparition
|
|
371
383
|
private
|
372
384
|
|
373
385
|
def in_view_bounding_rect
|
374
|
-
evaluate_on('
|
386
|
+
evaluate_on('() => this.scrollIntoViewIfNeeded()')
|
375
387
|
result = evaluate_on GET_BOUNDING_CLIENT_RECT_JS
|
376
388
|
result = result['model'] if result && result['model']
|
377
389
|
result
|
@@ -422,7 +434,7 @@ module Capybara::Apparition
|
|
422
434
|
value = value.to_s
|
423
435
|
if value.empty? && clear.nil?
|
424
436
|
evaluate_on <<~JS
|
425
|
-
|
437
|
+
() => {
|
426
438
|
this.focus();
|
427
439
|
this.value = '';
|
428
440
|
this.dispatchEvent(new Event('change', { bubbles: true }));
|
@@ -479,7 +491,7 @@ module Capybara::Apparition
|
|
479
491
|
|
480
492
|
def update_value_js(value)
|
481
493
|
evaluate_on(<<~JS, value: value)
|
482
|
-
|
494
|
+
value => {
|
483
495
|
if (document.activeElement !== this){
|
484
496
|
this.focus();
|
485
497
|
}
|
@@ -503,7 +515,7 @@ module Capybara::Apparition
|
|
503
515
|
hit_node = Capybara::Apparition::Node.new(driver, @page, r_o['objectId'])
|
504
516
|
result = begin
|
505
517
|
evaluate_on(<<~JS, objectId: hit_node.id)
|
506
|
-
|
518
|
+
(hit_node) => {
|
507
519
|
if ((hit_node == this) || this.contains(hit_node))
|
508
520
|
return { status: 'success' };
|
509
521
|
return { status: 'failure' };
|
@@ -513,38 +525,6 @@ module Capybara::Apparition
|
|
513
525
|
{ 'status': 'failure' }
|
514
526
|
end
|
515
527
|
OpenStruct.new(success: result['status'] == 'success', selector: r_o['description'])
|
516
|
-
|
517
|
-
# frame_offset = @page.current_frame_offset
|
518
|
-
# # return { status: 'failure' } if x < 0 || y < 0
|
519
|
-
# result = evaluate_on(<<~JS, { value: x - frame_offset[:x] }, value: y - frame_offset[:y])
|
520
|
-
# function(x,y){
|
521
|
-
# const hit_node = document.elementFromPoint(x,y);
|
522
|
-
# if ((hit_node == this) || this.contains(hit_node))
|
523
|
-
# return { status: 'success' };
|
524
|
-
#
|
525
|
-
# const getSelector = function(element){
|
526
|
-
# if (element == null)
|
527
|
-
# return 'Element out of bounds';
|
528
|
-
#
|
529
|
-
# let selector = '';
|
530
|
-
# if (element.tagName != 'HTML')
|
531
|
-
# selector = getSelector(element.parentNode) + ' ';
|
532
|
-
# selector += element.tagName.toLowerCase();
|
533
|
-
# if (element.id)
|
534
|
-
# selector += `#${element.id}`;
|
535
|
-
#
|
536
|
-
# for (let className of element.classList){
|
537
|
-
# if (className != '')
|
538
|
-
# selector += `.${className}`;
|
539
|
-
# }
|
540
|
-
# return selector;
|
541
|
-
# }
|
542
|
-
#
|
543
|
-
# return { status: 'failure', selector: getSelector(hit_node) };
|
544
|
-
# }
|
545
|
-
# JS
|
546
|
-
#
|
547
|
-
# OpenStruct.new(success: result['status'] == 'success', selector: result['selector'])
|
548
528
|
end
|
549
529
|
|
550
530
|
def scroll_element_to_location(element, location)
|
@@ -558,7 +538,7 @@ module Capybara::Apparition
|
|
558
538
|
else
|
559
539
|
raise ArgumentError, "Invalid scroll_to location: #{location}"
|
560
540
|
end
|
561
|
-
element.evaluate_on "
|
541
|
+
element.evaluate_on "() => this.scrollIntoView(#{scroll_opts})"
|
562
542
|
end
|
563
543
|
|
564
544
|
def scroll_to_location(location)
|
@@ -570,12 +550,12 @@ module Capybara::Apparition
|
|
570
550
|
when :center
|
571
551
|
'(this.scrollHeight - this.clientHeight)/2'
|
572
552
|
end
|
573
|
-
evaluate_on "
|
553
|
+
evaluate_on "() => this.scrollTo(0, #{scroll_y})"
|
574
554
|
end
|
575
555
|
|
576
556
|
def scroll_to_coords(x, y)
|
577
557
|
evaluate_on <<~JS, { value: x }, value: y
|
578
|
-
|
558
|
+
(x,y) => this.scrollTo(x,y)
|
579
559
|
JS
|
580
560
|
end
|
581
561
|
|
@@ -831,5 +811,15 @@ module Capybara::Apparition
|
|
831
811
|
this.dispatchEvent(event);
|
832
812
|
}
|
833
813
|
JS
|
814
|
+
|
815
|
+
GET_STYLES_JS = <<~JS
|
816
|
+
function(styles){
|
817
|
+
style = window.getComputedStyle(this);
|
818
|
+
return styles.reduce((res,name) => {
|
819
|
+
res[name] = style[name];
|
820
|
+
return res;
|
821
|
+
}, {})
|
822
|
+
}
|
823
|
+
JS
|
834
824
|
end
|
835
825
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'capybara/apparition/frame_manager'
|
4
|
-
require 'capybara/apparition/mouse'
|
5
|
-
require 'capybara/apparition/keyboard'
|
3
|
+
require 'capybara/apparition/page/frame_manager'
|
4
|
+
require 'capybara/apparition/page/mouse'
|
5
|
+
require 'capybara/apparition/page/keyboard'
|
6
6
|
|
7
7
|
module Capybara::Apparition
|
8
8
|
class Page
|
@@ -20,12 +20,13 @@ module Capybara::Apparition
|
|
20
20
|
|
21
21
|
page = Page.new(browser, session, id, ignore_https_errors, screenshot_task_queue, js_errors)
|
22
22
|
|
23
|
-
session.
|
24
|
-
session.command '
|
25
|
-
session.command '
|
23
|
+
session.async_commands 'Network.enable', 'Runtime.enable', 'Security.enable', 'DOM.enable'
|
24
|
+
# session.command 'Network.enable'
|
25
|
+
# session.command 'Runtime.enable'
|
26
|
+
# session.command 'Security.enable'
|
26
27
|
# session.command 'Security.setOverrideCertificateErrors', override: true if ignore_https_errors
|
27
28
|
session.command 'Security.setIgnoreCertificateErrors', ignore: !!ignore_https_errors
|
28
|
-
session.command 'DOM.enable'
|
29
|
+
# session.command 'DOM.enable'
|
29
30
|
# session.command 'Log.enable'
|
30
31
|
if Capybara.save_path
|
31
32
|
session.command 'Page.setDownloadBehavior', behavior: 'allow', downloadPath: Capybara.save_path
|
@@ -46,18 +47,26 @@ module Capybara::Apparition
|
|
46
47
|
@status_code = 0
|
47
48
|
@url_blacklist = []
|
48
49
|
@url_whitelist = []
|
50
|
+
@credentials = nil
|
49
51
|
@auth_attempts = []
|
52
|
+
@proxy_credentials = nil
|
53
|
+
@proxy_auth_attempts = []
|
50
54
|
@perm_headers = {}
|
51
55
|
@temp_headers = {}
|
52
56
|
@temp_no_redirect_headers = {}
|
53
57
|
@viewport_size = nil
|
54
58
|
@network_traffic = []
|
55
59
|
@open_resource_requests = {}
|
60
|
+
@raise_js_errors = js_errors
|
56
61
|
@js_error = nil
|
62
|
+
@modal_mutex = Mutex.new
|
63
|
+
@modal_closed = ConditionVariable.new
|
57
64
|
|
58
65
|
register_event_handlers
|
59
66
|
|
60
|
-
register_js_error_handler if js_errors
|
67
|
+
register_js_error_handler # if js_errors
|
68
|
+
|
69
|
+
setup_network_interception if browser.proxy_auth
|
61
70
|
end
|
62
71
|
|
63
72
|
def usable?
|
@@ -70,6 +79,7 @@ module Capybara::Apparition
|
|
70
79
|
@response_headers = {}
|
71
80
|
@status_code = 0
|
72
81
|
@auth_attempts = []
|
82
|
+
@proxy_auth_attempts = []
|
73
83
|
@perm_headers = {}
|
74
84
|
end
|
75
85
|
|
@@ -78,6 +88,11 @@ module Capybara::Apparition
|
|
78
88
|
@modals.push(modal_response)
|
79
89
|
end
|
80
90
|
|
91
|
+
def proxy_credentials=(creds)
|
92
|
+
@proxy_credentials = creds
|
93
|
+
setup_network_interception
|
94
|
+
end
|
95
|
+
|
81
96
|
def credentials=(creds)
|
82
97
|
@credentials = creds
|
83
98
|
setup_network_interception
|
@@ -151,7 +166,6 @@ module Capybara::Apparition
|
|
151
166
|
# Wait for the frame creation messages to be processed
|
152
167
|
if timer.expired?
|
153
168
|
puts 'Timed out waiting from frame to be ready'
|
154
|
-
# byebug
|
155
169
|
raise TimeoutError.new('push_frame')
|
156
170
|
end
|
157
171
|
sleep 0.1
|
@@ -181,25 +195,41 @@ module Capybara::Apparition
|
|
181
195
|
|
182
196
|
def execute(script, *args)
|
183
197
|
wait_for_loaded
|
184
|
-
_execute_script
|
198
|
+
_execute_script <<~JS, *args
|
199
|
+
function(){
|
200
|
+
#{script}
|
201
|
+
}
|
202
|
+
JS
|
185
203
|
nil
|
186
204
|
end
|
187
205
|
|
188
206
|
def evaluate(script, *args)
|
189
207
|
wait_for_loaded
|
190
|
-
_execute_script
|
208
|
+
_execute_script <<~JS, *args
|
209
|
+
function(){
|
210
|
+
let apparitionId=0;
|
211
|
+
return (function ider(obj){
|
212
|
+
if (obj && (typeof obj == 'object') && !obj.apparitionId){
|
213
|
+
obj.apparitionId = ++apparitionId;
|
214
|
+
Reflect.ownKeys(obj).forEach(key => ider(obj[key]))
|
215
|
+
}
|
216
|
+
return obj;
|
217
|
+
})((function(){ return #{script} }).apply(this, arguments))
|
218
|
+
}
|
219
|
+
JS
|
191
220
|
end
|
192
221
|
|
193
222
|
def evaluate_async(script, _wait_time, *args)
|
194
223
|
wait_for_loaded
|
195
|
-
_execute_script
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
224
|
+
_execute_script <<~JS, *args
|
225
|
+
function(){
|
226
|
+
var args = Array.prototype.slice.call(arguments);
|
227
|
+
return new Promise((resolve, reject)=>{
|
228
|
+
args.push(resolve);
|
229
|
+
(function(){ #{script} }).apply(this, args);
|
230
|
+
});
|
231
|
+
}
|
232
|
+
JS
|
203
233
|
end
|
204
234
|
|
205
235
|
def refresh
|
@@ -288,9 +318,15 @@ module Capybara::Apparition
|
|
288
318
|
wait_for_loaded
|
289
319
|
@viewport_size = { width: width, height: height }
|
290
320
|
result = @browser.command('Browser.getWindowForTarget', targetId: @target_id)
|
291
|
-
|
292
|
-
|
293
|
-
|
321
|
+
begin
|
322
|
+
@browser.command('Browser.setWindowBounds',
|
323
|
+
windowId: result['windowId'],
|
324
|
+
bounds: { width: width, height: height })
|
325
|
+
rescue WrongWorld # TODO: Fix Error naming here
|
326
|
+
@browser.command('Browser.setWindowBounds', windowId: result['windowId'], bounds: { windowState: 'normal' })
|
327
|
+
retry
|
328
|
+
end
|
329
|
+
|
294
330
|
metrics = {
|
295
331
|
mobile: false,
|
296
332
|
width: width,
|
@@ -339,7 +375,7 @@ module Capybara::Apparition
|
|
339
375
|
|
340
376
|
def update_headers(async: false)
|
341
377
|
method = async ? :async_command : :command
|
342
|
-
if (ua = extra_headers.find { |k, _v| k
|
378
|
+
if (ua = extra_headers.find { |k, _v| k =~ /^User-Agent$/i })
|
343
379
|
send(method, 'Network.setUserAgentOverride', userAgent: ua[1])
|
344
380
|
end
|
345
381
|
send(method, 'Network.setExtraHTTPHeaders', headers: extra_headers)
|
@@ -378,23 +414,14 @@ module Capybara::Apparition
|
|
378
414
|
def register_event_handlers
|
379
415
|
@session.on 'Page.javascriptDialogOpening' do |params|
|
380
416
|
type = params['type'].to_sym
|
381
|
-
accept =
|
382
|
-
|
383
|
-
else
|
384
|
-
response = @modals.pop
|
385
|
-
if !response&.key?(type)
|
386
|
-
handle_unexpected_modal(type)
|
387
|
-
else
|
388
|
-
@modal_messages.push(params['message'])
|
389
|
-
response[type]
|
390
|
-
end
|
391
|
-
end
|
417
|
+
accept = accept_modal?(type, message: params['message'], manual: params['hasBrowserHandler'])
|
418
|
+
next if accept.nil?
|
392
419
|
|
393
420
|
if type == :prompt
|
394
421
|
case accept
|
395
422
|
when false
|
396
423
|
async_command('Page.handleJavaScriptDialog', accept: false)
|
397
|
-
when
|
424
|
+
when true
|
398
425
|
async_command('Page.handleJavaScriptDialog', accept: true, promptText: params['defaultPrompt'])
|
399
426
|
else
|
400
427
|
async_command('Page.handleJavaScriptDialog', accept: true, promptText: accept)
|
@@ -404,6 +431,12 @@ module Capybara::Apparition
|
|
404
431
|
end
|
405
432
|
end
|
406
433
|
|
434
|
+
@session.on 'Page.javascriptDialogClosed' do
|
435
|
+
@modal_mutex.synchronize do
|
436
|
+
@modal_closed.signal
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
407
440
|
@session.on 'Page.windowOpen' do |params|
|
408
441
|
puts "**** windowOpen was called with: #{params}" if ENV['DEBUG']
|
409
442
|
# TODO: find a better way to handle this
|
@@ -474,7 +507,6 @@ module Capybara::Apparition
|
|
474
507
|
puts "unknown frame for context #{frame_id}"
|
475
508
|
end
|
476
509
|
end
|
477
|
-
# command 'Network.setRequestInterception', patterns: [{urlPattern: '*'}]
|
478
510
|
end
|
479
511
|
|
480
512
|
@session.on 'Runtime.executionContextDestroyed' do |params|
|
@@ -519,15 +551,24 @@ module Capybara::Apparition
|
|
519
551
|
@session.on 'Network.requestIntercepted' do |params|
|
520
552
|
request, interception_id = *params.values_at('request', 'interceptionId')
|
521
553
|
if params['authChallenge']
|
522
|
-
|
554
|
+
if params['authChallenge']['source'] == 'Proxy'
|
555
|
+
handle_proxy_auth(interception_id)
|
556
|
+
else
|
557
|
+
handle_user_auth(interception_id)
|
558
|
+
end
|
523
559
|
else
|
524
560
|
process_intercepted_request(interception_id, request, params['isNavigationRequest'])
|
525
561
|
end
|
526
562
|
end
|
527
563
|
|
528
564
|
@session.on 'Runtime.consoleAPICalled' do |params|
|
565
|
+
# {"type"=>"log", "args"=>[{"type"=>"string", "value"=>"hello"}], "executionContextId"=>2, "timestamp"=>1548722854903.285, "stackTrace"=>{"callFrames"=>[{"functionName"=>"", "scriptId"=>"15", "url"=>"http://127.0.0.1:53977/", "lineNumber"=>6, "columnNumber"=>22}]}}
|
566
|
+
details = params.dig('stackTrace', 'callFrames')&.first
|
529
567
|
@browser.console.log(params['type'],
|
530
|
-
|
568
|
+
params['args'].map { |arg| arg['description'] || arg['value'] }.join(' ').to_s,
|
569
|
+
source: details['url'].empty? ? nil : details['url'],
|
570
|
+
line_number: details['lineNumber'].zero? ? nil : details['lineNumber'],
|
571
|
+
columnNumber: details['columnNumber'].zero? ? nil : details['columnNumber'])
|
531
572
|
end
|
532
573
|
|
533
574
|
# @session.on 'Security.certificateError' do |params|
|
@@ -544,7 +585,14 @@ module Capybara::Apparition
|
|
544
585
|
|
545
586
|
def register_js_error_handler
|
546
587
|
@session.on 'Runtime.exceptionThrown' do |params|
|
547
|
-
@js_error ||= params.dig('exceptionDetails', 'exception', 'description')
|
588
|
+
@js_error ||= params.dig('exceptionDetails', 'exception', 'description') if @raise_js_errors
|
589
|
+
|
590
|
+
details = params.dig('exceptionDetails', 'stackTrace', 'callFrames')&.first
|
591
|
+
@browser.console.log('error',
|
592
|
+
params.dig('exceptionDetails', 'exception', 'description'),
|
593
|
+
source: details['url'].empty? ? nil : details['url'],
|
594
|
+
line_number: details['lineNumber'].zero? ? nil : details['lineNumber'],
|
595
|
+
columnNumber: details['columnNumber'].zero? ? nil : details['columnNumber'])
|
548
596
|
end
|
549
597
|
end
|
550
598
|
|
@@ -607,6 +655,20 @@ module Capybara::Apparition
|
|
607
655
|
wait_for_loaded
|
608
656
|
end
|
609
657
|
|
658
|
+
def accept_modal?(type, message:, manual:)
|
659
|
+
if type == :beforeunload
|
660
|
+
true
|
661
|
+
else
|
662
|
+
response = @modals.pop
|
663
|
+
if !response&.key?(type)
|
664
|
+
manual ? manual_unexpected_modal(type) : auto_unexpected_modal(type)
|
665
|
+
else
|
666
|
+
@modal_messages.push(message)
|
667
|
+
response[type].nil? ? true : response[type]
|
668
|
+
end
|
669
|
+
end
|
670
|
+
end
|
671
|
+
|
610
672
|
def _execute_script(script, *args)
|
611
673
|
args = args.map do |arg|
|
612
674
|
if arg.is_a? Capybara::Apparition::Node
|
@@ -658,26 +720,48 @@ module Capybara::Apparition
|
|
658
720
|
decode_result(result)
|
659
721
|
end
|
660
722
|
|
661
|
-
def
|
723
|
+
def manual_unexpected_modal(type)
|
724
|
+
warn "An unexpected #{type} modal has opened - please close"
|
725
|
+
@modal_mutex.synchronize do
|
726
|
+
@modal_closed.wait(@modal_mutex)
|
727
|
+
end
|
728
|
+
nil
|
729
|
+
end
|
730
|
+
|
731
|
+
def auto_unexpected_modal(type)
|
662
732
|
case type
|
663
733
|
when :prompt
|
664
734
|
warn 'Unexpected prompt modal - accepting with the default value.' \
|
665
|
-
'
|
666
|
-
nil
|
735
|
+
'You should be using `accept_prompt` or `dismiss_prompt`.'
|
667
736
|
when :confirm
|
668
737
|
warn 'Unexpected confirm modal - accepting.' \
|
669
|
-
'
|
670
|
-
true
|
738
|
+
'You should be using `accept_confirm` or `dismiss_confirm`.'
|
671
739
|
else
|
672
|
-
|
740
|
+
warn 'Unexpected alert modal - clearing.' \
|
741
|
+
'You should be using `accept_alert`.'
|
673
742
|
end
|
743
|
+
true
|
674
744
|
end
|
675
745
|
|
676
|
-
def
|
746
|
+
def handle_proxy_auth(interception_id)
|
747
|
+
credentials_response = if @proxy_auth_attempts.include?(interception_id)
|
748
|
+
puts 'Cancelling proxy auth' if ENV['DEBUG']
|
749
|
+
{ response: 'CancelAuth' }
|
750
|
+
else
|
751
|
+
puts 'Replying with proxy auth credentials' if ENV['DEBUG']
|
752
|
+
@proxy_auth_attempts.push(interception_id)
|
753
|
+
{ response: 'ProvideCredentials' }.merge(@browser.proxy_auth || {})
|
754
|
+
end
|
755
|
+
continue_request(interception_id, authChallengeResponse: credentials_response)
|
756
|
+
end
|
757
|
+
|
758
|
+
def handle_user_auth(interception_id)
|
677
759
|
credentials_response = if @auth_attempts.include?(interception_id)
|
760
|
+
puts 'Cancelling auth' if ENV['DEBUG']
|
678
761
|
{ response: 'CancelAuth' }
|
679
762
|
else
|
680
763
|
@auth_attempts.push(interception_id)
|
764
|
+
puts 'Replying with auth credentials' if ENV['DEBUG']
|
681
765
|
{ response: 'ProvideCredentials' }.merge(@credentials || {})
|
682
766
|
end
|
683
767
|
continue_request(interception_id, authChallengeResponse: credentials_response)
|
@@ -690,7 +774,7 @@ module Capybara::Apparition
|
|
690
774
|
objectId: result['objectId'],
|
691
775
|
ownProperties: true)
|
692
776
|
|
693
|
-
properties = remote_object['result']
|
777
|
+
properties = remote_object['result'].reject { |prop| prop['name'] == 'apparitionId' }
|
694
778
|
results = []
|
695
779
|
|
696
780
|
properties.each do |property|
|
@@ -714,16 +798,22 @@ module Capybara::Apparition
|
|
714
798
|
remote_object = command('Runtime.getProperties',
|
715
799
|
objectId: result['objectId'],
|
716
800
|
ownProperties: true)
|
717
|
-
|
718
|
-
|
719
|
-
|
801
|
+
|
802
|
+
# stable_id went away in Chrome 72 - we add our own id in evaluate
|
803
|
+
# stable_id = remote_object['internalProperties']
|
804
|
+
# &.find { |prop| prop['name'] == '[[StableObjectId]]' }
|
805
|
+
# &.dig('value', 'value')
|
806
|
+
|
720
807
|
# We could actually return cyclic objects here but Capybara would need to be updated to support
|
721
|
-
# return object_cache[stable_id] if object_cache.key?(stable_id)
|
808
|
+
# return object_cache[stable_id] if object_cache.key?(stable_id) # and update the cache to be a hash
|
722
809
|
|
810
|
+
stable_id = remote_object['result']
|
811
|
+
&.find { |prop| prop['name'] == 'apparitionId'}
|
812
|
+
&.dig('value', 'value')
|
723
813
|
return '(cyclic structure)' if object_cache.key?(stable_id)
|
724
814
|
|
725
815
|
object_cache[stable_id] = {}
|
726
|
-
properties = remote_object['result']
|
816
|
+
properties = remote_object['result'].reject { |prop| prop['name'] == "apparitionId"}
|
727
817
|
|
728
818
|
return properties.each_with_object(object_cache[stable_id]) do |property, memo|
|
729
819
|
if property['enumerable']
|
File without changes
|
File without changes
|
@@ -10,10 +10,12 @@ module Capybara::Apparition
|
|
10
10
|
|
11
11
|
def click_at(x:, y:, button: 'left', count: 1, modifiers: [])
|
12
12
|
move_to x: x, y: y
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
count.times do |num|
|
14
|
+
@keyboard.with_keys(modifiers) do
|
15
|
+
mouse_params = { x: x, y: y, button: button, count: num+1 }
|
16
|
+
down mouse_params
|
17
|
+
up mouse_params
|
18
|
+
end
|
17
19
|
end
|
18
20
|
self
|
19
21
|
end
|
@@ -24,21 +26,21 @@ module Capybara::Apparition
|
|
24
26
|
self
|
25
27
|
end
|
26
28
|
|
27
|
-
def down(**options)
|
28
|
-
options = @current_pos.merge(options)
|
29
|
+
def down(button: 'left', **options)
|
30
|
+
options = @current_pos.merge(button: button).merge(options)
|
29
31
|
mouse_event('mousePressed', options)
|
30
32
|
self
|
31
33
|
end
|
32
34
|
|
33
|
-
def up(**options)
|
34
|
-
options = @current_pos.merge(options)
|
35
|
+
def up(button: 'left', **options)
|
36
|
+
options = @current_pos.merge(button: button).merge(options)
|
35
37
|
mouse_event('mouseReleased', options)
|
36
38
|
self
|
37
39
|
end
|
38
40
|
|
39
41
|
private
|
40
42
|
|
41
|
-
def mouse_event(type, x:, y:, button: '
|
43
|
+
def mouse_event(type, x:, y:, button: 'none', count: 1)
|
42
44
|
@page.command('Input.dispatchMouseEvent',
|
43
45
|
type: type,
|
44
46
|
button: button,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apparition
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Walpole
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backports
|
@@ -184,6 +184,20 @@ dependencies:
|
|
184
184
|
- - "~>"
|
185
185
|
- !ruby/object:Gem::Version
|
186
186
|
version: '3.6'
|
187
|
+
- !ruby/object:Gem::Dependency
|
188
|
+
name: selenium-webdriver
|
189
|
+
requirement: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - ">="
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: '0'
|
194
|
+
type: :development
|
195
|
+
prerelease: false
|
196
|
+
version_requirements: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ">="
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
187
201
|
- !ruby/object:Gem::Dependency
|
188
202
|
name: sinatra
|
189
203
|
requirement: !ruby/object:Gem::Requirement
|
@@ -210,20 +224,19 @@ files:
|
|
210
224
|
- README.md
|
211
225
|
- lib/capybara/apparition.rb
|
212
226
|
- lib/capybara/apparition/browser.rb
|
213
|
-
- lib/capybara/apparition/chrome_client.rb
|
214
227
|
- lib/capybara/apparition/console.rb
|
215
228
|
- lib/capybara/apparition/cookie.rb
|
229
|
+
- lib/capybara/apparition/cookie_jar.rb
|
216
230
|
- lib/capybara/apparition/dev_tools_protocol/session.rb
|
217
231
|
- lib/capybara/apparition/dev_tools_protocol/target.rb
|
218
232
|
- lib/capybara/apparition/dev_tools_protocol/target_manager.rb
|
219
233
|
- lib/capybara/apparition/driver.rb
|
234
|
+
- lib/capybara/apparition/driver/chrome_client.rb
|
235
|
+
- lib/capybara/apparition/driver/launcher.rb
|
236
|
+
- lib/capybara/apparition/driver/response.rb
|
237
|
+
- lib/capybara/apparition/driver/web_socket_client.rb
|
220
238
|
- lib/capybara/apparition/errors.rb
|
221
|
-
- lib/capybara/apparition/frame.rb
|
222
|
-
- lib/capybara/apparition/frame_manager.rb
|
223
239
|
- lib/capybara/apparition/inspector.rb
|
224
|
-
- lib/capybara/apparition/keyboard.rb
|
225
|
-
- lib/capybara/apparition/launcher.rb
|
226
|
-
- lib/capybara/apparition/mouse.rb
|
227
240
|
- lib/capybara/apparition/network_traffic.rb
|
228
241
|
- lib/capybara/apparition/network_traffic/error.rb
|
229
242
|
- lib/capybara/apparition/network_traffic/request.rb
|
@@ -231,10 +244,12 @@ files:
|
|
231
244
|
- lib/capybara/apparition/node.rb
|
232
245
|
- lib/capybara/apparition/node/drag.rb
|
233
246
|
- lib/capybara/apparition/page.rb
|
234
|
-
- lib/capybara/apparition/
|
247
|
+
- lib/capybara/apparition/page/frame.rb
|
248
|
+
- lib/capybara/apparition/page/frame_manager.rb
|
249
|
+
- lib/capybara/apparition/page/keyboard.rb
|
250
|
+
- lib/capybara/apparition/page/mouse.rb
|
235
251
|
- lib/capybara/apparition/utility.rb
|
236
252
|
- lib/capybara/apparition/version.rb
|
237
|
-
- lib/capybara/apparition/web_socket_client.rb
|
238
253
|
homepage: https://github.com/twalpole/apparition
|
239
254
|
licenses:
|
240
255
|
- MIT
|