puppeteer-ruby 0.34.2 → 0.36.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b57897093b83b5817c3fc7e533542cc817cda1299b5cece2a05d9d7850cce8c
4
- data.tar.gz: 39b21af3b69fee33fa3e191bd93f11efde50b20e26e5b24b0ea82a8a2e44bc3d
3
+ metadata.gz: 1d4af926ca9ad39046dcc4ce9507622bf72c3263b747516ee1ba642c02e8e38d
4
+ data.tar.gz: 3eff89952883a47270dee6a9ee7281609dbbe7bac197eada9e6b6dcabbaa1f78
5
5
  SHA512:
6
- metadata.gz: 8cf6ae4da0e3dd3b21090dd792b1611726022665e61c8ee9c0f8de9451445f723192d0b1fc5e8f22a8cfdeb17b62059d97bb4570f47b13789b296f59b1e2e532
7
- data.tar.gz: 83aa119d4469e380fbd7d9fb81240a976d3ee7d465eb7ee3c662c65187c1161c6711df73dab88f47f404ea01dd2ddb3299307be7e0f78c9eb068edb44e4b11df
6
+ metadata.gz: d83085eb31bb6d0d9f125e4c82fe172f46676bc373bd7652b2be430984570f7facff20bd3b1da20dbcb41beca52a740064b9b6d5cb6f51a69bf8f4f97e699947
7
+ data.tar.gz: 141bed0475d5e40a0ddb9ec0cb2a82f44313a14e835a7d5cc271a413dad0c9881658a81f0ec0567d7896a7658539fc131bb5069c1c07c6573f6b633c99a53f8e
data/CHANGELOG.md CHANGED
@@ -1,7 +1,34 @@
1
- ### master [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.34.2...master)]
1
+ ### master [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.36.0...master)]
2
2
 
3
3
  * xxx
4
4
 
5
+ ### 0.36.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.35.1...0.36.0)]
6
+
7
+ New features:
8
+
9
+ * Drag and Drop feature introduced in Puppeteer 10.1
10
+ * `Page#emulateNetworkConditions`, `Page#emulateCPUThrottling`
11
+ * `Page#exposeFunction`
12
+ * Metrics
13
+
14
+ ### 0.35.1 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.35.0...0.35.1)]
15
+
16
+ New features:
17
+
18
+ * Allow Rails users to use this library without `require 'puppeteer'`.
19
+
20
+ ### 0.35.0 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.34.3...0.35.0)]
21
+
22
+ New features:
23
+
24
+ * Add `channel` parameter for Puppeteer.launch. Now `channel: chrome` or `channel: chrome-canary` (chrome-beta, chrome-dev is also available) automatically detects the executablePath of Google Chrome. Windows/macOS users can also use `channel: msedge`.
25
+
26
+ ### 0.34.3 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.34.2...0.34.3)]
27
+
28
+ Bugfix:
29
+
30
+ * Fix wait_for_xxx's timeout error type.
31
+
5
32
  ### 0.34.2 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.34.1...0.34.2)]
6
33
 
7
34
  New features:
data/README.md CHANGED
@@ -20,31 +20,29 @@ gem 'puppeteer-ruby'
20
20
 
21
21
  And then execute:
22
22
 
23
- $ bundle
24
-
25
- Or install it yourself as:
26
-
27
- $ gem install puppeteer-ruby
23
+ $ bundle install
28
24
 
29
25
  ### Capture a site
30
26
 
31
27
  ```ruby
32
- require 'puppeteer'
28
+ require 'puppeteer-ruby'
33
29
 
34
30
  Puppeteer.launch(headless: false) do |browser|
35
- page = browser.pages.first || browser.new_page
31
+ page = browser.new_page
36
32
  page.goto("https://github.com/YusukeIwaki")
37
33
  page.screenshot(path: "YusukeIwaki.png")
38
34
  end
39
35
  ```
40
36
 
37
+ NOTE: `require 'puppeteer-ruby'` is not necessary in Rails.
38
+
41
39
  ### Simple scraping
42
40
 
43
41
  ```ruby
44
- require 'puppeteer'
42
+ require 'puppeteer-ruby'
45
43
 
46
44
  Puppeteer.launch(headless: false, slow_mo: 50, args: ['--guest', '--window-size=1280,800']) do |browser|
47
- page = browser.pages.first || browser.new_page
45
+ page = browser.new_page
48
46
  page.viewport = Puppeteer::Viewport.new(width: 1280, height: 800)
49
47
  page.goto("https://github.com/", wait_until: 'domcontentloaded')
50
48
 
@@ -69,10 +67,10 @@ end
69
67
  ### Evaluate JavaScript
70
68
 
71
69
  ```ruby
72
- require 'puppeteer'
70
+ require 'puppeteer-ruby'
73
71
 
74
72
  Puppeteer.launch do |browser|
75
- page = browser.pages.last || browser.new_page
73
+ page = browser.new_page
76
74
  page.goto 'https://github.com/YusukeIwaki'
77
75
 
78
76
  # Get the "viewport" of the page, as reported by the page.
data/docs/api_coverage.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # API coverages
2
- - Puppeteer version: v10.0.0
3
- - puppeteer-ruby version: 0.34.1
2
+ - Puppeteer version: v10.2.0
3
+ - puppeteer-ruby version: 0.36.0
4
4
 
5
5
  ## Puppeteer
6
6
 
@@ -13,7 +13,7 @@
13
13
  * ~~errors~~
14
14
  * executablePath => `#executable_path`
15
15
  * launch
16
- * ~~networkConditions~~
16
+ * networkConditions => `#network_conditions`
17
17
  * product
18
18
  * ~~registerCustomQueryHandler~~
19
19
  * ~~unregisterCustomQueryHandler~~
@@ -78,18 +78,20 @@
78
78
  * content
79
79
  * cookies
80
80
  * coverage
81
+ * createPDFStream => `#create_pdf_stream`
81
82
  * deleteCookie => `#delete_cookie`
82
83
  * emulate
84
+ * emulateCPUThrottling => `#emulate_cpu_throttling`
83
85
  * emulateIdleState => `#emulate_idle_state`
84
86
  * emulateMediaFeatures => `#emulate_media_features`
85
87
  * emulateMediaType => `#emulate_media_type`
86
- * ~~emulateNetworkConditions~~
88
+ * emulateNetworkConditions => `#emulate_network_conditions`
87
89
  * emulateTimezone => `#emulate_timezone`
88
90
  * emulateVisionDeficiency => `#emulate_vision_deficiency`
89
91
  * evaluate
90
92
  * evaluateHandle => `#evaluate_handle`
