apparition 0.0.2 → 0.0.3
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/lib/capybara/apparition/browser.rb +3 -1
- data/lib/capybara/apparition/driver.rb +1 -1
- data/lib/capybara/apparition/errors.rb +1 -0
- data/lib/capybara/apparition/inspector.rb +1 -1
- data/lib/capybara/apparition/node/drag.rb +1 -1
- data/lib/capybara/apparition/node.rb +60 -45
- data/lib/capybara/apparition/page.rb +29 -13
- data/lib/capybara/apparition/version.rb +1 -1
- data/lib/capybara/apparition.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4f76aefa6b5bebbab16d325e6f434846c2a426b74df9b8c0248465653124202
|
4
|
+
data.tar.gz: e9538e39a9c912471527fc456e801f0b3cc261bf042ddc82177d0e74e0769a33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f187d2d4b1185e2fe5460adf9435daec58d008789e69bca907df06bdc20f59b1b8808ac4f346ef1c7d00d4caa62a6fe7aaf033a9e3287299a007e8c9c7493fb
|
7
|
+
data.tar.gz: 443d5076e6b92f8c051a261663a8dc93a3ae2b0a75d87943579b762927b0f8d4e42a527b3c047c4ae937bf001198f7e14ebd8f4ea77de7ffd1ec04d4e096ad65
|
@@ -133,7 +133,9 @@ module Capybara::Apparition
|
|
133
133
|
|
134
134
|
def close_window(handle)
|
135
135
|
@current_page_handle = nil if @current_page_handle == handle
|
136
|
-
@targets.delete(handle)
|
136
|
+
win_target = @targets.delete(handle)
|
137
|
+
warn "Window was already closed unexpectedly" if win_target.nil?
|
138
|
+
win_target&.close
|
137
139
|
end
|
138
140
|
|
139
141
|
def within_window(locator)
|
@@ -286,7 +286,7 @@ module Capybara::Apparition
|
|
286
286
|
end
|
287
287
|
|
288
288
|
def invalid_element_errors
|
289
|
-
[Capybara::Apparition::ObsoleteNode, Capybara::Apparition::MouseEventFailed]
|
289
|
+
[Capybara::Apparition::ObsoleteNode, Capybara::Apparition::MouseEventFailed, Capybara::Apparition::WrongWorld]
|
290
290
|
end
|
291
291
|
|
292
292
|
def accept_modal(type, options = {})
|
@@ -7,7 +7,7 @@ module Capybara::Apparition
|
|
7
7
|
DEFAULT_PORT = 9664
|
8
8
|
|
9
9
|
def self.detect_browser
|
10
|
-
@browser ||= BROWSERS.find { |name| browser_binary_exists?(name) }
|
10
|
+
@browser ||= BROWSERS.find { |name| browser_binary_exists?(name) } # rubocop:disable Naming/MemoizedInstanceVariableName
|
11
11
|
end
|
12
12
|
|
13
13
|
attr_reader :port
|
@@ -44,7 +44,7 @@ module Capybara::Apparition
|
|
44
44
|
def html5_drag_to(element)
|
45
45
|
driver.execute_script MOUSEDOWN_TRACKER
|
46
46
|
scroll_if_needed
|
47
|
-
@page.mouse.move_to(
|
47
|
+
@page.mouse.move_to(visible_center).down
|
48
48
|
if driver.evaluate_script('window.capybara_mousedown_prevented')
|
49
49
|
element.scroll_if_needed
|
50
50
|
@page.mouse.move_to(element.visible_center).up
|
@@ -79,16 +79,7 @@ module Capybara::Apparition
|
|
79
79
|
def [](name)
|
80
80
|
# Although the attribute matters, the property is consistent. Return that in
|
81
81
|
# preference to the attribute for links and images.
|
82
|
-
|
83
|
-
# if ((tag_name == 'img') && (name == 'src')) || ((tag_name == 'a') && (name == 'href'))
|
84
|
-
# # if attribute exists get the property
|
85
|
-
# return attribute(name) && property(name)
|
86
|
-
# end
|
87
|
-
#
|
88
|
-
# value = property(name)
|
89
|
-
# value = attribute(name) if value.nil? || value.is_a?(Hash)
|
90
|
-
#
|
91
|
-
# value
|
82
|
+
evaluate_on ELEMENT_PROP_OR_ATTR_JS, value: name
|
92
83
|
end
|
93
84
|
|
94
85
|
def attributes
|
@@ -165,6 +156,7 @@ module Capybara::Apparition
|
|
165
156
|
raise ::Capybara::Apparition::MouseEventImpossible.new(self, 'args' => ['click']) if pos.nil?
|
166
157
|
|
167
158
|
test = mouse_event_test(pos)
|
159
|
+
raise ::Capybara::Apparition::MouseEventImpossible.new(self, 'args' => ['click']) if test.nil?
|
168
160
|
raise ::Capybara::Apparition::MouseEventFailed.new(self, 'args' => ['click', test.selector, pos]) unless test.success
|
169
161
|
|
170
162
|
@page.mouse.click_at pos.merge(button: button, count: count, modifiers: keys)
|
@@ -248,7 +240,9 @@ module Capybara::Apparition
|
|
248
240
|
|
249
241
|
frame_offset = @page.current_frame_offset
|
250
242
|
|
251
|
-
if
|
243
|
+
if rect['width'].zero? || rect['height'].zero?
|
244
|
+
return nil unless tag_name == 'area'
|
245
|
+
|
252
246
|
map = find('xpath', 'ancestor::map').first
|
253
247
|
img = find('xpath', "//img[@usemap='##{map[:name]}']").first
|
254
248
|
return nil unless img.visible?
|
@@ -280,7 +274,9 @@ module Capybara::Apparition
|
|
280
274
|
|
281
275
|
frame_offset = @page.current_frame_offset
|
282
276
|
|
283
|
-
if
|
277
|
+
if rect['width'].zero? || rect['height'].zero?
|
278
|
+
return nil unless tag_name == 'area'
|
279
|
+
|
284
280
|
map = find('xpath', 'ancestor::map').first
|
285
281
|
img = find('xpath', "//img[@usemap='##{map[:name]}']").first
|
286
282
|
return nil unless img.visible?
|
@@ -489,37 +485,54 @@ module Capybara::Apparition
|
|
489
485
|
end
|
490
486
|
|
491
487
|
def mouse_event_test(x:, y:)
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
return 'Element out of bounds';
|
503
|
-
|
504
|
-
let selector = '';
|
505
|
-
if (element.tagName != 'HTML')
|
506
|
-
selector = getSelector(element.parentNode) + ' ';
|
507
|
-
selector += element.tagName.toLowerCase();
|
508
|
-
if (element.id)
|
509
|
-
selector += `#${element.id}`;
|
510
|
-
|
511
|
-
for (let className of element.classList){
|
512
|
-
if (className != '')
|
513
|
-
selector += `.${className}`;
|
514
|
-
}
|
515
|
-
return selector;
|
488
|
+
r_o = @page.element_from_point(x: x, y: y)
|
489
|
+
return nil unless r_o && r_o['objectId']
|
490
|
+
|
491
|
+
hit_node = Capybara::Apparition::Node.new(driver, @page, r_o['objectId'])
|
492
|
+
result = begin
|
493
|
+
evaluate_on(<<~JS, objectId: hit_node.id)
|
494
|
+
function(hit_node){
|
495
|
+
if ((hit_node == this) || this.contains(hit_node))
|
496
|
+
return { status: 'success' };
|
497
|
+
return { status: 'failure' };
|
516
498
|
}
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
499
|
+
JS
|
500
|
+
rescue WrongWorld
|
501
|
+
{ 'status': 'failure' }
|
502
|
+
end
|
503
|
+
OpenStruct.new(success: result['status'] == 'success', selector: r_o['description'])
|
504
|
+
|
505
|
+
# frame_offset = @page.current_frame_offset
|
506
|
+
# # return { status: 'failure' } if x < 0 || y < 0
|
507
|
+
# result = evaluate_on(<<~JS, { value: x - frame_offset[:x] }, value: y - frame_offset[:y])
|
508
|
+
# function(x,y){
|
509
|
+
# const hit_node = document.elementFromPoint(x,y);
|
510
|
+
# if ((hit_node == this) || this.contains(hit_node))
|
511
|
+
# return { status: 'success' };
|
512
|
+
#
|
513
|
+
# const getSelector = function(element){
|
514
|
+
# if (element == null)
|
515
|
+
# return 'Element out of bounds';
|
516
|
+
#
|
517
|
+
# let selector = '';
|
518
|
+
# if (element.tagName != 'HTML')
|
519
|
+
# selector = getSelector(element.parentNode) + ' ';
|
520
|
+
# selector += element.tagName.toLowerCase();
|
521
|
+
# if (element.id)
|
522
|
+
# selector += `#${element.id}`;
|
523
|
+
#
|
524
|
+
# for (let className of element.classList){
|
525
|
+
# if (className != '')
|
526
|
+
# selector += `.${className}`;
|
527
|
+
# }
|
528
|
+
# return selector;
|
529
|
+
# }
|
530
|
+
#
|
531
|
+
# return { status: 'failure', selector: getSelector(hit_node) };
|
532
|
+
# }
|
533
|
+
# JS
|
534
|
+
#
|
535
|
+
# OpenStruct.new(success: result['status'] == 'success', selector: result['selector'])
|
523
536
|
end
|
524
537
|
|
525
538
|
def scroll_element_to_location(element, location)
|
@@ -615,7 +628,7 @@ module Capybara::Apparition
|
|
615
628
|
properties.each_with_object({}) do |property, object|
|
616
629
|
if property['enumerable']
|
617
630
|
object[property['name']] = property['value']['value']
|
618
|
-
else
|
631
|
+
else # rubocop:disable Style/EmptyElse
|
619
632
|
# releasePromises.push(helper.releaseObject(@element._client, property.value))
|
620
633
|
end
|
621
634
|
# releasePromises = [helper.releaseObject(@element._client, remote_object)]
|
@@ -749,11 +762,13 @@ module Capybara::Apparition
|
|
749
762
|
return false;
|
750
763
|
}
|
751
764
|
}
|
752
|
-
|
765
|
+
var forced_visible = false;
|
753
766
|
while (el) {
|
754
767
|
const style = window.getComputedStyle(el);
|
768
|
+
if (style.visibility == 'visible')
|
769
|
+
forced_visible = true;
|
755
770
|
if ((style.display == 'none') ||
|
756
|
-
(style.visibility == 'hidden') ||
|
771
|
+
((style.visibility == 'hidden') && !forced_visible) ||
|
757
772
|
(parseFloat(style.opacity) == 0)) {
|
758
773
|
return false;
|
759
774
|
}
|
@@ -43,7 +43,7 @@ module Capybara::Apparition
|
|
43
43
|
@modal_messages = []
|
44
44
|
@frames = Capybara::Apparition::FrameManager.new(id)
|
45
45
|
@response_headers = {}
|
46
|
-
@status_code =
|
46
|
+
@status_code = 0
|
47
47
|
@url_blacklist = []
|
48
48
|
@url_whitelist = []
|
49
49
|
@auth_attempts = []
|
@@ -68,7 +68,7 @@ module Capybara::Apparition
|
|
68
68
|
@modals.clear
|
69
69
|
@modal_messages.clear
|
70
70
|
@response_headers = {}
|
71
|
-
@status_code =
|
71
|
+
@status_code = 0
|
72
72
|
@auth_attempts = []
|
73
73
|
@perm_headers = {}
|
74
74
|
end
|
@@ -112,11 +112,7 @@ module Capybara::Apparition
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def current_frame_offset
|
115
|
-
|
116
|
-
|
117
|
-
result = command('DOM.getBoxModel', objectId: current_frame.element_id)
|
118
|
-
x, y = result['model']['content']
|
119
|
-
{ x: x, y: y }
|
115
|
+
frame_offset(current_frame)
|
120
116
|
end
|
121
117
|
|
122
118
|
def render(options)
|
@@ -233,7 +229,6 @@ module Capybara::Apparition
|
|
233
229
|
until cf.usable? || (allow_obsolete && cf.obsolete?) || @js_error
|
234
230
|
if timer.expired?
|
235
231
|
puts 'Timedout waiting for page to be loaded'
|
236
|
-
# byebug
|
237
232
|
raise TimeoutError.new('wait_for_loaded')
|
238
233
|
end
|
239
234
|
sleep 0.05
|
@@ -255,7 +250,7 @@ module Capybara::Apparition
|
|
255
250
|
|
256
251
|
def visit(url)
|
257
252
|
wait_for_loaded
|
258
|
-
@status_code =
|
253
|
+
@status_code = 0
|
259
254
|
navigate_opts = { url: url, transitionType: 'reload' }
|
260
255
|
navigate_opts[:referrer] = extra_headers['Referer'] if extra_headers['Referer']
|
261
256
|
response = command('Page.navigate', navigate_opts)
|
@@ -273,6 +268,17 @@ module Capybara::Apparition
|
|
273
268
|
_raw_evaluate('window.location.href', context_id: main_frame.context_id)
|
274
269
|
end
|
275
270
|
|
271
|
+
def element_from_point(x:, y:)
|
272
|
+
r_o = _raw_evaluate("document.elementFromPoint(#{x}, #{y})", context_id: main_frame.context_id)
|
273
|
+
while r_o && (r_o['description'] =~ /^iframe/)
|
274
|
+
frame_node = command('DOM.describeNode', objectId: r_o['objectId'])
|
275
|
+
frame = @frames.get(frame_node.dig('node', 'frameId'))
|
276
|
+
fo = frame_offset(frame)
|
277
|
+
r_o = _raw_evaluate("document.elementFromPoint(#{x - fo[:x]}, #{y - fo[:y]})", context_id: frame.context_id)
|
278
|
+
end
|
279
|
+
r_o
|
280
|
+
end
|
281
|
+
|
276
282
|
def frame_url
|
277
283
|
wait_for_loaded
|
278
284
|
_raw_evaluate('window.location.href')
|
@@ -361,6 +367,14 @@ module Capybara::Apparition
|
|
361
367
|
|
362
368
|
private
|
363
369
|
|
370
|
+
def frame_offset(frame)
|
371
|
+
return { x: 0, y: 0 } if frame.id == main_frame.id
|
372
|
+
|
373
|
+
result = command('DOM.getBoxModel', objectId: frame.element_id)
|
374
|
+
x, y = result['model']['content']
|
375
|
+
{ x: x, y: y }
|
376
|
+
end
|
377
|
+
|
364
378
|
def register_event_handlers
|
365
379
|
@session.on 'Page.javascriptDialogOpening' do |params|
|
366
380
|
type = params['type'].to_sym
|
@@ -437,7 +451,7 @@ module Capybara::Apparition
|
|
437
451
|
# end
|
438
452
|
# end
|
439
453
|
|
440
|
-
@session.on('Page.domContentEventFired') do
|
454
|
+
@session.on('Page.domContentEventFired') do
|
441
455
|
# TODO: Really need something better than this
|
442
456
|
main_frame.loaded! if @status_code != 200
|
443
457
|
end
|
@@ -497,7 +511,9 @@ module Capybara::Apparition
|
|
497
511
|
@session.on 'Network.loadingFailed' do |params|
|
498
512
|
req = @network_traffic.find { |request| request.request_id == params['requestId'] }
|
499
513
|
req&.blocked_params = params if params['blockedReason']
|
500
|
-
|
514
|
+
if params['type'] == 'Document'
|
515
|
+
puts "Loading Failed - request: #{params['requestId']} : #{params['errorText']}" if ENV['DEBUG']
|
516
|
+
end
|
501
517
|
end
|
502
518
|
|
503
519
|
@session.on 'Network.requestIntercepted' do |params|
|
@@ -546,7 +562,7 @@ module Capybara::Apparition
|
|
546
562
|
def process_intercepted_request(interception_id, request, navigation)
|
547
563
|
headers, url = request.values_at('headers', 'url')
|
548
564
|
|
549
|
-
unless @temp_headers.empty? || navigation
|
565
|
+
unless @temp_headers.empty? || navigation # rubocop:disable Style/IfUnlessModifier
|
550
566
|
headers.delete_if { |name, value| @temp_headers[name] == value }
|
551
567
|
end
|
552
568
|
unless @temp_no_redirect_headers.empty? || !navigation
|
@@ -711,7 +727,7 @@ module Capybara::Apparition
|
|
711
727
|
return properties.each_with_object(object_cache[stable_id]) do |property, memo|
|
712
728
|
if property['enumerable']
|
713
729
|
memo[property['name']] = decode_result(property['value'], object_cache)
|
714
|
-
else
|
730
|
+
else # rubocop:disable Style/EmptyElse
|
715
731
|
# TODO: Do we need to cleanup these resources?
|
716
732
|
# releasePromises.push(helper.releaseObject(@element._client, property.value))
|
717
733
|
end
|
data/lib/capybara/apparition.rb
CHANGED
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.3
|
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-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|