puppeteer-ruby 0.0.3 → 0.0.4
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/.github/stale.yml +16 -0
- data/README.md +2 -0
- data/lib/puppeteer/cdp_session.rb +2 -2
- data/lib/puppeteer/dom_world.rb +21 -17
- data/lib/puppeteer/element_handle.rb +117 -79
- data/lib/puppeteer/execution_context.rb +5 -0
- data/lib/puppeteer/frame.rb +6 -4
- data/lib/puppeteer/frame_manager.rb +6 -6
- data/lib/puppeteer/js_handle.rb +0 -1
- data/lib/puppeteer/keyboard.rb +1 -1
- data/lib/puppeteer/keyboard/us_keyboard_layout.rb +4 -4
- data/lib/puppeteer/lifecycle_watcher.rb +6 -1
- data/lib/puppeteer/mouse.rb +10 -7
- data/lib/puppeteer/page.rb +14 -3
- data/lib/puppeteer/remote_object.rb +5 -0
- data/lib/puppeteer/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2764adee69056c36a0112866aa1f35a97ccb655ed81bc2977be9707efed7d121
|
4
|
+
data.tar.gz: 8919e7f0228b6dff08a1ee13906c97ad2d08552b1fd7652bc094b506bc9ac4e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c142553b4316d8cf7cf541e41283f01c982fc2f0ece3ffb1f87c258130035e3894062831364284fdfaa6c97771029687232955f7a4e64cb24e8d876aee36f08d
|
7
|
+
data.tar.gz: 5d59f78bb651c955617b0a0fee01b02b9e5aa4907d46d15cc79acf559db8f44d1a2a96ecd76571d3431737bfa8b9fd8a24a9a2ad80c5c8c0cc9754c42d1b75af
|
data/.github/stale.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Number of days of inactivity before an issue becomes stale
|
2
|
+
daysUntilStale: 14
|
3
|
+
# Number of days of inactivity before a stale issue is closed
|
4
|
+
daysUntilClose: 7
|
5
|
+
# Issues with these labels will never be considered stale
|
6
|
+
exemptLabels:
|
7
|
+
- security
|
8
|
+
# Label to use when marking an issue as stale
|
9
|
+
staleLabel: inactive
|
10
|
+
# Comment to post when marking an issue as stale. Set to `false` to disable
|
11
|
+
markComment: >
|
12
|
+
This issue has been automatically marked as stale because it has not had
|
13
|
+
recent activity. It will be closed if no further activity occurs. Thank you
|
14
|
+
for your contributions.
|
15
|
+
# Comment to post when closing a stale issue. Set to `false` to disable
|
16
|
+
closeComment: false
|
data/README.md
CHANGED
@@ -46,6 +46,8 @@ end
|
|
46
46
|

