puppeteer-ruby 0.0.17 → 0.0.18
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/.rubocop.yml +39 -3
- data/README.md +3 -1
- data/lib/puppeteer/dom_world.rb +21 -1
- data/lib/puppeteer/element_handle.rb +27 -16
- data/lib/puppeteer/frame.rb +13 -7
- data/lib/puppeteer/js_handle.rb +37 -27
- data/lib/puppeteer/page.rb +12 -6
- data/lib/puppeteer/remote_object.rb +16 -0
- data/lib/puppeteer/version.rb +1 -1
- data/lib/puppeteer/wait_task.rb +1 -1
- data/puppeteer-ruby.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63cde4d139f1dc95710efb059310822219b905ef4b44ec8a1347b4bdc97a6b2e
|
4
|
+
data.tar.gz: '0989de5d246bb1c2bcb5ab625eb0702f608ec6ec667db9bbcf4282cf419314fa'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96aaf3dc540e160dd983660f2ea4fa10a8c3a2126e9c56f57f9c7a11c31c956376f556473c2d6c591b4cf4253c92e91055cc564e1910fe6dbaf3eb8244d2e852
|
7
|
+
data.tar.gz: c2195746ce0ed09fb2be8e66cb842cc2fb9487c51cb2232e51f3970df0234aec97fce173627bbedd1c4d113cd82154c134a69d0f9eb02c23826ab0bc0ad7ee18
|
data/.rubocop.yml
CHANGED
@@ -146,17 +146,47 @@ Lint/AmbiguousOperator:
|
|
146
146
|
Lint/AmbiguousRegexpLiteral:
|
147
147
|
Enabled: true
|
148
148
|
|
149
|
+
Lint/BinaryOperatorWithIdenticalOperands:
|
150
|
+
Enabled: true
|
151
|
+
|
152
|
+
Lint/DeprecatedClassMethods:
|
153
|
+
Enabled: true
|
154
|
+
|
155
|
+
Lint/DuplicateRescueException:
|
156
|
+
Enabled: true
|
157
|
+
|
149
158
|
Lint/ErbNewArguments:
|
150
159
|
Enabled: true
|
151
160
|
|
161
|
+
Lint/EmptyConditionalBody:
|
162
|
+
Enabled: true
|
163
|
+
|
164
|
+
Lint/FloatComparison:
|
165
|
+
Enabled: true
|
166
|
+
|
167
|
+
Lint/MissingSuper:
|
168
|
+
Enabled: true
|
169
|
+
|
170
|
+
Lint/OutOfRangeRegexpRef:
|
171
|
+
Enabled: true
|
172
|
+
|
173
|
+
Lint/RedundantStringCoercion:
|
174
|
+
Enabled: true
|
175
|
+
|
152
176
|
# Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
|
153
177
|
Lint/RequireParentheses:
|
154
178
|
Enabled: true
|
155
179
|
|
180
|
+
Lint/SelfAssignment:
|
181
|
+
Enabled: true
|
182
|
+
|
156
183
|
Lint/ShadowingOuterLocalVariable:
|
157
184
|
Enabled: true
|
158
185
|
|
159
|
-
Lint/
|
186
|
+
Lint/TopLevelReturnWithArgument:
|
187
|
+
Enabled: true
|
188
|
+
|
189
|
+
Lint/UnreachableLoop:
|
160
190
|
Enabled: true
|
161
191
|
|
162
192
|
Lint/UriEscapeUnescape:
|
@@ -165,15 +195,18 @@ Lint/UriEscapeUnescape:
|
|
165
195
|
Lint/UselessAssignment:
|
166
196
|
Enabled: true
|
167
197
|
|
168
|
-
|
198
|
+
Style/ParenthesesAroundCondition:
|
169
199
|
Enabled: true
|
170
200
|
|
171
|
-
Style/
|
201
|
+
Style/ExplicitBlockArgument:
|
172
202
|
Enabled: true
|
173
203
|
|
174
204
|
Style/FrozenStringLiteralComment:
|
175
205
|
Enabled: false
|
176
206
|
|
207
|
+
Style/GlobalStdStream:
|
208
|
+
Enabled: true
|
209
|
+
|
177
210
|
Style/HashEachMethods:
|
178
211
|
Enabled: true
|
179
212
|
|
@@ -198,6 +231,9 @@ Style/Semicolon:
|
|
198
231
|
Enabled: true
|
199
232
|
AllowAsExpressionSeparator: true
|
200
233
|
|
234
|
+
Style/StringConcatenation:
|
235
|
+
Enabled: true
|
236
|
+
|
201
237
|
# Prefer Foo.method over Foo::method
|
202
238
|
Style/ColonMethodCall:
|
203
239
|
Enabled: true
|
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[](https://badge.fury.io/rb/puppeteer-ruby)
|
2
|
+
|
1
3
|
# Puppeteer in Ruby [UNDER HEAVY DEVELOPMENT]
|
2
4
|
|
3
5
|
A Ruby port of [puppeteer](https://pptr.dev/).
|
@@ -47,7 +49,7 @@ end
|
|
47
49
|
|
48
50
|
More usage examples can be found [here](https://github.com/YusukeIwaki/puppeteer-ruby-example)
|
49
51
|
|
50
|
-
## Collaboration with Selenium or Capybara
|
52
|
+
## :bulb: Collaboration with Selenium or Capybara
|
51
53
|
|
52
54
|
It is really remarkable that we can use puppeteer functions in existing Selenium or Capybara codes, with a few configuration in advance.
|
53
55
|
|
data/lib/puppeteer/dom_world.rb
CHANGED
@@ -402,6 +402,26 @@ class Puppeteer::DOMWorld
|
|
402
402
|
# return new WaitTask(this, pageFunction, 'function', polling, timeout, ...args).promise;
|
403
403
|
# }
|
404
404
|
|
405
|
+
# @param page_function [String]
|
406
|
+
# @param args [Array]
|
407
|
+
# @param polling [Integer|String]
|
408
|
+
# @param timeout [Integer]
|
409
|
+
# @return [Puppeteer::JSHandle]
|
410
|
+
def wait_for_function(page_function, args: [], polling: nil, timeout: nil)
|
411
|
+
option_polling = polling || 'raf'
|
412
|
+
option_timeout = timeout || @timeout_settings.timeout
|
413
|
+
|
414
|
+
Puppeteer::WaitTask.new(
|
415
|
+
dom_world: self,
|
416
|
+
predicate_body: page_function,
|
417
|
+
title: 'function',
|
418
|
+
polling: option_polling,
|
419
|
+
timeout: option_timeout,
|
420
|
+
args: args,
|
421
|
+
).await_promise
|
422
|
+
end
|
423
|
+
|
424
|
+
|
405
425
|
# @return [String]
|
406
426
|
def title
|
407
427
|
evaluate('() => document.title')
|
@@ -427,7 +447,7 @@ class Puppeteer::DOMWorld
|
|
427
447
|
|
428
448
|
wait_task = Puppeteer::WaitTask.new(
|
429
449
|
dom_world: self,
|
430
|
-
predicate_body:
|
450
|
+
predicate_body: PREDICATE,
|
431
451
|
title: title,
|
432
452
|
polling: polling,
|
433
453
|
timeout: option_timeout,
|
@@ -3,6 +3,7 @@ require_relative './element_handle/box_model'
|
|
3
3
|
require_relative './element_handle/point'
|
4
4
|
|
5
5
|
class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
6
|
+
include Puppeteer::DebugPrint
|
6
7
|
include Puppeteer::IfPresent
|
7
8
|
using Puppeteer::DefineAsyncMethod
|
8
9
|
|
@@ -62,7 +63,14 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
62
63
|
end
|
63
64
|
|
64
65
|
def clickable_point
|
65
|
-
result =
|
66
|
+
result =
|
67
|
+
begin
|
68
|
+
@remote_object.content_quads(@client)
|
69
|
+
rescue => err
|
70
|
+
debug_puts(err)
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
|
66
74
|
if !result || result["quads"].empty?
|
67
75
|
raise ElementNotVisibleError.new
|
68
76
|
end
|
@@ -380,21 +388,24 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
380
388
|
|
381
389
|
define_async_method :async_Sx
|
382
390
|
|
383
|
-
#
|
384
|
-
#
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
391
|
+
# in JS, #isIntersectingViewport.
|
392
|
+
# @return [Boolean]
|
393
|
+
def intersecting_viewport?
|
394
|
+
js = <<~JAVASCRIPT
|
395
|
+
async element => {
|
396
|
+
const visibleRatio = await new Promise(resolve => {
|
397
|
+
const observer = new IntersectionObserver(entries => {
|
398
|
+
resolve(entries[0].intersectionRatio);
|
399
|
+
observer.disconnect();
|
400
|
+
});
|
401
|
+
observer.observe(element);
|
402
|
+
});
|
403
|
+
return visibleRatio > 0;
|
404
|
+
}
|
405
|
+
JAVASCRIPT
|
406
|
+
|
407
|
+
evaluate(js)
|
408
|
+
end
|
398
409
|
|
399
410
|
# @param quad [Array<Point>]
|
400
411
|
private def compute_quad_area(quad)
|
data/lib/puppeteer/frame.rb
CHANGED
@@ -142,7 +142,7 @@ class Puppeteer::Frame
|
|
142
142
|
end
|
143
143
|
|
144
144
|
def child_frames
|
145
|
-
@child_frames.
|
145
|
+
@child_frames.to_a
|
146
146
|
end
|
147
147
|
|
148
148
|
def detached?
|
@@ -225,6 +225,11 @@ class Puppeteer::Frame
|
|
225
225
|
|
226
226
|
define_async_method :async_wait_for_selector
|
227
227
|
|
228
|
+
# @param milliseconds [Integer] the number of milliseconds to wait.
|
229
|
+
def wait_for_timeout(milliseconds)
|
230
|
+
sleep(milliseconds / 1000.0)
|
231
|
+
end
|
232
|
+
|
228
233
|
# @param xpath [String]
|
229
234
|
# @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
|
230
235
|
# @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
|
@@ -242,12 +247,13 @@ class Puppeteer::Frame
|
|
242
247
|
|
243
248
|
define_async_method :async_wait_for_xpath
|
244
249
|
|
245
|
-
# @param
|
246
|
-
# @param
|
247
|
-
# @param
|
248
|
-
# @
|
249
|
-
|
250
|
-
|
250
|
+
# @param page_function [String]
|
251
|
+
# @param args [Integer|Array]
|
252
|
+
# @param polling [String]
|
253
|
+
# @param timeout [Integer]
|
254
|
+
# @return [Puppeteer::JSHandle]
|
255
|
+
def wait_for_function(page_function, args: [], polling: nil, timeout: nil)
|
256
|
+
@main_world.wait_for_function(page_function, args: args, polling: polling, timeout: timeout)
|
251
257
|
end
|
252
258
|
|
253
259
|
define_async_method :async_wait_for_function
|
data/lib/puppeteer/js_handle.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class Puppeteer::JSHandle
|
2
2
|
using Puppeteer::DefineAsyncMethod
|
3
|
+
include Puppeteer::IfPresent
|
3
4
|
|
4
5
|
# @param context [Puppeteer::ExecutionContext]
|
5
6
|
# @param remote_object [Puppeteer::RemoteObject]
|
@@ -57,21 +58,29 @@ class Puppeteer::JSHandle
|
|
57
58
|
|
58
59
|
define_async_method :async_evaluate_handle
|
59
60
|
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
61
|
+
# getProperty(propertyName) in JavaScript
|
62
|
+
# @param name [String]
|
63
|
+
# @return [Puppeteer::JSHandle]
|
64
|
+
def property(name)
|
65
|
+
js = <<~JAVASCRIPT
|
66
|
+
(object, propertyName) => {
|
67
|
+
const result = {__proto__: null};
|
68
|
+
result[propertyName] = object[propertyName];
|
69
|
+
return result;
|
70
|
+
}
|
71
|
+
JAVASCRIPT
|
72
|
+
object_handle = evaluate_handle(js, name)
|
73
|
+
properties = object_handle.properties
|
74
|
+
result = properties[name]
|
75
|
+
object_handle.dispose
|
76
|
+
result
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param name [String]
|
80
|
+
# @return [Puppeteer::JSHandle]
|
81
|
+
def [](name)
|
82
|
+
property(name)
|
83
|
+
end
|
75
84
|
|
76
85
|
# getProperties in JavaScript.
|
77
86
|
# @return [Hash<String, JSHandle>]
|
@@ -101,7 +110,7 @@ class Puppeteer::JSHandle
|
|
101
110
|
#
|
102
111
|
# However it would be better that RemoteObject is responsible for
|
103
112
|
# the logic `if (this._remoteObject.objectId) { ... }`.
|
104
|
-
@remote_object.evaluate_self(@client) || @remote_object.value
|
113
|
+
@remote_object.evaluate_self(@client)&.value || @remote_object.value
|
105
114
|
end
|
106
115
|
|
107
116
|
def as_element
|
@@ -119,15 +128,16 @@ class Puppeteer::JSHandle
|
|
119
128
|
@disposed
|
120
129
|
end
|
121
130
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
131
|
+
def to_s
|
132
|
+
# original logic was:
|
133
|
+
# if (this._remoteObject.objectId) {
|
134
|
+
# const type = this._remoteObject.subtype || this._remoteObject.type;
|
135
|
+
# return 'JSHandle@' + type;
|
136
|
+
# }
|
137
|
+
# return 'JSHandle:' + helper.valueFromRemoteObject(this._remoteObject);
|
138
|
+
#
|
139
|
+
# However it would be better that RemoteObject is responsible for
|
140
|
+
# the logic `if (this._remoteObject.objectId) { ... }`.
|
141
|
+
if_present(@remote_object.type_str) { |type_str| "JSHandle@#{type_str}" } || "JSHandle:#{@remote_object.value || 'undefined'}"
|
142
|
+
end
|
133
143
|
end
|
data/lib/puppeteer/page.rb
CHANGED
@@ -1116,6 +1116,11 @@ class Puppeteer::Page
|
|
1116
1116
|
|
1117
1117
|
define_async_method :async_wait_for_selector
|
1118
1118
|
|
1119
|
+
# @param milliseconds [Integer] the number of milliseconds to wait.
|
1120
|
+
def wait_for_timeout(milliseconds)
|
1121
|
+
main_frame.wait_for_timeout(milliseconds)
|
1122
|
+
end
|
1123
|
+
|
1119
1124
|
# @param xpath [String]
|
1120
1125
|
# @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
|
1121
1126
|
# @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
|
@@ -1126,12 +1131,13 @@ class Puppeteer::Page
|
|
1126
1131
|
|
1127
1132
|
define_async_method :async_wait_for_xpath
|
1128
1133
|
|
1129
|
-
# @param
|
1130
|
-
# @param
|
1131
|
-
# @param
|
1132
|
-
# @
|
1133
|
-
|
1134
|
-
|
1134
|
+
# @param page_function [String]
|
1135
|
+
# @param args [Integer|Array]
|
1136
|
+
# @param polling [String]
|
1137
|
+
# @param timeout [Integer]
|
1138
|
+
# @return [Puppeteer::JSHandle]
|
1139
|
+
def wait_for_function(page_function, args: [], polling: nil, timeout: nil)
|
1140
|
+
main_frame.wait_for_function(page_function, args: args, polling: polling, timeout: timeout)
|
1135
1141
|
end
|
1136
1142
|
|
1137
1143
|
define_async_method :async_wait_for_function
|
@@ -6,6 +6,7 @@ class Puppeteer::RemoteObject
|
|
6
6
|
# @param payload [Hash]
|
7
7
|
def initialize(payload)
|
8
8
|
@object_id = payload['objectId']
|
9
|
+
@type = payload['type']
|
9
10
|
@sub_type = payload['subtype']
|
10
11
|
@unserializable_value = payload['unserializableValue']
|
11
12
|
@value = payload['value']
|
@@ -42,6 +43,21 @@ class Puppeteer::RemoteObject
|
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
46
|
+
# @return [String]
|
47
|
+
def type_str
|
48
|
+
# used in JSHandle#to_s
|
49
|
+
# original logic:
|
50
|
+
# if (this._remoteObject.objectId) {
|
51
|
+
# const type = this._remoteObject.subtype || this._remoteObject.type;
|
52
|
+
# return 'JSHandle@' + type;
|
53
|
+
# }
|
54
|
+
if @object_id
|
55
|
+
@sub_type || @type
|
56
|
+
else
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
45
61
|
# used in JSHandle#properties
|
46
62
|
def properties(client)
|
47
63
|
# original logic:
|
data/lib/puppeteer/version.rb
CHANGED
data/lib/puppeteer/wait_task.rb
CHANGED
@@ -25,7 +25,7 @@ class Puppeteer::WaitTask
|
|
25
25
|
@dom_world = dom_world
|
26
26
|
@polling = polling
|
27
27
|
@timeout = timeout
|
28
|
-
@predicate_body = predicate_body
|
28
|
+
@predicate_body = "return (#{predicate_body})(...args);"
|
29
29
|
@args = args
|
30
30
|
@run_count = 0
|
31
31
|
@dom_world._wait_tasks.add(self)
|
data/puppeteer-ruby.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_development_dependency 'rake', '~> 10.0'
|
27
27
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
28
28
|
spec.add_development_dependency 'rspec_junit_formatter' # for CircleCI.
|
29
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
29
|
+
spec.add_development_dependency 'rubocop', '~> 0.89.0'
|
30
30
|
spec.add_development_dependency 'rubocop-rspec'
|
31
31
|
spec.add_development_dependency 'sinatra'
|
32
32
|
spec.add_development_dependency 'yard'
|
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.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- YusukeIwaki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -128,14 +128,14 @@ dependencies:
|
|
128
128
|
requirements:
|
129
129
|
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: 0.
|
131
|
+
version: 0.89.0
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 0.
|
138
|
+
version: 0.89.0
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: rubocop-rspec
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|