puppeteer-ruby 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2277fda99720c2566927af9a2acfc56da2b8e87ee10521871c368fd4a05649b2
4
- data.tar.gz: 59636e168935b0fb6c964cd62355ae3becf8199ed2ee1af58cb512ccacc9d7cb
3
+ metadata.gz: 63cde4d139f1dc95710efb059310822219b905ef4b44ec8a1347b4bdc97a6b2e
4
+ data.tar.gz: '0989de5d246bb1c2bcb5ab625eb0702f608ec6ec667db9bbcf4282cf419314fa'
5
5
  SHA512:
6
- metadata.gz: b45495a2ae160e740e242bc04bb81bfa493c1101583393f78e8e7ff3d065c00594fe0196b8225ac73e281a17428127597d11c8f8323ba6b58d64b437e2979d97
7
- data.tar.gz: 72c9bd1ca17f37927ceb51a79904583c638066e29cdb08cc2534e77bcc7b3ee348e53e69546ecd579917bd6d8db9c4413d4a63cf617ffa33b8c69c756603439e
6
+ metadata.gz: 96aaf3dc540e160dd983660f2ea4fa10a8c3a2126e9c56f57f9c7a11c31c956376f556473c2d6c591b4cf4253c92e91055cc564e1910fe6dbaf3eb8244d2e852
7
+ data.tar.gz: c2195746ce0ed09fb2be8e66cb842cc2fb9487c51cb2232e51f3970df0234aec97fce173627bbedd1c4d113cd82154c134a69d0f9eb02c23826ab0bc0ad7ee18
@@ -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/RedundantStringCoercion:
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
- Lint/DeprecatedClassMethods:
198
+ Style/ParenthesesAroundCondition:
169
199
  Enabled: true
170
200
 
171
- Style/ParenthesesAroundCondition:
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
+ [![Gem Version](https://badge.fury.io/rb/puppeteer-ruby.svg)](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
 
@@ -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: "return (#{PREDICATE})(...args)",
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 = @remote_object.content_quads(@client)
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
- # * @returns {!Promise<boolean>}
385
- # */
386
- # isIntersectingViewport() {
387
- # return this.evaluate(async element => {
388
- # const visibleRatio = await new Promise(resolve => {
389
- # const observer = new IntersectionObserver(entries => {
390
- # resolve(entries[0].intersectionRatio);
391
- # observer.disconnect();
392
- # });
393
- # observer.observe(element);
394
- # });
395
- # return visibleRatio > 0;
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)
@@ -142,7 +142,7 @@ class Puppeteer::Frame
142
142
  end
143
143
 
144
144
  def child_frames
145
- @child_frames.dup
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 {Function|string} pageFunction
246
- # @param {!{polling?: string|number, timeout?: number}=} options
247
- # @param {!Array<*>} args
248
- # @return {!Promise<!Puppeteer.JSHandle>}
249
- def wait_for_function(page_function, options = {}, *args)
250
- @main_world.wait_for_function(page_function, options, *args)
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
@@ -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
- # * @param {string} propertyName
62
- # * @return {!Promise<?JSHandle>}
63
- # */
64
- # async getProperty(propertyName) {
65
- # const objectHandle = await this.evaluateHandle((object, propertyName) => {
66
- # const result = {__proto__: null};
67
- # result[propertyName] = object[propertyName];
68
- # return result;
69
- # }, propertyName);
70
- # const properties = await objectHandle.getProperties();
71
- # const result = properties.get(propertyName) || null;
72
- # await objectHandle.dispose();
73
- # return result;
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
- # * @override
124
- # * @return {string}
125
- # */
126
- # toString() {
127
- # if (this._remoteObject.objectId) {
128
- # const type = this._remoteObject.subtype || this._remoteObject.type;
129
- # return 'JSHandle@' + type;
130
- # }
131
- # return 'JSHandle:' + helper.valueFromRemoteObject(this._remoteObject);
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
@@ -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 {Function|string} pageFunction
1130
- # @param {!{polling?: string|number, timeout?: number}=} options
1131
- # @param {!Array<*>} args
1132
- # @return {!Promise<!Puppeteer.JSHandle>}
1133
- def wait_for_function(page_function, options = {}, *args)
1134
- main_frame.wait_for_function(page_function, options, *args)
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:
@@ -1,3 +1,3 @@
1
1
  class Puppeteer
2
- VERSION = '0.0.17'
2
+ VERSION = '0.0.18'
3
3
  end
@@ -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)
@@ -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.86.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.17
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-07-28 00:00:00.000000000 Z
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.86.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.86.0
138
+ version: 0.89.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: rubocop-rspec
141
141
  requirement: !ruby/object:Gem::Requirement