puppeteer-ruby 0.0.16 → 0.0.21

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.
@@ -101,7 +101,9 @@ class Puppeteer::Page
101
101
  end
102
102
  # client.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event));
103
103
  # client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));
104
- # client.on('Page.javascriptDialogOpening', event => this._onDialog(event));
104
+ @client.on_event 'Page.javascriptDialogOpening' do |event|
105
+ handle_dialog_opening(event)
106
+ end
105
107
  # client.on('Runtime.exceptionThrown', exception => this._handleException(exception.exceptionDetails));
106
108
  # client.on('Inspector.targetCrashed', event => this._onTargetCrashed());
107
109
  # client.on('Performance.metrics', event => this._emitMetrics(event));
@@ -129,7 +131,7 @@ class Puppeteer::Page
129
131
  EVENT_MAPPINGS = {
130
132
  close: 'Events.Page.Close',
131
133
  # console: 'Events.Page.Console',
132
- # dialog: 'Events.Page.Dialog',
134
+ dialog: 'Events.Page.Dialog',
133
135
  domcontentloaded: 'Events.Page.DOMContentLoaded',
134
136
  # error:
135
137
  frameattached: 'Events.Page.FrameAttached',
@@ -266,7 +268,13 @@ class Puppeteer::Page
266
268
  @frame_manager.main_frame
267
269
  end
268
270
 
269
- attr_reader :keyboard, :touch_screen, :coverage, :accessibility
271
+ attr_reader :touch_screen, :coverage, :accessibility
272
+
273
+ def keyboard(&block)
274
+ @keyboard.instance_eval(&block) unless block.nil?
275
+
276
+ @keyboard
277
+ end
270
278
 
271
279
  def frames
272
280
  @frame_manager.frames
@@ -626,20 +634,17 @@ class Puppeteer::Page
626
634
  # this.emit(Events.Page.Console, message);
627
635
  # }
628
636
 
629
- # _onDialog(event) {
630
- # let dialogType = null;
631
- # if (event.type === 'alert')
632
- # dialogType = Dialog.Type.Alert;
633
- # else if (event.type === 'confirm')
634
- # dialogType = Dialog.Type.Confirm;
635
- # else if (event.type === 'prompt')
636
- # dialogType = Dialog.Type.Prompt;
637
- # else if (event.type === 'beforeunload')
638
- # dialogType = Dialog.Type.BeforeUnload;
639
- # assert(dialogType, 'Unknown javascript dialog type: ' + event.type);
640
- # const dialog = new Dialog(this._client, dialogType, event.message, event.defaultPrompt);
641
- # this.emit(Events.Page.Dialog, dialog);
642
- # }
637
+ private def handle_dialog_opening(event)
638
+ dialog_type = event['type']
639
+ unless %w(alert confirm prompt beforeunload).include?(dialog_type)
640
+ raise ArgumentError.new("Unknown javascript dialog type: #{dialog_type}")
641
+ end
642
+ dialog = Puppeteer::Dialog.new(@client,
643
+ type: dialog_type,
644
+ message: event['message'],
645
+ default_value: event['defaultPrompt'])
646
+ emit_event('Events.Page.Dialog', dialog)
647
+ end
643
648
 
644
649
  # @return [String]
645
650
  def url
@@ -681,12 +686,14 @@ class Puppeteer::Page
681
686
  ).first
682
687
  end
683
688
 
684
- # @param timeout [number|nil]
685
- # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
686
689
  private def wait_for_navigation(timeout: nil, wait_until: nil)
687
690
  main_frame.send(:wait_for_navigation, timeout: timeout, wait_until: wait_until)
688
691
  end
689
692
 
693
+ # @!method async_wait_for_navigation(timeout: nil, wait_until: nil)
694
+ #
695
+ # @param timeout [number|nil]
696
+ # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
690
697
  define_async_method :async_wait_for_navigation
691
698
 
692
699
  private def wait_for_network_manager_event(event_name, predicate:, timeout:)
@@ -725,13 +732,6 @@ class Puppeteer::Page
725
732
  end
726
733
  end
727
734
 
728
- # - Waits until request URL matches
729
- # `wait_for_request(url: 'https://example.com/awesome')`
730
- # - Waits until request matches the given predicate
731
- # `wait_for_request(predicate: -> (req){ req.url.start_with?('https://example.com/search') })`
732
- #
733
- # @param url [String]
734
- # @param predicate [Proc(Puppeteer::Request -> Boolean)]
735
735
  private def wait_for_request(url: nil, predicate: nil, timeout: nil)
736
736
  if !url && !predicate
737
737
  raise ArgumentError.new('url or predicate must be specified')
@@ -752,10 +752,20 @@ class Puppeteer::Page
752
752
  )
753
753
  end
754
754
 
755
- define_async_method :async_wait_for_request
756
-
755
+ # @!method async_wait_for_request(url: nil, predicate: nil, timeout: nil)
756
+ #
757
+ # Waits until request URL matches or request matches the given predicate.
758
+ #
759
+ # Waits until request URL matches
760
+ # wait_for_request(url: 'https://example.com/awesome')
761
+ #
762
+ # Waits until request matches the given predicate
763
+ # wait_for_request(predicate: -> (req){ req.url.start_with?('https://example.com/search') })
764
+ #
757
765
  # @param url [String]