91
93
  * evaluateOnNewDocument => `#evaluate_on_new_document`
92
- * ~~exposeFunction~~
94
+ * exposeFunction => `#expose_function`
93
95
  * focus
94
96
  * frames
95
97
  * goBack => `#go_back`
@@ -97,10 +99,11 @@
97
99
  * goto
98
100
  * hover
99
101
  * isClosed => `#closed?`
102
+ * isDragInterceptionEnabled => `#drag_interception_enabled?`
100
103
  * isJavaScriptEnabled => `#javascript_enabled?`
101
104
  * keyboard
102
105
  * mainFrame => `#main_frame`
103
- * ~~metrics~~
106
+ * metrics
104
107
  * mouse
105
108
  * pdf
106
109
  * queryObjects => `#query_objects`
@@ -113,6 +116,7 @@
113
116
  * setCookie => `#set_cookie`
114
117
  * setDefaultNavigationTimeout => `#default_navigation_timeout=`
115
118
  * setDefaultTimeout => `#default_timeout=`
119
+ * ~~setDragInterception~~
116
120
  * setExtraHTTPHeaders => `#extra_http_headers=`
117
121
  * setGeolocation => `#geolocation=`
118
122
  * setJavaScriptEnabled => `#javascript_enabled=`
@@ -162,6 +166,11 @@
162
166
 
163
167
  * click
164
168
  * down
169
+ * drag
170
+ * dragAndDrop => `#drag_and_drop`
171
+ * dragEnter => `#drag_enter`
172
+ * dragOver => `#drag_over`
173
+ * drop
165
174
  * move
166
175
  * up
167
176
  * wheel
@@ -260,8 +269,14 @@
260
269
  * boundingBox => `#bounding_box`
261
270
  * boxModel => `#box_model`
262
271
  * click
272
+ * clickablePoint => `#clickable_point`
263
273
  * contentFrame => `#content_frame`
264
274
  * dispose
275
+ * drag
276
+ * dragAndDrop => `#drag_and_drop`
277
+ * dragEnter => `#drag_enter`
278
+ * dragOver => `#drag_over`
279
+ * drop
265
280
  * evaluate
266
281
  * evaluateHandle => `#evaluate_handle`
267
282
  * executionContext => `#execution_context`
@@ -282,8 +297,12 @@
282
297
  ## ~~HTTPRequest~~
283
298
 
284
299
  * ~~abort~~
300
+ * ~~abortErrorReason~~
285
301
  * ~~continue~~
302
+ * ~~continueRequestOverrides~~
303
+ * ~~enqueueInterceptAction~~
286
304
  * ~~failure~~
305
+ * ~~finalizeInterceptions~~
287
306
  * ~~frame~~
288
307
  * ~~headers~~
289
308
  * ~~isNavigationRequest~~
@@ -293,6 +312,7 @@
293
312
  * ~~resourceType~~
294
313
  * ~~respond~~
295
314
  * ~~response~~
315
+ * ~~responseForRequest~~
296
316
  * ~~url~~
297
317
 
298
318
  ## ~~HTTPResponse~~
@@ -0,0 +1,2 @@
1
+ # just an alias.
2
+ require 'puppeteer'
data/lib/puppeteer.rb CHANGED
@@ -5,7 +5,6 @@ module Puppeteer; end
5
5
  require 'puppeteer/env'
6
6
 
7
7
  # Custom data types.
8
- require 'puppeteer/device'
9
8
  require 'puppeteer/events'
10
9
  require 'puppeteer/errors'
11
10
  require 'puppeteer/geolocation'
@@ -44,6 +43,7 @@ require 'puppeteer/keyboard'
44
43
  require 'puppeteer/launcher'
45
44
  require 'puppeteer/lifecycle_watcher'
46
45
  require 'puppeteer/mouse'
46
+ require 'puppeteer/network_conditions'
47
47
  require 'puppeteer/network_manager'
48
48
  require 'puppeteer/page'
49
49
  require 'puppeteer/protocol_stream_reader'
@@ -3,11 +3,11 @@ module Puppeteer::ConcurrentRubyUtils
3
3
  module ConcurrentPromisesFutureExtension
4
4
  # Extension for describing 2 concurrent tasks smartly.
5
5
  #
6
- # page.async_for_navigation.with_waiting_for_complete do
6
+ # page.async_wait_for_navigation.with_waiting_for_complete do
7
7
  # page.click('#submit')
8
8
  # end
9
9
  def with_waiting_for_complete(&block)
10
- async_block_call = Concurrent::Promises.future do
10
+ async_block_call = Concurrent::Promises.delay do
11
11
  block.call
12
12
  rescue => err
13
13
  Logger.new($stderr).warn(err)
@@ -40,7 +40,7 @@ module Puppeteer::DefineAsyncMethod
40
40
  end
41
41
  end
42
42
 
43
- async_block_call = Concurrent::Promises.future do
43
+ async_block_call = Concurrent::Promises.delay do
44
44
  block.call
45
45
  rescue => err
46
46
  Logger.new($stderr).warn(err)
