puppeteer-ruby 0.34.2 → 0.36.0

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: 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