758
766
  # @param predicate [Proc(Puppeteer::Request -> Boolean)]
767
+ define_async_method :async_wait_for_request
768
+
759
769
  private def wait_for_response(url: nil, predicate: nil, timeout: nil)
760
770
  if !url && !predicate
761
771
  raise ArgumentError.new('url or predicate must be specified')
@@ -776,6 +786,10 @@ class Puppeteer::Page
776
786
  )
777
787
  end
778
788
 
789
+ # @!method async_wait_for_response(url: nil, predicate: nil, timeout: nil)
790
+ #
791
+ # @param url [String]
792
+ # @param predicate [Proc(Puppeteer::Request -> Boolean)]
779
793
  define_async_method :async_wait_for_response
780
794
 
781
795
  # @param timeout [number|nil]
@@ -1071,8 +1085,19 @@ class Puppeteer::Page
1071
1085
  define_async_method :async_select
1072
1086
 
1073
1087
  # @param selector [String]
1074
- def tap(selector)
1075
- main_frame.tap(selector)
1088
+ def tap(selector: nil, &block)
1089
+ # resolves double meaning of tap.
1090
+ if selector.nil? && block
1091
+ # Original usage of Object#tap.
1092
+ #
1093
+ # browser.new_page.tap do |page|
1094
+ # ...
1095
+ # end
1096
+ super(&block)
1097
+ else
1098
+ # Puppeteer's Page#tap.
1099
+ main_frame.tap(selector)
1100
+ end
1076
1101
  end
1077
1102
 
1078
1103
  define_async_method :async_tap
@@ -1096,6 +1121,11 @@ class Puppeteer::Page
1096
1121
 
1097
1122
  define_async_method :async_wait_for_selector
1098
1123
 
1124
+ # @param milliseconds [Integer] the number of milliseconds to wait.
1125
+ def wait_for_timeout(milliseconds)
1126
+ main_frame.wait_for_timeout(milliseconds)
1127
+ end
1128
+
1099
1129
  # @param xpath [String]
1100
1130
  # @param visible [Boolean] Wait for element visible (not 'display: none' nor 'visibility: hidden') on true. default to false.
1101
1131
  # @param hidden [Boolean] Wait for element invisible ('display: none' nor 'visibility: hidden') on true. default to false.
@@ -1106,12 +1136,13 @@ class Puppeteer::Page
1106
1136
 
1107
1137
  define_async_method :async_wait_for_xpath
1108
1138
 
1109
- # @param {Function|string} pageFunction
1110
- # @param {!{polling?: string|number, timeout?: number}=} options
1111
- # @param {!Array<*>} args
1112
- # @return {!Promise<!Puppeteer.JSHandle>}
1113
- def wait_for_function(page_function, options = {}, *args)
1114
- main_frame.wait_for_function(page_function, options, *args)
1139
+ # @param page_function [String]
1140
+ # @param args [Integer|Array]
1141
+ # @param polling [String]
1142
+ # @param timeout [Integer]
1143
+ # @return [Puppeteer::JSHandle]
1144
+ def wait_for_function(page_function, args: [], polling: nil, timeout: nil)
1145
+ main_frame.wait_for_function(page_function, args: args, polling: polling, timeout: timeout)
1115
1146
  end
1116
1147
 
1117
1148
  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:
@@ -64,7 +80,18 @@ class Puppeteer::RemoteObject
64
80
 
65
81
  # used in ElementHandle#_box_model
66
82
  def box_model(client)
67
- client.send_message('DOM.getBoxModel', objectId: @object_id)
83
+ result = client.send_message('DOM.getBoxModel', objectId: @object_id)
84
+
85
+ # Firefox returns width/height = 0, content/padding/border/margin = [nil, nil, nil, nil, nil, nil, nil, nil]
86
+ # while Chrome throws Error(Could not compute box model)
87
+ model = result['model']
88
+ if model['width'] == 0 && model['height'] == 0 &&
89
+ %w(content padding border margin).all? { |key| model[key].all?(&:nil?) }
90
+
91
+ debug_puts('Could not compute box model in Firefox.')
92
+ return nil
93
+ end
94
+ result
68
95
  rescue => err
69
96
  debug_puts(err)
70
97
  nil
@@ -106,17 +106,15 @@ class Puppeteer::Request
106
106
  #
107
107
  # Example:
108
108
  #
109
- # ````
110
- # page.on 'request' do |req|
111
- # # Override headers
112
- # headers = req.headers.merge(
113
- # foo: 'bar', # set "foo" header
114
- # origin: nil, # remove "origin" header
115
- # )
116
- # req.continue(headers: headers)
117
- # end
118
- # ```
119
- #`
109
+ # page.on 'request' do |req|
110
+ # # Override headers
111
+ # headers = req.headers.merge(
112
+ # foo: 'bar', # set "foo" header
113
+ # origin: nil, # remove "origin" header
114
+ # )
115
+ # req.continue(headers: headers)
116
+ # end
117
+ #
120
118
  # @param error_code [String|Symbol]