@@ -1,3 +1,5 @@
1
+ require_relative './device'
2
+
1
3
  Puppeteer::DEVICES = Hash[
2
4
  [
3
5
  {
@@ -147,6 +147,47 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
147
147
 
148
148
  define_async_method :async_click
149
149
 
150
+ class DragInterceptionNotEnabledError < StandardError
151
+ def initialize
152
+ super('Drag Interception is not enabled!')
153
+ end
154
+ end
155
+
156
+ def drag(x:, y:)
157
+ unless @page.drag_interception_enabled?
158
+ raise DragInterceptionNotEnabledError.new
159
+ end
160
+ scroll_into_view_if_needed
161
+ start = clickable_point
162
+ @page.mouse.drag(start, Point.new(x: x, y: y))
163
+ end
164
+
165
+ def drag_enter(data)
166
+ scroll_into_view_if_needed
167
+ target = clickable_point
168
+ @page.mouse.drag_enter(target, data)
169
+ end
170
+
171
+ def drag_over(data)
172
+ scroll_into_view_if_needed
173
+ target = clickable_point
174
+ @page.mouse.drag_over(target, data)
175
+ end
176
+
177
+ def drop(data)
178
+ scroll_into_view_if_needed
179
+ target = clickable_point
180
+ @page.mouse.drop(target, data)
181
+ end
182
+
183
+ # @param target [ElementHandle]
184
+ def drag_and_drop(target, delay: nil)
185
+ scroll_into_view_if_needed
186
+ start_point = clickable_point
187
+ target_point = target.clickable_point
188
+ @page.mouse.drag_and_drop(start_point, target_point, delay: delay)
189
+ end
190
+
150
191
  # @return [Array<String>]
151
192
  def select(*values)
152
193
  if nonstring = values.find { |value| !value.is_a?(String) }
@@ -1,4 +1,3 @@
1
- require_relative './launcher/base'
2
1
  require_relative './launcher/browser_options'
3
2
  require_relative './launcher/chrome'
4
3
  require_relative './launcher/chrome_arg_options'
@@ -2,7 +2,13 @@ require 'tmpdir'
2
2
 
3
3
  # https://github.com/puppeteer/puppeteer/blob/main/src/node/Launcher.ts
4
4
  module Puppeteer::Launcher
5
- class Chrome < Base
5
+ class Chrome
6
+ def initialize(project_root:, preferred_revision:, is_puppeteer_core:)
7
+ @project_root = project_root
8
+ @preferred_revision = preferred_revision
9
+ @is_puppeteer_core = is_puppeteer_core
10
+ end
11
+
6
12
  # @param {!(Launcher.LaunchOptions & Launcher.ChromeArgOptions & Launcher.BrowserOptions)=} options
7
13
  # @return {!Promise<!Browser>}
8
14
  def launch(options = {})
@@ -38,7 +44,12 @@ module Puppeteer::Launcher
38
44
  chrome_arguments << "--user-data-dir=#{temporary_user_data_dir}"
39
45
  end
40
46
 
41
- chrome_executable = @launch_options.executable_path || resolve_executable_path
47
+ chrome_executable =
48
+ if @launch_options.channel
49
+ executable_path_for_channel(@launch_options.channel.to_s)
50
+ else
51
+ @launch_options.executable_path || executable_path_for_channel('chrome')
52
+ end
42
53
  use_pipe = chrome_arguments.include?('--remote-debugging-pipe')
43
54
  runner = Puppeteer::BrowserRunner.new(chrome_executable, chrome_arguments, temporary_user_data_dir)
44
55
  runner.start(
@@ -201,8 +212,57 @@ module Puppeteer::Launcher
201
212
  end
202
213
 
203
214
  # @return {string}
204
- def executable_path
205
- resolve_executable_path
215
+ def executable_path(channel: nil)
216
+ if channel
217
+ executable_path_for_channel(channel.to_s)
218
+ else
219
+ executable_path_for_channel('chrome')
220
+ end
221
+ end
222
+
223
+ CHROMIUM_CHANNELS = {
224
+ windows: {
225
+ 'chrome' => "#{ENV['PROGRAMFILES']}\\Google\\Chrome\\Application\\chrome.exe",
226
+ 'chrome-beta' => "#{ENV['PROGRAMFILES']}\\Google\\Chrome Beta\\Application\\chrome.exe",
227
+ 'chrome-canary' => "#{ENV['PROGRAMFILES']}\\Google\\Chrome SxS\\Application\\chrome.exe",
228
+ 'chrome-dev' => "#{ENV['PROGRAMFILES']}\\Google\\Chrome Dev\\Application\\chrome.exe",
229
+ 'msedge' => "#{ENV['PROGRAMFILES(X86)']}\\Microsoft\\Edge\\Application\\msedge.exe",
230
+ },
231
+ darwin: {
232
+ 'chrome' => '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
233
+ 'chrome-beta' => '/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta',
234
+ 'chrome-canary' => '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
235
+ 'chrome-dev' => '/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev',
236
+ 'msedge' => '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
237
+ },
238
+ linux: {
239
+ 'chrome' => '/opt/google/chrome/chrome',
240
+ 'chrome-beta' => '/opt/google/chrome-beta/chrome',
241
+ 'chrome-dev' => '/opt/google/chrome-unstable/chrome',
242
+ },
243
+ }.freeze
244
+
245
+ # @param channel [String]
246
+ private def executable_path_for_channel(channel)
247
+ chrome_path_map =
248
+ if Puppeteer.env.windows?
249
+ CHROMIUM_CHANNELS[:windows]
250
+ elsif Puppeteer.env.darwin?
251
+ CHROMIUM_CHANNELS[:darwin]
252
+ else
253
+ CHROMIUM_CHANNELS[:linux]
254
+ end
255
+
256
+ chrome_path = chrome_path_map[channel]
257
+ unless chrome_path
258
+ raise ArgumentError.new("Invalid channel: '#{channel}'. Allowed channel is #{chrome_path_map.keys}")
259
+ end
260
+
261
+ unless File.exist?(chrome_path)
262
+ raise "#{channel} is not installed on this system.\nExpected path: #{chrome_path}"
263
+ end
264
+
265
+ chrome_path
206
266
  end
207
267
 
208
268
  def product
@@ -2,7 +2,13 @@ require 'tmpdir'
2
2
 
3
3
  # https://github.com/puppeteer/puppeteer/blob/main/src/node/Launcher.ts
4
4
  module Puppeteer::Launcher
5
- class Firefox < Base
5
+ class Firefox
6
+ def initialize(project_root:, preferred_revision:, is_puppeteer_core:)
7
+ @project_root = project_root
8
+ @preferred_revision = preferred_revision
9
+ @is_puppeteer_core = is_puppeteer_core
10
+ end
11
+
6
12
  # @param {!(Launcher.LaunchOptions & Launcher.ChromeArgOptions & Launcher.BrowserOptions)=} options
7
13
  # @return {!Promise<!Browser>}
8
14
  def launch(options = {})
@@ -32,7 +38,12 @@ module Puppeteer::Launcher
32
38
  firefox_arguments << temporary_user_data_dir
33
39
  end
34
40
 
35
- firefox_executable = @launch_options.executable_path || resolve_executable_path
41
+ firefox_executable =
42
+ if @launch_options.channel
43
+ executable_path_for_channel(@launch_options.channel.to_s)
44
+ else
45
+ @launch_options.executable_path || executable_path_for_channel('nightly')
46
+ end
36
47
  runner = Puppeteer::BrowserRunner.new(firefox_executable, firefox_arguments, temporary_user_data_dir)
37
48
  runner.start(
38
49
  handle_SIGHUP: @launch_options.handle_SIGHUP?,
@@ -123,8 +134,41 @@ module Puppeteer::Launcher
123
134
  end
124
135
 
125
136
  # @return {string}
126
- def executable_path
127
- resolve_executable_path
137
+ def executable_path(channel: nil)
138
+ if channel
139
+ executable_path_for_channel(channel.to_s)
140
+ else
141
+ executable_path_for_channel('firefox')
142
+ end
143
+ end
144
+
145
+ FIREFOX_EXECUTABLE_PATHS = {
146
+ windows: "#{ENV['PROGRAMFILES']}\\Firefox Nightly\\firefox.exe",
147
+ darwin: '/Applications/Firefox Nightly.app/Contents/MacOS/firefox',
148
+ linux: '/usr/bin/firefox',
149
+ }.freeze
150
+
151
+ # @param channel [String]
152
+ private def executable_path_for_channel(channel)
153
+ allowed = ['firefox', 'firefox-nightly', 'nightly']
154
+ unless allowed.include?(channel)
155
+ raise ArgumentError.new("Invalid channel: '#{channel}'. Allowed channel is #{allowed}")
156
+ end
157
+
158
+ firefox_path =
159
+ if Puppeteer.env.windows?
160
+ FIREFOX_EXECUTABLE_PATHS[:windows]
161
+ elsif Puppeteer.env.darwin?
162
+ FIREFOX_EXECUTABLE_PATHS[:darwin]
163
+ else
164
+ FIREFOX_EXECUTABLE_PATHS[:linux]
165
+ end
166
+
167
+ unless File.exist?(firefox_path)
168
+ raise "Nightly version of Firefox is not installed on this system.\nExpected path: #{firefox_path}"
169
+ end
170
+
171
+ firefox_path
128
172
  end
129
173
 
130
174
  def product
@@ -32,6 +32,7 @@ module Puppeteer::Launcher
32
32
  # @property {!Object<string, string | undefined>=} env
33
33
  # @property {boolean=} pipe
34
34
  def initialize(options)
35
+ @channel = options[:channel]
35
36
  @executable_path = options[:executable_path]
36
37
  @ignore_default_args = options[:ignore_default_args] || false
37
38
  @handle_SIGINT = options[:handle_SIGINT] || true
@@ -43,7 +44,7 @@ module Puppeteer::Launcher
43
44
  @pipe = options[:pipe] || false
44
45
  end
45
46
 
46
- attr_reader :executable_path, :ignore_default_args, :timeout, :env
47
+ attr_reader :channel, :executable_path, :ignore_default_args, :timeout, :env
47
48
 
48
49
  def handle_SIGINT?
49
50
  @handle_SIGINT
@@ -94,6 +94,8 @@ class Puppeteer::Mouse
94
94
  )
95
95
  end
96
96
 
97
+ define_async_method :async_up
98
+
97
99
  # Dispatches a `mousewheel` event.
98
100
  #
99
101
  # @param delta_x [Integer]
@@ -110,5 +112,56 @@ class Puppeteer::Mouse
110
112
  )
111
113
  end
112
114
 
113
- define_async_method :async_up
115
+ def drag(start, target)
116
+ promise = resolvable_future do |f|
117
+ @client.once('Input.dragIntercepted') do |event|
118
+ f.fulfill(event['data'])
119
+ end
120
+ end
121
+ move(start.x, start.y)
122
+ down
123
+ move(target.x, target.y)
124
+ promise.value!
125
+ end
126
+
127
+ def drag_enter(target, data)
128
+ @client.send_message('Input.dispatchDragEvent',
129
+ type: 'dragEnter',
130
+ x: target.x,
131
+ y: target.y,
132
+ modifiers: @keyboard.modifiers,
133
+ data: data,
134
+ )
135
+ end
136
+
137
+ def drag_over(target, data)
138
+ @client.send_message('Input.dispatchDragEvent',
139
+ type: 'dragOver',
140
+ x: target.x,
141
+ y: target.y,
142
+ modifiers: @keyboard.modifiers,
143
+ data: data,
144
+ )
145
+ end
146
+
147
+ def drop(target, data)
148
+ @client.send_message('Input.dispatchDragEvent',
149
+ type: 'drop',
150
+ x: target.x,
151
+ y: target.y,
152
+ modifiers: @keyboard.modifiers,
153
+ data: data,
154
+ )
155
+ end
156
+
157
+ def drag_and_drop(start, target, delay: nil)
158
+ data = drag(start, target)
159
+ drag_enter(target, data)
160
+ drag_over(target, data)
161
+ if delay
162
+ sleep(delay / 1000.0)
163
+ end
164
+ drop(target, data)
165
+ up
166
+ end
114
167
  end
@@ -0,0 +1,12 @@
1
+ class Puppeteer::NetworkCondition
2
+ # @param download [Number] Download speed (bytes/s)
3
+ # @param upload [Number] Upload speed (bytes/s)
4
+ # @param latency [Number] Latency (ms)
5
+ def initialize(download:, upload:, latency:)
6
+ @download = download
7
+ @upload = upload
8
+ @latency = latency
9
+ end
10
+
11
+ attr_reader :download, :upload, :latency
12
+ end
@@ -0,0 +1,24 @@
1
+ require_relative './network_condition'
2
+
3
+ Puppeteer::NETWORK_CONDITIONS = {
4
+ 'Slow 3G' => Puppeteer::NetworkCondition.new(
5
+ download: ((500 * 1000) / 8) * 0.8,
6
+ upload: ((500 * 1000) / 8) * 0.8,
7
+ latency: 400 * 5,
8
+ ),
9
+ 'Fast 3G' => Puppeteer::NetworkCondition.new(
10
+ download: ((1.6 * 1000 * 1000) / 8) * 0.9,
11
+ upload: ((750 * 1000) / 8) * 0.9,
12
+ latency: 150 * 3.75,
13
+ ),
14
+ }
15
+
16
+ module Puppeteer::NetworkConditions
17
+ module_function def slow_3g
18
+ Puppeteer::NETWORK_CONDITIONS['Slow 3G']
19
+ end
20
+
21
+ module_function def fast_3g
22
+ Puppeteer::NETWORK_CONDITIONS['Fast 3G']
23
+ end
24
+ end
@@ -13,6 +13,46 @@ class Puppeteer::NetworkManager
13
13
  attr_reader :username, :password
14
14
  end
15
15
 
16
+ class InternalNetworkCondition
17
+ attr_writer :offline, :upload, :download, :latency
18
+
19
+ def initialize(client)
20
+ @client = client
21
+ @offline = false
22
+ @upload = -1
23
+ @download = -1
24
+ @latency = 0
25
+ end
26
+
27
+ def offline_mode=(value)
28
+ return if @offline == value
29
+ @offline = value
30
+ update_network_conditions
31
+ end
32
+
33
+ def network_condition=(network_condition)
34
+ if network_condition
35
+ @upload = network_condition.upload
36
+ @download = network_condition.download
37
+ @latency = network_condition.latency
38
+ else
39
+ @upload = -1
40
+ @download = -1
41
+ @latency = 0
42
+ end
43
+ update_network_conditions
44
+ end
45
+
46
+ private def update_network_conditions
47
+ @client.send_message('Network.emulateNetworkConditions',
48
+ offline: @offline,
49
+ latency: @latency,
50
+ downloadThroughput: @download,
51
+ uploadThroughput: @upload,
52
+ )
53
+ end
54
+ end
55
+
16
56
  # @param {!Puppeteer.CDPSession} client
17
57
  # @param {boolean} ignoreHTTPSErrors
18
58
  # @param {!Puppeteer.FrameManager} frameManager
@@ -29,13 +69,12 @@ class Puppeteer::NetworkManager
29
69
 
30
70
  @extra_http_headers = {}
31
71
 
32
- @offline = false
33
-
34
72
  @attempted_authentications = Set.new
35
73
  @user_request_interception_enabled = false
36
74
  @protocol_request_interception_enabled = false
37
75
  @user_cache_disabled = false
38
76
  @request_id_to_interception_id = {}
77
+ @internal_network_condition = InternalNetworkCondition.new(@client)
39
78
 
40
79
  @client.on_event('Fetch.requestPaused') do |event|
41
80
  handle_request_paused(event)
@@ -94,15 +133,12 @@ class Puppeteer::NetworkManager
94
133
 
95
134
  # @param value [TrueClass|FalseClass]
96
135
  def offline_mode=(value)
97
- return if @offline == value
98
- @offline = value
99
- @client.send_message('Network.emulateNetworkConditions',
100
- offline: @offline,
101
- # values of 0 remove any active throttling. crbug.com/456324#c9
102
- latency: 0,
103
- downloadThroughput: -1,
104
- uploadThroughput: -1,
105
- )
136
+ @internal_network_condition.offline_mode=(value)
137
+ end
138
+
139
+ # @param network_condition [Puppeteer::NetworkCondition|nil]
140
+ def emulate_network_conditions(network_condition)
141
+ @internal_network_condition.network_condition = network_condition
106
142
  end
107
143
 
108
144
  # @param user_agent [String]
@@ -2,11 +2,13 @@ require 'base64'
2
2
  require 'json'
3
3
  require "stringio"
4
4
 
5
+ require_relative './page/metrics'
5
6
  require_relative './page/pdf_options'
6
7
  require_relative './page/screenshot_options'
7
8
  require_relative './page/screenshot_task_queue'
8
9
 
9
10
  class Puppeteer::Page
11
+ include Puppeteer::DebugPrint
10
12
  include Puppeteer::EventCallbackable
11
13
  include Puppeteer::IfPresent
12
14
  using Puppeteer::DefineAsyncMethod
@@ -46,6 +48,8 @@ class Puppeteer::Page
46
48
  @screenshot_task_queue = ScreenshotTaskQueue.new
47
49
 
48
50
  @workers = {}
51
+ @user_drag_interception_enabled = false
52
+
49
53
  @client.on_event('Target.attachedToTarget') do |event|
50
54
  if event['targetInfo']['type'] != 'worker'
51
55
  # If we don't detach from service workers, they will never die.
@@ -102,7 +106,9 @@ class Puppeteer::Page
102
106
  @client.on('Runtime.consoleAPICalled') do |event|
103
107
  handle_console_api(event)
104
108
  end
105
- # client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));
109
+ @client.on('Runtime.bindingCalled') do |event|
110
+ handle_binding_called(event)
111
+ end
106
112
  @client.on_event('Page.javascriptDialogOpening') do |event|
107
113
  handle_dialog_opening(event)
108
114
  end
@@ -112,7 +118,9 @@ class Puppeteer::Page
112
118
  @client.on_event('Inspector.targetCrashed') do |event|
113
119
  handle_target_crashed
114
120
  end
115
- # client.on('Performance.metrics', event => this._emitMetrics(event));
121
+ @client.on_event('Performance.metrics') do |event|
122
+ emit_event(PageEmittedEvents::Metrics, MetricsEvent.new(event))
123
+ end
116
124
  @client.on_event('Log.entryAdded') do |event|
117
125
  handle_log_entry_added(event)
118
126
  end
@@ -134,6 +142,11 @@ class Puppeteer::Page
134
142
  )
135
143
  end
136
144
 
145
+ def drag_interception_enabled?
146
+ @user_drag_interception_enabled
147
+ end
148
+ alias_method :drag_interception_enabled, :drag_interception_enabled?
149
+
137
150
  # @param event_name [Symbol]
138
151
  def on(event_name, &block)
139
152
  unless PageEmittedEvents.values.include?(event_name.to_s)
@@ -266,10 +279,20 @@ class Puppeteer::Page
266
279
  @frame_manager.network_manager.request_interception = value
267
280
  end
268
281
 
282
+ def drag_interception_enabled=(enabled)
283
+ @user_drag_interception_enabled = enabled
284
+ @client.send_message('Input.setInterceptDrags', enabled: enabled)
285
+ end
286
+
269
287
  def offline_mode=(enabled)
270
288
  @frame_manager.network_manager.offline_mode = enabled
271
289
  end
272
290
 
291
+ # @param network_condition [Puppeteer::NetworkCondition|nil]
292
+ def emulate_network_conditions(network_condition)
293
+ @frame_manager.network_manager.emulate_network_conditions(network_condition)
294
+ end
295
+
273
296
  # @param {number} timeout
274
297
  def default_navigation_timeout=(timeout)
275
298
  @timeout_settings.default_navigation_timeout = timeout
@@ -392,6 +415,51 @@ class Puppeteer::Page
392
415
  main_frame.add_style_tag(url: url, path: path, content: content)
393
416
  end
394
417
 
418
+ # @param name [String]
419
+ # @param puppeteer_function [Proc]
420
+ def expose_function(name, puppeteer_function)
421
+ if @page_bindings[name]
422
+ raise ArgumentError.new("Failed to add page binding with name `#{name}` already exists!")
423
+ end
424
+ @page_bindings[name] = puppeteer_function
425
+
426
+ add_page_binding = <<~JAVASCRIPT
427
+ function (type, bindingName) {
428
+ /* Cast window to any here as we're about to add properties to it
429
+ * via win[bindingName] which TypeScript doesn't like.
430
+ */
431
+ const win = window;
432
+ const binding = win[bindingName];
433
+
434
+ win[bindingName] = (...args) => {
435
+ const me = window[bindingName];
436
+ let callbacks = me.callbacks;
437
+ if (!callbacks) {
438
+ callbacks = new Map();
439
+ me.callbacks = callbacks;
440
+ }
441
+ const seq = (me.lastSeq || 0) + 1;
442
+ me.lastSeq = seq;
443
+ const promise = new Promise((resolve, reject) =>
444
+ callbacks.set(seq, { resolve, reject })
445
+ );
446
+ binding(JSON.stringify({ type, name: bindingName, seq, args }));
447
+ return promise;
448
+ };
449
+ }
450
+ JAVASCRIPT
451
+
452
+ source = JavaScriptFunction.new(add_page_binding, ['exposedFun', name]).source
453
+ @client.send_message('Runtime.addBinding', name: name)
454
+ @client.send_message('Page.addScriptToEvaluateOnNewDocument', source: source)
455
+
456
+ promises = @frame_manager.frames.map do |frame|
457
+ frame.async_evaluate("() => #{source}")
458
+ end
459
+ await_all(*promises)
460
+
461
+ nil
462
+ end
395
463
  # /**
396
464
  # * @param {string} name
397
465
  # * @param {Function} puppeteerFunction
@@ -440,36 +508,10 @@ class Puppeteer::Page
440
508
  @frame_manager.network_manager.user_agent = user_agent
441
509
  end
442
510
 
443
- # /**
444
- # * @return {!Promise<!Metrics>}
445
- # */
446
- # async metrics() {
447
- # const response = await this._client.send('Performance.getMetrics');
448
- # return this._buildMetricsObject(response.metrics);
449
- # }
450
-
451
- # /**
452
- # * @param {!Protocol.Performance.metricsPayload} event
453
- # */
454
- # _emitMetrics(event) {
455
- # this.emit(PageEmittedEvents::Metrics, {
456
- # title: event.title,
457
- # metrics: this._buildMetricsObject(event.metrics)
458
- # });
459
- # }
460
-
461
- # /**
462
- # * @param {?Array<!Protocol.Performance.Metric>} metrics
463
- # * @return {!Metrics}
464
- # */
465
- # _buildMetricsObject(metrics) {
466
- # const result = {};
467
- # for (const metric of metrics || []) {
468
- # if (supportedMetrics.has(metric.name))
469
- # result[metric.name] = metric.value;
470
- # }
471
- # return result;
472
- # }
511
+ def metrics
512
+ response = @client.send_message('Performance.getMetrics')
513
+ Metrics.new(response['metrics'])
514
+ end
473
515
 
474
516
  class PageError < StandardError ; end
475
517
 
@@ -506,56 +548,51 @@ class Puppeteer::Page
506
548
  add_console_message(event['type'], values, event['stackTrace'])
507
549
  end
508
550
 
509
- # /**
510
- # * @param {!Protocol.Runtime.bindingCalledPayload} event
511
- # */
512
- # async _onBindingCalled(event) {
513
- # const {name, seq, args} = JSON.parse(event.payload);
514
- # let expression = null;
515
- # try {
516
- # const result = await this._pageBindings.get(name)(...args);
517
- # expression = helper.evaluationString(deliverResult, name, seq, result);
518
- # } catch (error) {
519
- # if (error instanceof Error)
520
- # expression = helper.evaluationString(deliverError, name, seq, error.message, error.stack);
521
- # else
522
- # expression = helper.evaluationString(deliverErrorValue, name, seq, error);
523
- # }
524
- # this._client.send('Runtime.evaluate', { expression, contextId: event.executionContextId }).catch(debugError);
525
-
526
- # /**
527
- # * @param {string} name
528
- # * @param {number} seq
529
- # * @param {*} result
530
- # */
531
- # function deliverResult(name, seq, result) {
532
- # window[name]['callbacks'].get(seq).resolve(result);
533
- # window[name]['callbacks'].delete(seq);
534
- # }
551
+ def handle_binding_called(event)
552
+ execution_context_id = event['executionContextId']
553
+ payload =
554
+ begin
555
+ JSON.parse(event['payload'])
556
+ rescue
557
+ # The binding was either called by something in the page or it was
558
+ # called before our wrapper was initialized.
559
+ return
560
+ end
561
+ name = payload['name']
562
+ seq = payload['seq']
563
+ args = payload['args']
535
564
 
536
- # /**
537
- # * @param {string} name
538
- # * @param {number} seq
539
- # * @param {string} message
540
- # * @param {string} stack
541
- # */
542
- # function deliverError(name, seq, message, stack) {
543
- # const error = new Error(message);
544
- # error.stack = stack;
545
- # window[name]['callbacks'].get(seq).reject(error);
546
- # window[name]['callbacks'].delete(seq);
547
- # }
565
+ if payload['type'] != 'exposedFun' || !@page_bindings[name]
566
+ return
567
+ end
548
568
 
549
- # /**
550
- # * @param {string} name
551
- # * @param {number} seq
552
- # * @param {*} value
553
- # */
554
- # function deliverErrorValue(name, seq, value) {
555
- # window[name]['callbacks'].get(seq).reject(value);
556
- # window[name]['callbacks'].delete(seq);
557
- # }
558
- # }
569
+ expression =
570
+ begin
571
+ result = @page_bindings[name].call(*args)
572
+
573
+ deliver_result = <<~JAVASCRIPT
574
+ function (name, seq, result) {
575
+ window[name].callbacks.get(seq).resolve(result);
576
+ window[name].callbacks.delete(seq);
577
+ }
578
+ JAVASCRIPT
579
+
580
+ JavaScriptFunction.new(deliver_result, [name, seq, result]).source
581
+ rescue => err
582
+ deliver_error = <<~JAVASCRIPT
583
+ function (name, seq, message) {
584
+ const error = new Error(message);
585
+ window[name].callbacks.get(seq).reject(error);
586
+ window[name].callbacks.delete(seq);
587
+ }
588
+ JAVASCRIPT
589
+ JavaScriptFunction.new(deliver_error, [name, seq, err.message]).source
590
+ end
591
+
592
+ @client.async_send_message('Runtime.evaluate', expression: expression, contextId: execution_context_id).rescue do |error|
593
+ debug_puts(error)
594
+ end
595
+ end
559
596
 
560
597
  private def add_console_message(type, args, stack_trace)
561
598
  text_tokens = args.map { |arg| arg.remote_object.value }
@@ -631,10 +668,9 @@ class Puppeteer::Page
631
668
  # @param wait_until [string|nil] 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
632
669
  # @return [Puppeteer::Response]
633
670
  def reload(timeout: nil, wait_until: nil)
634
- await_all(
635
- async_wait_for_navigation(timeout: timeout, wait_until: wait_until),
636
- @client.async_send_message('Page.reload'),
637
- ).first
671
+ wait_for_navigation(timeout: timeout, wait_until: wait_until) do
672
+ @client.send_message('Page.reload')
673
+ end
638
674
  end
639
675
 
640
676
  def wait_for_navigation(timeout: nil, wait_until: nil)
@@ -760,10 +796,9 @@ class Puppeteer::Page
760
796
  entries = history['entries']
761
797
  index = history['currentIndex'] + delta
762
798
  if_present(entries[index]) do |entry|
763
- await_all(
764
- async_wait_for_navigation(timeout: timeout, wait_until: wait_until),
765
- @client.async_send_message('Page.navigateToHistoryEntry', entryId: entry['id']),
766
- )
799
+ wait_for_navigation(timeout: timeout, wait_until: wait_until) do
800
+ @client.send_message('Page.navigateToHistoryEntry', entryId: entry['id'])
801
+ end
767
802
  end
768
803
  end
769
804
 
@@ -799,6 +834,15 @@ class Puppeteer::Page
799
834
  @client.send_message('Emulation.setEmulatedMedia', media: media_type_str)
800
835
  end
801
836
 
837
+ # @param factor [Number|nil] Factor at which the CPU will be throttled (2x, 2.5x. 3x, ...). Passing `nil` disables cpu throttling.
838
+ def emulate_cpu_throttling(factor)
839
+ if factor.nil? || factor >= 1
840
+ @client.send_message('Emulation.setCPUThrottlingRate', rate: factor || 1)
841
+ else
842
+ raise ArgumentError.new('Throttling rate should be greater or equal to 1')
843
+ end
844
+ end
845
+
802
846
  # @param features [Array]
803
847
  def emulate_media_features(features)
804
848
  if features.nil?
@@ -0,0 +1,49 @@
1
+ class Puppeteer::Page
2
+ class Metrics
3
+ SUPPORTED_KEYS = Set.new([
4
+ 'Timestamp',
5
+ 'Documents',
6
+ 'Frames',
7
+ 'JSEventListeners',
8
+ 'Nodes',
9
+ 'LayoutCount',
10
+ 'RecalcStyleCount',
11
+ 'LayoutDuration',
12
+ 'RecalcStyleDuration',
13
+ 'ScriptDuration',
14
+ 'TaskDuration',
15
+ 'JSHeapUsedSize',
16
+ 'JSHeapTotalSize',
17
+ ]).freeze
18
+
19
+ SUPPORTED_KEYS.each do |key|
20
+ attr_reader key
21
+ end
22
+
23
+ # @param metrics_result [Hash] response for Performance.getMetrics
24
+ def initialize(metrics_response)
25
+ metrics_response.each do |metric|
26
+ if SUPPORTED_KEYS.include?(metric['name'])
27
+ instance_variable_set(:"@#{metric['name']}", metric['value'])
28
+ end
29
+ end
30
+ end
31
+
32
+ def [](key)
33
+ if SUPPORTED_KEYS.include?(key.to_s)
34
+ instance_variable_get(:"@#{key}")
35
+ else
36
+ raise ArgumentError.new("invalid metric key specified: #{key}")
37
+ end
38
+ end
39
+ end
40
+
41
+ class MetricsEvent
42
+ def initialize(metrics_event)
43
+ @title = metrics_event['title']
44
+ @metrics = Metrics.new(metrics_event['metrics'])
45
+ end
46
+
47
+ attr_reader :title, :metrics
48
+ end
49
+ end
@@ -11,6 +11,7 @@ class Puppeteer::Puppeteer
11
11
  class NoViewport ; end
12
12
 
13
13
  # @param product [String]
14
+ # @param channel [String|Symbol]
14
15
  # @param executable_path [String]
15
16
  # @param ignore_default_args [Array<String>|nil]
16
17
  # @param handle_SIGINT [Boolean]
@@ -30,6 +31,7 @@ class Puppeteer::Puppeteer
30
31
  # @return [Puppeteer::Browser]
31
32
  def launch(
32
33
  product: nil,
34
+ channel: nil,
33
35
  executable_path: nil,
34
36
  ignore_default_args: nil,
35
37
  handle_SIGINT: nil,
@@ -48,6 +50,7 @@ class Puppeteer::Puppeteer
48
50
  slow_mo: nil
49
51
  )
50
52
  options = {
53
+ channel: channel&.to_s,
51
54
  executable_path: executable_path,
52
55
  ignore_default_args: ignore_default_args,
53
56
  handle_SIGINT: handle_SIGINT,
@@ -118,8 +121,8 @@ class Puppeteer::Puppeteer
118
121
  end
119
122
 
120
123
  # @return [String]
121
- def executable_path
122
- launcher.executable_path
124
+ def executable_path(channel: nil)
125
+ launcher.executable_path(channel: channel)
123
126
  end
124
127
 
125
128
  private def launcher
@@ -146,6 +149,11 @@ class Puppeteer::Puppeteer
146
149
  # # ???
147
150
  # end
148
151
 
152
+ # @return [Puppeteer::NetworkConditions]
153
+ def network_conditions
154
+ Puppeteer::NetworkConditions
155
+ end
156
+
149
157
  # @param args [Array<String>]
150
158
  # @param user_data_dir [String]
151
159
  # @param devtools [Boolean]
@@ -1,3 +1,3 @@
1
1
  module Puppeteer
2
- VERSION = '0.34.2'
2
+ VERSION = '0.36.0'
3
3
  end
@@ -3,7 +3,7 @@ class Puppeteer::WaitTask
3
3
 
4
4
  class TerminatedError < StandardError; end
5
5
 
6
- class TimeoutError < StandardError
6
+ class TimeoutError < ::Puppeteer::TimeoutError
7
7
  def initialize(title:, timeout:)
8
8
  super("waiting for #{title} failed: timeout #{timeout}ms exceeded")
9
9
  end
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'rollbar'
33
33
  spec.add_development_dependency 'rspec', '~> 3.10.0 '
34
34
  spec.add_development_dependency 'rspec_junit_formatter' # for CircleCI.
35
- spec.add_development_dependency 'rubocop', '~> 1.17.0'
35
+ spec.add_development_dependency 'rubocop', '~> 1.19.0'
36
36
  spec.add_development_dependency 'rubocop-rspec'
37
37
  spec.add_development_dependency 'sinatra'
38
38
  spec.add_development_dependency 'webrick'
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.34.2
4
+ version: 0.36.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - YusukeIwaki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-27 00:00:00.000000000 Z
11
+ date: 2021-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -170,14 +170,14 @@ dependencies:
170
170
  requirements:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: 1.17.0
173
+ version: 1.19.0
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: 1.17.0
180
+ version: 1.19.0
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: rubocop-rspec
183
183
  requirement: !ruby/object:Gem::Requirement
@@ -244,15 +244,14 @@ files:
244
244
  - ".rspec"
245
245
  - ".rubocop.yml"
246
246
  - CHANGELOG.md
247
- - Dockerfile
248
247
  - Gemfile
249
248
  - LICENSE
250
249
  - README.md
251
250
  - Rakefile
252
251
  - bin/console
253
252
  - bin/setup
254
- - docker-compose.yml
255
253
  - docs/api_coverage.md
254
+ - lib/puppeteer-ruby.rb
256
255
  - lib/puppeteer.rb
257
256
  - lib/puppeteer/aria_query_handler.rb
258
257
  - lib/puppeteer/browser.rb
@@ -294,7 +293,6 @@ files:
294
293
  - lib/puppeteer/keyboard/key_description.rb
295
294
  - lib/puppeteer/keyboard/us_keyboard_layout.rb
296
295
  - lib/puppeteer/launcher.rb
297
- - lib/puppeteer/launcher/base.rb
298
296
  - lib/puppeteer/launcher/browser_options.rb
299
297
  - lib/puppeteer/launcher/chrome.rb
300
298
  - lib/puppeteer/launcher/chrome_arg_options.rb
@@ -302,8 +300,11 @@ files:
302
300
  - lib/puppeteer/launcher/launch_options.rb
303
301
  - lib/puppeteer/lifecycle_watcher.rb
304
302
  - lib/puppeteer/mouse.rb
303
+ - lib/puppeteer/network_condition.rb
304
+ - lib/puppeteer/network_conditions.rb
305
305
  - lib/puppeteer/network_manager.rb
306
306
  - lib/puppeteer/page.rb
307
+ - lib/puppeteer/page/metrics.rb
307
308
  - lib/puppeteer/page/pdf_options.rb
308
309
  - lib/puppeteer/page/screenshot_options.rb
309
310
  - lib/puppeteer/page/screenshot_task_queue.rb
data/Dockerfile DELETED
@@ -1,9 +0,0 @@
1
- FROM circleci/ruby:3.0.0-rc1-buster-node-browsers
2
-
3
- USER root
4
-
5
- RUN wget -O nightly.tar.bz2 "https://download.mozilla.org/?product=firefox-nightly-latest-ssl&os=linux64&lang=en-US" \
6
- && tar xf nightly.tar.bz2 \
7
- && ln -s $(pwd)/firefox/firefox /usr/bin/firefox
8
-
9
- USER circleci
data/docker-compose.yml DELETED
@@ -1,34 +0,0 @@
1
- version: "3"
2
- services:
3
- chrome:
4
- tty: true
5
- stdin_open: true
6
- build: .
7
- environment:
8
- BUNDLE_PATH: /usr/local/bundle
9
- DEBUG: 1
10
- CI: 1
11
- volumes:
12
- - .:/puppeteer-ruby
13
- - bundle-data:/usr/local/bundle
14
- working_dir: /puppeteer-ruby
15
- command: bundle exec rspec
16
-
17
- firefox:
18
- tty: true
19
- stdin_open: true
20
- build: .
21
- environment:
22
- BUNDLE_PATH: /usr/local/bundle
23
- PUPPETEER_PRODUCT_RSPEC: firefox
24
- DEBUG: 1
25
- CI: 1
26
- volumes:
27
- - .:/puppeteer-ruby
28
- - bundle-data:/usr/local/bundle
29
- working_dir: /puppeteer-ruby
30
- command: bundle exec rspec spec/integration/
31
-
32
- volumes:
33
- bundle-data:
34
- driver: local
@@ -1,66 +0,0 @@
1
- module Puppeteer::Launcher
2
- class Base
3
- # @param {string} projectRoot
4
- # @param {string} preferredRevision
5
- def initialize(project_root:, preferred_revision:, is_puppeteer_core:)
6
- @project_root = project_root
7
- @preferred_revision = preferred_revision
8
- @is_puppeteer_core = is_puppeteer_core
9
- end
10
-
11
- class ExecutablePathNotFound < StandardError; end
12
-
13
- # @returns [String] Chrome Executable file path.
14
- # @raise [ExecutablePathNotFound]
15
- def resolve_executable_path
16
- if !@is_puppeteer_core
17
- # puppeteer-core doesn't take into account PUPPETEER_* env variables.
18
- executable_path = ENV['PUPPETEER_EXECUTABLE_PATH']
19
- if FileTest.exist?(executable_path)
20
- return executable_path
21
- end
22
- raise ExecutablePathNotFound.new(
23
- "Tried to use PUPPETEER_EXECUTABLE_PATH env variable to launch browser but did not find any executable at: #{executable_path}",
24
- )
25
- end
26
-
27
- # temporal logic.
28
- if Puppeteer.env.darwin?
29
- case self
30
- when Chrome
31
- '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
32
- when Firefox
33
- '/Applications/Firefox Nightly.app/Contents/MacOS/firefox'
34
- end
35
- elsif Puppeteer.env.windows?
36
- case self
37
- when Chrome
38
- 'C:\Program Files\Google\Chrome\Application\chrome.exe'
39
- # 'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe'
40
- when Firefox
41
- 'C:\Program Files\Firefox Nightly\firefox.exe'
42
- end
43
- else
44
- case self
45
- when Chrome
46
- '/usr/bin/google-chrome'
47
- when Firefox
48
- '/usr/bin/firefox'
49
- end
50
- end
51
-
52
- # const browserFetcher = new BrowserFetcher(launcher._projectRoot);
53
- # if (!launcher._isPuppeteerCore) {
54
- # const revision = process.env['PUPPETEER_CHROMIUM_REVISION'];
55
- # if (revision) {
56
- # const revisionInfo = browserFetcher.revisionInfo(revision);
57
- # const missingText = !revisionInfo.local ? 'Tried to use PUPPETEER_CHROMIUM_REVISION env variable to launch browser but did not find executable at: ' + revisionInfo.executablePath : null;
58
- # return {executablePath: revisionInfo.executablePath, missingText};
59
- # }
60
- # }
61
- # const revisionInfo = browserFetcher.revisionInfo(launcher._preferredRevision);
62
- # const missingText = !revisionInfo.local ? `Browser is not downloaded. Run "npm install" or "yarn install"` : null;
63
- # return {executablePath: revisionInfo.executablePath, missingText};
64
- end
65
- end
66
- end