|
47
47
|
|
48
48
|
|
49
|
+
More usage examples can be found [here](https://github.com/YusukeIwaki/puppeteer-ruby-example)
|
50
|
+
|
49
51
|
## Contributing
|
50
52
|
|
51
53
|
Bug reports and pull requests are welcome on GitHub at https://github.com/YusukeIwaki/puppeteer-ruby.
|
@@ -44,8 +44,8 @@ class Puppeteer::CDPSession
|
|
44
44
|
callback.reject(
|
45
45
|
Puppeteer::Connection::ProtocolError.new(
|
46
46
|
method: callback.method,
|
47
|
-
error_message:
|
48
|
-
error_data:
|
47
|
+
error_message: message['error']['message'],
|
48
|
+
error_data: message['error']['data']))
|
49
49
|
else
|
50
50
|
callback.resolve(message['result'])
|
51
51
|
end
|
data/lib/puppeteer/dom_world.rb
CHANGED
@@ -12,6 +12,7 @@ class Puppeteer::DOMWorld
|
|
12
12
|
@frame = frame
|
13
13
|
@timeout_settings = timeout_settings
|
14
14
|
@context_promise = resolvable_future
|
15
|
+
@pending_destroy = []
|
15
16
|
@wait_tasks = Set.new
|
16
17
|
@detached = false
|
17
18
|
end
|
@@ -29,20 +30,24 @@ class Puppeteer::DOMWorld
|
|
29
30
|
|
30
31
|
if context
|
31
32
|
if @context_promise.fulfilled?
|
33
|
+
@pending_destroy << context._context_id
|
32
34
|
@document = nil
|
33
35
|
@context_promise = resolvable_future
|
34
|
-
@pending_destroy_exists = true
|
35
36
|
end
|
36
37
|
@context_promise.fulfill(context)
|
37
38
|
# for (const waitTask of this._waitTasks)
|
38
39
|
# waitTask.rerun();
|
39
40
|
else
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
raise ArgumentError.new("context should now be nil. Use #delete_context for clearing document.")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete_context(execution_context_id)
|
46
|
+
if @pending_destroy.include?(execution_context_id)
|
47
|
+
@pending_destroy.delete(execution_context_id)
|
48
|
+
else
|
49
|
+
@document = nil
|
50
|
+
@context_promise = resolvable_future
|
46
51
|
end
|
47
52
|
end
|
48
53
|
|
@@ -303,16 +308,15 @@ class Puppeteer::DOMWorld
|
|
303
308
|
# }
|
304
309
|
# }
|
305
310
|
|
306
|
-
#
|
307
|
-
#
|
308
|
-
#
|
309
|
-
#
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
# }
|
311
|
+
# @param selector [String]
|
312
|
+
# @param delay [Number]
|
313
|
+
# @param button [String] "left"|"right"|"middle"
|
314
|
+
# @param click_count [Number]
|
315
|
+
def click(selector, delay: nil, button: nil, click_count: nil)
|
316
|
+
handle = S(selector)
|
317
|
+
handle.click(delay: delay, button: button, click_count: click_count)
|
318
|
+
handle.dispose
|
319
|
+
end
|
316
320
|
|
317
321
|
# /**
|
318
322
|
# * @param {string} selector
|
@@ -28,62 +28,89 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
31
|
+
class ScrollIntoViewError < StandardError; end
|
32
|
+
|
33
|
+
def scroll_into_view_if_needed
|
34
|
+
js = <<~JAVASCRIPT
|
35
|
+
async(element, pageJavascriptEnabled) => {
|
36
|
+
if (!element.isConnected)
|
37
|
+
return 'Node is detached from document';
|
38
|
+
if (element.nodeType !== Node.ELEMENT_NODE)
|
39
|
+
return 'Node is not of type HTMLElement';
|
40
|
+
// force-scroll if page's javascript is disabled.
|
41
|
+
if (!pageJavascriptEnabled) {
|
42
|
+
element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'});
|
43
|
+
return false;
|
44
|
+
}
|
45
|
+
const visibleRatio = await new Promise(resolve => {
|
46
|
+
const observer = new IntersectionObserver(entries => {
|
47
|
+
resolve(entries[0].intersectionRatio);
|
48
|
+
observer.disconnect();
|
49
|
+
});
|
50
|
+
observer.observe(element);
|
51
|
+
});
|
52
|
+
if (visibleRatio !== 1.0)
|
53
|
+
element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'});
|
54
|
+
return false;
|
55
|
+
}
|
56
|
+
JAVASCRIPT
|
57
|
+
error = evaluate(js, @page.javascript_enabled) # returns String or false
|
58
|
+
if error
|
59
|
+
raise ScrollIntoViewError.new(error)
|
60
|
+
end
|
61
|
+
end
|
56
62
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
63
|
+
class Point
|
64
|
+
def initialize(x:, y:)
|
65
|
+
@x = x
|
66
|
+
@y = y
|
67
|
+
end
|
68
|
+
|
69
|
+
def +(other)
|
70
|
+
Point.new(
|
71
|
+
x: @x + other.x,
|
72
|
+
y: @y + other.y,
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
def /(num)
|
77
|
+
Point.new(
|
78
|
+
x: @x / num,
|
79
|
+
y: @y / num,
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
attr_reader :x, :y
|
84
|
+
end
|
85
|
+
|
86
|
+
class ElementNotVisibleError < StandardError
|
87
|
+
def initialize
|
88
|
+
super("Node is either not visible or not an HTMLElement")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def clickable_point
|
93
|
+
result = @remote_object.content_quads(@client)
|
94
|
+
if !result || result["quads"].empty?
|
95
|
+
raise ElementNotVisibleError.new
|
96
|
+
end
|
97
|
+
|
98
|
+
# Filter out quads that have too small area to click into.
|
99
|
+
layout_metrics = @client.send_message('Page.getLayoutMetrics')
|
100
|
+
client_width = layout_metrics["layoutViewport"]["clientWidth"]
|
101
|
+
client_height = layout_metrics["layoutViewport"]["clientHeight"]
|
102
|
+
|
103
|
+
quads = result["quads"].
|
104
|
+
map { |quad| from_protocol_quad(quad) }.
|
105
|
+
map { |quad| intersect_quad_with_viewport(quad, client_width, client_height) }.
|
106
|
+
select { |quad| compute_quad_area(quad) > 1 }
|
107
|
+
if quads.empty?
|
108
|
+
raise ElementNotVisibleError.new
|
109
|
+
end
|
110
|
+
|
111
|
+
# Return the middle point of the first quad.
|
112
|
+
quads.first.reduce(:+) / 4
|
113
|
+
end
|
87
114
|
|
88
115
|
# /**
|
89
116
|
# * @return {!Promise<void|Protocol.DOM.getBoxModelReturnValue>}
|
@@ -94,31 +121,26 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
94
121
|
# }).catch(error => debugError(error));
|
95
122
|
# }
|
96
123
|
|
97
|
-
#
|
98
|
-
#
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
# {x: quad[2], y: quad[3]},
|
105
|
-
# {x: quad[4], y: quad[5]},
|
106
|
-
# {x: quad[6], y: quad[7]}
|
107
|
-
# ];
|
108
|
-
# }
|
124
|
+
# @param quad [Array<number>]
|
125
|
+
# @return [Array<Point>]
|
126
|
+
private def from_protocol_quad(quad)
|
127
|
+
quad.each_slice(2).map do |x, y|
|
128
|
+
Point.new(x: x, y: y)
|
129
|
+
end
|
130
|
+
end
|
109
131
|
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
132
|
+
# @param quad [Array<Point>]
|
133
|
+
# @param width [number]
|
134
|
+
# @param height [number]
|
135
|
+
# @return [Array<Point>]
|
136
|
+
private def intersect_quad_with_viewport(quad, width, height)
|
137
|
+
quad.map do |point|
|
138
|
+
Point.new(
|
139
|
+
x: [[point.x, 0].max, width].min,
|
140
|
+
y: [[point.y, 0].max, height].min,
|
141
|
+
)
|
142
|
+
end
|
143
|
+
end
|
122
144
|
|
123
145
|
# async hover() {
|
124
146
|
# await this._scrollIntoViewIfNeeded();
|
@@ -126,6 +148,15 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
126
148
|
# await this._page.mouse.move(x, y);
|
127
149
|
# }
|
128
150
|
|
151
|
+
# @param delay [Number]
|
152
|
+
# @param button [String] "left"|"right"|"middle"
|
153
|
+
# @param click_count [Number]
|
154
|
+
def click(delay: nil, button: nil, click_count: nil)
|
155
|
+
scroll_into_view_if_needed
|
156
|
+
point = clickable_point
|
157
|
+
@page.mouse.click(point.x, point.y, delay: delay, button: button, click_count: click_count)
|
158
|
+
end
|
159
|
+
|
129
160
|
# /**
|
130
161
|
# * @param {!{delay?: number, button?: "left"|"right"|"middle", clickCount?: number}=} options
|
131
162
|
# */
|
@@ -430,4 +461,11 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
430
461
|
# return visibleRatio > 0;
|
431
462
|
# });
|
432
463
|
# }
|
464
|
+
|
465
|
+
# @param quad [Array<Point>]
|
466
|
+
private def compute_quad_area(quad)
|
467
|
+
# Compute sum of all directed areas of adjacent triangles
|
468
|
+
# https://en.wikipedia.org/wiki/Polygon#Simple_polygons
|
469
|
+
quad.zip(quad.rotate).map { |p1, p2| (p1.x * p2.y - p2.x * p1.y) / 2 }.reduce(:+).abs
|
470
|
+
end
|
433
471
|
end
|
data/lib/puppeteer/frame.rb
CHANGED
@@ -143,8 +143,10 @@ class Puppeteer::Frame
|
|
143
143
|
@main_world.add_style_tag(style_tag)
|
144
144
|
end
|
145
145
|
|
146
|
-
# @param
|
147
|
-
# @param
|
146
|
+
# @param selector [String]
|
147
|
+
# @param delay [Number]
|
148
|
+
# @param button [String] "left"|"right"|"middle"
|
149
|
+
# @param click_count [Number]
|
148
150
|
def click(selector, delay: nil, button: nil, click_count: nil)
|
149
151
|
@secondary_world.click(selector, delay: delay, button: button, click_count: click_count)
|
150
152
|
end
|
@@ -268,8 +270,8 @@ class Puppeteer::Frame
|
|
268
270
|
|
269
271
|
def detach
|
270
272
|
@detached = true
|
271
|
-
|
272
|
-
|
273
|
+
@main_world.detach
|
274
|
+
@secondary_world.detach
|
273
275
|
if @parent_frame
|
274
276
|
@parent_frame._child_frames.delete(self)
|
275
277
|
end
|
@@ -206,12 +206,12 @@ class Puppeteer::FrameManager
|
|
206
206
|
# @param {string} frameId
|
207
207
|
# @param {?string} parentFrameId
|
208
208
|
def handle_frame_attached(frame_id, parent_frame_id)
|
209
|
-
return if @frames.has_key?
|
209
|
+
return if @frames.has_key?(frame_id)
|
210
210
|
if !parent_frame_id
|
211
211
|
raise ArgymentError.new('parent_frame_id must not be nil')
|
212
212
|
end
|
213
213
|
parent_frame = @frames[parent_frame_id]
|
214
|
-
frame = Frame.new(self, @client, parent_frame, frame_id)
|
214
|
+
frame = Puppeteer::Frame.new(self, @client, parent_frame, frame_id)
|
215
215
|
@frames[frame_id] = frame
|
216
216
|
|
217
217
|
emit_event 'Events.FrameManager.FrameAttached', frame
|
@@ -332,12 +332,12 @@ class Puppeteer::FrameManager
|
|
332
332
|
@context_id_to_context.delete(execution_context_id)
|
333
333
|
@context_id_created.delete(execution_context_id)
|
334
334
|
if context.world
|
335
|
-
context.world.
|
335
|
+
context.world.delete_context(execution_context_id)
|
336
336
|
end
|
337
337
|
end
|
338
338
|
|
339
339
|
def handle_execution_contexts_cleared
|
340
|
-
#
|
340
|
+
# executionContextsCleared is often notified after executionContextCreated.
|
341
341
|
# D, [2020-04-06T01:47:03.101227 #13823] DEBUG -- : RECV << {"method"=>"Runtime.executionContextCreated", "params"=>{"context"=>{"id"=>5, "origin"=>"https://github.com", "name"=>"", "auxData"=>{"isDefault"=>true, "type"=>"default", "frameId"=>"71C347B70848B89DDDEFAA8AB5B0BC92"}}}, "sessionId"=>"53F088EED260C28001D26A019F95D9E3"}
|
342
342
|
# D, [2020-04-06T01:47:03.101439 #13823] DEBUG -- : RECV << {"method"=>"Page.frameNavigated", "params"=>{"frame"=>{"id"=>"71C347B70848B89DDDEFAA8AB5B0BC92", "loaderId"=>"80338225D035AC96BAE8F6D4E81C7D51", "url"=>"https://github.com/search?q=puppeteer", "securityOrigin"=>"https://github.com", "mimeType"=>"text/html"}}, "sessionId"=>"53F088EED260C28001D26A019F95D9E3"}
|
343
343
|
# D, [2020-04-06T01:47:03.101325 #13823] DEBUG -- : RECV << {"method"=>"Target.targetInfoChanged", "params"=>{"targetInfo"=>{"targetId"=>"71C347B70848B89DDDEFAA8AB5B0BC92", "type"=>"page", "title"=>"https://github.com/search?q=puppeteer", "url"=>"https://github.com/search?q=puppeteer", "attached"=>true, "browserContextId"=>"AF37BC660284CE1552B4ECB147BE9305"}}}
|
@@ -346,9 +346,9 @@ class Puppeteer::FrameManager
|
|
346
346
|
# To avoid the problem, just skip recent created ids.
|
347
347
|
now = Time.now
|
348
348
|
context_ids_to_skip = @context_id_created.select { |k, v| now - v < 1 }.keys
|
349
|
-
@context_id_to_context.reject { |k, v| context_ids_to_skip.include?(k) }.
|
349
|
+
@context_id_to_context.reject { |k, v| context_ids_to_skip.include?(k) }.each do |execution_context_id, context|
|
350
350
|
if context.world
|
351
|
-
context.world.
|
351
|
+
context.world.delete_context(execution_context_id)
|
352
352
|
end
|
353
353
|
end
|
354
354
|
@context_id_to_context.select! { |k, v| context_ids_to_skip.include?(k) }
|
data/lib/puppeteer/js_handle.rb
CHANGED
data/lib/puppeteer/keyboard.rb
CHANGED
@@ -41,10 +41,10 @@ class Puppeteer::Keyboard
|
|
41
41
|
'Backspace': KeyDefinition.new({ 'keyCode': 8, 'code': 'Backspace', 'key': 'Backspace' }),
|
42
42
|
'Tab': KeyDefinition.new({ 'keyCode': 9, 'code': 'Tab', 'key': 'Tab' }),
|
43
43
|
'Numpad5': KeyDefinition.new({ 'keyCode': 12, 'shiftKeyCode': 101, 'key': 'Clear', 'code': 'Numpad5', 'shiftKey': '5', 'location': 3 }),
|
44
|
-
'NumpadEnter': KeyDefinition.new({ 'keyCode': 13, 'code': 'NumpadEnter', 'key': 'Enter', 'text':
|
45
|
-
'Enter': KeyDefinition.new({ 'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text':
|
46
|
-
|
47
|
-
|
44
|
+
'NumpadEnter': KeyDefinition.new({ 'keyCode': 13, 'code': 'NumpadEnter', 'key': 'Enter', 'text': "\r", 'location': 3 }),
|
45
|
+
'Enter': KeyDefinition.new({ 'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': "\r" }),
|
46
|
+
"\r": KeyDefinition.new({ 'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': "\r" }),
|
47
|
+
"\n": KeyDefinition.new({ 'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': "\r" }),
|
48
48
|
'ShiftLeft': KeyDefinition.new({ 'keyCode': 16, 'code': 'ShiftLeft', 'key': 'Shift', 'location': 1 }),
|
49
49
|
'ShiftRight': KeyDefinition.new({ 'keyCode': 16, 'code': 'ShiftRight', 'key': 'Shift', 'location': 2 }),
|
50
50
|
'ControlLeft': KeyDefinition.new({ 'keyCode': 17, 'code': 'ControlLeft', 'key': 'Control', 'location': 1 }),
|
@@ -50,6 +50,11 @@ class Puppeteer::LifecycleWatcher
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
class FrameDetachedError < StandardError
|
54
|
+
def initialize
|
55
|
+
super('Navigating frame was detached')
|
56
|
+
end
|
57
|
+
end
|
53
58
|
class TerminatedError < StandardError; end
|
54
59
|
|
55
60
|
# * @param {!Puppeteer.FrameManager} frameManager
|
@@ -92,7 +97,7 @@ class Puppeteer::LifecycleWatcher
|
|
92
97
|
# @param frame [Puppeteer::Frame]
|
93
98
|
def handle_frame_detached(frame)
|
94
99
|
if @frame == frame
|
95
|
-
|
100
|
+
@termination_promise.reject(FrameDetachedError.new)
|
96
101
|
return
|
97
102
|
end
|
98
103
|
check_lifecycle_complete
|
data/lib/puppeteer/mouse.rb
CHANGED
@@ -37,8 +37,8 @@ class Puppeteer::Mouse
|
|
37
37
|
@client.send_message('Input.dispatchMouseEvent',
|
38
38
|
type: 'mouseMoved',
|
39
39
|
button: @button,
|
40
|
-
x: from_x + (@x - from_x) * n /
|
41
|
-
y: from_y + (@y - from_y) * n /
|
40
|
+
x: from_x + (@x - from_x) * n / move_steps,
|
41
|
+
y: from_y + (@y - from_y) * n / move_steps,
|
42
42
|
modifiers: @keyboard.modifiers,
|
43
43
|
)
|
44
44
|
end
|
@@ -56,16 +56,19 @@ class Puppeteer::Mouse
|
|
56
56
|
# @param y [number]
|
57
57
|
# @param {!{delay?: number, button?: "left"|"right"|"middle", clickCount?: number}=} options
|
58
58
|
def click(x, y, delay: nil, button: nil, click_count: nil)
|
59
|
+
# await_all(async_move, async_down, async_up) often breaks the order of CDP commands.
|
60
|
+
# D, [2020-04-15T17:09:47.895895 #88683] DEBUG -- : RECV << {"id"=>23, "result"=>{"layoutViewport"=>{"pageX"=>0, "pageY"=>1, "clientWidth"=>375, "clientHeight"=>667}, "visualViewport"=>{"offsetX"=>0, "offsetY"=>0, "pageX"=>0, "pageY"=>1, "clientWidth"=>375, "clientHeight"=>667, "scale"=>1, "zoom"=>1}, "contentSize"=>{"x"=>0, "y"=>0, "width"=>375, "height"=>2007}}, "sessionId"=>"0B09EA5E18DEE403E525B3E7FCD7E225"}
|
61
|
+
# D, [2020-04-15T17:09:47.898422 #88683] DEBUG -- : SEND >> {"sessionId":"0B09EA5E18DEE403E525B3E7FCD7E225","method":"Input.dispatchMouseEvent","params":{"type":"mouseReleased","button":"left","x":0,"y":0,"modifiers":0,"clickCount":1},"id":24}
|
62
|
+
# D, [2020-04-15T17:09:47.899711 #88683] DEBUG -- : SEND >> {"sessionId":"0B09EA5E18DEE403E525B3E7FCD7E225","method":"Input.dispatchMouseEvent","params":{"type":"mousePressed","button":"left","x":0,"y":0,"modifiers":0,"clickCount":1},"id":25}
|
63
|
+
# D, [2020-04-15T17:09:47.900237 #88683] DEBUG -- : SEND >> {"sessionId":"0B09EA5E18DEE403E525B3E7FCD7E225","method":"Input.dispatchMouseEvent","params":{"type":"mouseMoved","button":"left","x":187,"y":283,"modifiers":0},"id":26}
|
64
|
+
# So we execute move in advance.
|
65
|
+
move(x, y)
|
59
66
|
if delay
|
60
|
-
|
61
|
-
async_move(x, y),
|
62
|
-
async_down(button: button, click_count: click_count),
|
63
|
-
)
|
67
|
+
down(button: button, click_count: click_count)
|
64
68
|
sleep(delay / 1000.0)
|
65
69
|
up(button: button, click_count: click_count)
|
66
70
|
else
|
67
71
|
await_all(
|
68
|
-
async_move(x, y),
|
69
72
|
async_down(button: button, click_count: click_count),
|
70
73
|
async_up(button: button, click_count: click_count),
|
71
74
|
)
|
data/lib/puppeteer/page.rb
CHANGED
@@ -173,7 +173,7 @@ class Puppeteer::Page
|
|
173
173
|
# await this._client.send('Emulation.setGeolocationOverride', {longitude, latitude, accuracy});
|
174
174
|
# }
|
175
175
|
|
176
|
-
attr_reader :target
|
176
|
+
attr_reader :javascript_enabled, :target
|
177
177
|
|
178
178
|
def browser
|
179
179
|
@target.browser
|
@@ -932,12 +932,23 @@ class Puppeteer::Page
|
|
932
932
|
|
933
933
|
attr_reader :mouse
|
934
934
|
|
935
|
-
# @param
|
936
|
-
# @param
|
935
|
+
# @param selector [String]
|
936
|
+
# @param delay [Number]
|
937
|
+
# @param button [String] "left"|"right"|"middle"
|
938
|
+
# @param click_count [Number]
|
937
939
|
def click(selector, delay: nil, button: nil, click_count: nil)
|
938
940
|
main_frame.click(selector, delay: delay, button: button, click_count: click_count)
|
939
941
|
end
|
940
942
|
|
943
|
+
# @param selector [String]
|
944
|
+
# @param delay [Number]
|
945
|
+
# @param button [String] "left"|"right"|"middle"
|
946
|
+
# @param click_count [Number]
|
947
|
+
# @return [Future]
|
948
|
+
async def async_click(selector, delay: nil, button: nil, click_count: nil)
|
949
|
+
click(selector, delay: delay, button: button, click_count: click_count)
|
950
|
+
end
|
951
|
+
|
941
952
|
# @param {string} selector
|
942
953
|
def focus(selector)
|
943
954
|
main_frame.focus(selector)
|
@@ -57,6 +57,11 @@ class Puppeteer::RemoteObject
|
|
57
57
|
client.send_message('DOM.describeNode', objectId: @object_id)
|
58
58
|
end
|
59
59
|
|
60
|
+
# used in ElementHandle#clickable_point
|
61
|
+
def content_quads(client)
|
62
|
+
client.send_message('DOM.getContentQuads', objectId: @object_id)
|
63
|
+
end
|
64
|
+
|
60
65
|
# helper#valueFromRemoteObject
|
61
66
|
def value
|
62
67
|
if @unserializable_value
|
data/lib/puppeteer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppeteer-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- YusukeIwaki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-04-
|
11
|
+
date: 2020-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -130,6 +130,7 @@ extensions: []
|
|
130
130
|
extra_rdoc_files: []
|
131
131
|
files:
|
132
132
|
- ".circleci/config.yml"
|
133
|
+
- ".github/stale.yml"
|
133
134
|
- ".gitignore"
|
134
135
|
- ".rspec"
|
135
136
|
- ".rubocop.yml"
|