121
119
  def continue(url: nil, method: nil, post_data: nil, headers: nil)
122
120
  # Request interception is not supported for data: urls.
@@ -152,15 +150,13 @@ class Puppeteer::Request
152
150
  #
153
151
  # Example:
154
152
  #
155
- # ```
156
- # page.on 'request' do |req|
157
- # req.respond(
158
- # status: 404,
159
- # content_type: 'text/plain',
160
- # body: 'Not Found!'
161
- # )
162
- # end
163
- # ````
153
+ # page.on 'request' do |req|
154
+ # req.respond(
155
+ # status: 404,
156
+ # content_type: 'text/plain',
157
+ # body: 'Not Found!'
158
+ # )
159
+ # end
164
160
  #
165
161
  # @param status [Integer]
166
162
  # @param headers [Hash<String, String>]
@@ -211,16 +207,14 @@ class Puppeteer::Request
211
207
  #
212
208
  # Example:
213
209
  #
214
- # ````
215
- # page.on 'request' do |req|
216
- # if req.url.include?("porn")
217
- # req.abort
218
- # else
219
- # req.continue
210
+ # page.on 'request' do |req|
211
+ # if req.url.include?("porn")
212
+ # req.abort
213
+ # else
214
+ # req.continue
215
+ # end
220
216
  # end
221
- # end
222
- # ```
223
- #`
217
+ #
224
218
  # @param error_code [String|Symbol]
225
219
  def abort(error_code: :failed)
226
220
  # Request interception is not supported for data: urls.
@@ -1,3 +1,3 @@
1
1
  class Puppeteer
2
- VERSION = '0.0.16'
2
+ VERSION = '0.0.21'
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)
@@ -16,10 +16,14 @@ class Puppeteer::WebSocket
16
16
 
17
17
  def write(data)
18
18
  @socket.write(data)
19
+ rescue Errno::EPIPE
20
+ raise EOFError.new('already closed')
19
21
  end
20
22
 
21
23
  def readpartial(maxlen = 1024)
22
24
  @socket.readpartial(maxlen)
25
+ rescue Errno::ECONNRESET
26
+ raise EOFError.new('closed by remote')
23
27
  end
24
28
  end
25
29
 
@@ -40,6 +44,9 @@ class Puppeteer::WebSocket
40
44
  rescue EOFError
41
45
  # Google Chrome was gone.
42
46
  # We have nothing todo. Just finish polling.
47
+ if @ready_state < STATE_CLOSING
48
+ handle_on_close(reason: 'Going Away', code: 1001)
49
+ end
43
50
  end
44
51
  end
45
52
 
@@ -26,7 +26,8 @@ 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.90.0'
30
30
  spec.add_development_dependency 'rubocop-rspec'
31
+ spec.add_development_dependency 'sinatra'
31
32
  spec.add_development_dependency 'yard'
32
33
  end
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.16
4
+ version: 0.0.21
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-12 00:00:00.000000000 Z
11
+ date: 2020-10-26 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.90.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.90.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: rubocop-rspec
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: sinatra
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: yard
155
169
  requirement: !ruby/object:Gem::Requirement
@@ -179,11 +193,13 @@ files:
179
193
  - ".rspec"
180
194
  - ".rubocop.yml"
181
195
  - ".travis.yml"
196
+ - Dockerfile
182
197
  - Gemfile
183
198
  - README.md
184
199
  - Rakefile
185
200
  - bin/console
186
201
  - bin/setup
202
+ - docker-compose.yml
187
203
  - lib/puppeteer.rb
188
204
  - lib/puppeteer/browser.rb
189
205
  - lib/puppeteer/browser_context.rb
@@ -197,12 +213,14 @@ files:
197
213
  - lib/puppeteer/define_async_method.rb
198
214
  - lib/puppeteer/device.rb
199
215
  - lib/puppeteer/devices.rb
216
+ - lib/puppeteer/dialog.rb
200
217
  - lib/puppeteer/dom_world.rb
201
218
  - lib/puppeteer/element_handle.rb
202
219
  - lib/puppeteer/element_handle/bounding_box.rb
203
220
  - lib/puppeteer/element_handle/box_model.rb
204
221
  - lib/puppeteer/element_handle/point.rb
205
222
  - lib/puppeteer/emulation_manager.rb
223
+ - lib/puppeteer/env.rb
206
224
  - lib/puppeteer/errors.rb
207
225
  - lib/puppeteer/event_callbackable.rb
208
226
  - lib/puppeteer/execution_context.rb
@@ -219,6 +237,7 @@ files:
219
237
  - lib/puppeteer/launcher/browser_options.rb
220
238
  - lib/puppeteer/launcher/chrome.rb
221
239
  - lib/puppeteer/launcher/chrome_arg_options.rb
240
+ - lib/puppeteer/launcher/firefox.rb
222
241
  - lib/puppeteer/launcher/launch_options.rb
223
242
  - lib/puppeteer/lifecycle_watcher.rb
224
243
  - lib/puppeteer/mouse.rb