puppeteer-ruby 0.0.20 → 0.0.26

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: 8a0821b740ece89c3194c7b9fc7778b18528d38becf524e7a1c50ceffd37ab3c
4
- data.tar.gz: 86a3e592c61b4f0095ca3fad2ab0ecb1b031c4dbe4f9607caa52b2b82cf225bd
3
+ metadata.gz: f76be710be28b32694ef8d21bcaa305f00b8ac0ada333d2992137f166614bd94
4
+ data.tar.gz: 29d4c83aaa00705db67dd1a33b62b304b125fc59bd5f826099a9f864202f3e00
5
5
  SHA512:
6
- metadata.gz: e73f8a9f380aadb2e4dd4164be571ee22b688b48b1999720d0ecefb39b62f79a071a709134b00f701b04a1d179bba3efe742d3307fca9bc2d2f56cb305b7bb53
7
- data.tar.gz: f03efa136e60899f4eb0e0bd671e60c86b52efb13a59d62754b88961188d1495e7e85e012bb93a11d118e2f5a93375de07c453ef5a5eff7375325c2ec9b2b5ae
6
+ metadata.gz: f5dbf6ee744fdb70d7645bdfaf3840088d756b31a0dfcf05109058299d07ea338967c019ee4a55f834bc388b39cfc19b147ac7f08d80762d5eb44ed8517d0f1a
7
+ data.tar.gz: 05a88198b74788638619bbdef3faaede3503c61a5b6574a562180265f5f927a236a564b3f0d73dfefcaa442b492227b934f7233ad72183924b98d66e242e4850
@@ -116,6 +116,43 @@ Style/DefWithParentheses:
116
116
  Style/MethodDefParentheses:
117
117
  Enabled: true
118
118
 
119
+ Style/MethodCallWithArgsParentheses:
120
+ Enabled: true
121
+ IgnoredMethods:
122
+ # Gemfile, gemspec
123
+ - source
124
+ - add_dependency
125
+ - add_development_dependency
126
+
127
+ # include/require
128
+ - require
129
+ - require_relative
130
+ - include
131
+
132
+ # fundamental methods
133
+ - raise
134
+ - sleep
135
+
136
+ # RSpec
137
+ - describe
138
+ - it
139
+ - to
140
+ - not_to
141
+ - be
142
+ - eq
143
+
144
+ # async/await
145
+ - define_async_method
146
+ - await
147
+ - future
148
+
149
+ # utils
150
+ - debug_print
151
+ - debug_puts
152
+
153
+ Style/MethodCallWithoutArgsParentheses:
154
+ Enabled: true
155
+
119
156
  Style/RedundantFreeze:
120
157
  Enabled: true
121
158
 
@@ -0,0 +1,62 @@
1
+ ### master [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.25...master)]
2
+
3
+ * xxx
4
+
5
+ ### 0.0.25 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.23...0.0.25)]
6
+
7
+ New feature:
8
+
9
+ * **Cookie** feature: `Page#set_cookie`, `Page#cookies`
10
+
11
+ ### 0.0.23 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.22...0.0.23)]
12
+
13
+ New feature:
14
+
15
+ * **GeoLocation** feature
16
+ * grant/clear permission
17
+
18
+ Bugfix/Improvement:
19
+
20
+ * Refactoring for events ([#31](https://github.com/YusukeIwaki/puppeteer-ruby/pull/31))
21
+ * Improve SEND/RECV handling in CDPSession ([#34](https://github.com/YusukeIwaki/puppeteer-ruby/pull/34))
22
+
23
+ ### 0.0.22 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.21...0.0.22)]
24
+
25
+ Bugfix
26
+
27
+ * Make `Puppeteer#default_args` to work
28
+ * Respect Firefox launch options
29
+ * Respect `default_viewport: nil`
30
+
31
+ ### 0.0.21 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.20...0.0.21)]
32
+
33
+ Bugfix/Improvement:
34
+
35
+ * Update DeviceDescriptors (list of emulatable devices)
36
+ * Fix bug on inputing "(" ([#25](https://github.com/YusukeIwaki/puppeteer-ruby/pull/25))
37
+
38
+ ### 0.0.20 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.19...0.0.20)]
39
+
40
+ New feature
41
+
42
+ * Dialog-handling feature
43
+
44
+ ### 0.0.19 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.18...0.0.19)]
45
+
46
+ New feature
47
+
48
+ * **Firefox support**
49
+
50
+ Bugfix/Improvement
51
+
52
+ * Allow `Page#keyboard` with block ([#18](https://github.com/YusukeIwaki/puppeteer-ruby/pull/18))
53
+
54
+ ### 0.0.18 [[diff](https://github.com/YusukeIwaki/puppeteer-ruby/compare/0.0.17...0.0.18)]
55
+
56
+ New feature
57
+
58
+ * **Firefox support**
59
+
60
+ Bugfix/Improvement
61
+
62
+ * Allow `Page#keyboard` with block ([#18](https://github.com/YusukeIwaki/puppeteer-ruby/pull/18))
data/README.md CHANGED
@@ -72,6 +72,21 @@ end
72
72
 
73
73
  More usage examples can be found [here](https://github.com/YusukeIwaki/puppeteer-ruby-example)
74
74
 
75
+ ## :whale: Running in Docker
76
+
77
+ Following packages are required.
78
+
79
+ * Google Chrome or Chromium
80
+ * In Debian-based images, `google-chrome-stable`
81
+ * In Alpine-based images, `chromium`
82
+
83
+ Also, CJK font will be required for Chinese, Japanese, Korean sites.
84
+
85
+ ### References
86
+
87
+ * Puppeteer official README: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-puppeteer-in-docker
88
+ * puppeteer-ruby example: https://github.com/YusukeIwaki/puppeteer-ruby-example/tree/master/docker_chromium
89
+
75
90
  ## :bulb: Collaboration with Selenium or Capybara
76
91
 
77
92
  It is really remarkable that we can use puppeteer functions in existing Selenium or Capybara codes, with a few configuration in advance.
@@ -6,7 +6,9 @@ require 'puppeteer/env'
6
6
 
7
7
  # Custom data types.
8
8
  require 'puppeteer/device'
9
+ require 'puppeteer/events'
9
10
  require 'puppeteer/errors'
11
+ require 'puppeteer/geolocation'
10
12
  require 'puppeteer/viewport'
11
13
 
12
14
  # Modules
@@ -27,6 +29,7 @@ require 'puppeteer/devices'
27
29
  require 'puppeteer/dialog'
28
30
  require 'puppeteer/dom_world'
29
31
  require 'puppeteer/emulation_manager'
32
+ require 'puppeteer/exception_details'
30
33
  require 'puppeteer/execution_context'
31
34
  require 'puppeteer/file_chooser'
32
35
  require 'puppeteer/frame'
@@ -61,7 +64,11 @@ class Puppeteer
61
64
  is_puppeteer_core: true,
62
65
  )
63
66
 
64
- @puppeteer.send(method, *args, **kwargs, &block)
67
+ if kwargs.empty? # for Ruby < 2.7
68
+ @puppeteer.public_send(method, *args, &block)
69
+ else
70
+ @puppeteer.public_send(method, *args, **kwargs, &block)
71
+ end
65
72
  end
66
73
 
67
74
  # @param project_root [String]
@@ -127,7 +134,7 @@ class Puppeteer
127
134
  ignore_https_errors: ignore_https_errors,
128
135
  default_viewport: default_viewport,
129
136
  slow_mo: slow_mo,
130
- }.compact
137
+ }
131
138
 
132
139
  @product_name ||= product
133
140
  browser = launcher.launch(options)
@@ -36,7 +36,6 @@ class Puppeteer::Browser
36
36
  @ignore_https_errors = ignore_https_errors
37
37
  @default_viewport = default_viewport
38
38
  @process = process
39
- # @screenshot_task_queue = TaskQueue.new
40
39
  @connection = connection
41
40
  @close_callback = close_callback
42
41
 
@@ -46,37 +45,30 @@ class Puppeteer::Browser
46
45
  @contexts[context_id] = Puppeteer::BrowserContext.new(@connection, self, context_id)
47
46
  end
48
47
  @targets = {}
49
- @connection.on_event 'Events.Connection.Disconnected' do
50
- emit_event 'Events.Browser.Disconnected'
48
+ @connection.on_event(ConnectionEmittedEvents::Disconnected) do
49
+ emit_event(BrowserEmittedEvents::Disconnected)
51
50
  end
52
- @connection.on_event 'Target.targetCreated', &method(:handle_target_created)
53
- @connection.on_event 'Target.targetDestroyed', &method(:handle_target_destroyed)
54
- @connection.on_event 'Target.targetInfoChanged', &method(:handle_target_info_changed)
51
+ @connection.on_event('Target.targetCreated', &method(:handle_target_created))
52
+ @connection.on_event('Target.targetDestroyed', &method(:handle_target_destroyed))
53
+ @connection.on_event('Target.targetInfoChanged', &method(:handle_target_info_changed))
55
54
  end
56
55
 
57
- EVENT_MAPPINGS = {
58
- disconnected: 'Events.Browser.Disconnected',
59
- targetcreated: 'Events.Browser.TargetCreated',
60
- targetchanged: 'Events.Browser.TargetChanged',
61
- targetdestroyed: 'Events.Browser.TargetDestroyed',
62
- }
63
-
64
56
  # @param event_name [Symbol] either of :disconnected, :targetcreated, :targetchanged, :targetdestroyed
65
57
  def on(event_name, &block)
66
- unless EVENT_MAPPINGS.has_key?(event_name.to_sym)
67
- raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{EVENT_MAPPINGS.keys.join(", ")}")
58
+ unless BrowserEmittedEvents.values.include?(event_name.to_s)
59
+ raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{BrowserEmittedEvents.values.to_a.join(", ")}")
68
60
  end
69
61
 
70
- add_event_listener(EVENT_MAPPINGS[event_name.to_sym], &block)
62
+ super(event_name.to_s, &block)
71
63
  end
72
64
 
73
65
  # @param event_name [Symbol]
74
66
  def once(event_name, &block)
75
- unless EVENT_MAPPINGS.has_key?(event_name.to_sym)
76
- raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{EVENT_MAPPINGS.keys.join(", ")}")
67
+ unless BrowserEmittedEvents.values.include?(event_name.to_s)
68
+ raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{BrowserEmittedEvents.values.to_a.join(", ")}")
77
69
  end
78
70
 
79
- observe_first(EVENT_MAPPINGS[event_name.to_sym], &block)
71
+ super(event_name.to_s, &block)
80
72
  end
81
73
 
82
74
  # @return [Puppeteer::BrowserRunner::BrowserProcess]
@@ -132,13 +124,12 @@ class Puppeteer::Browser
132
124
  session_factory: -> { @connection.create_session(target_info) },
133
125
  ignore_https_errors: @ignore_https_errors,
134
126
  default_viewport: @default_viewport,
135
- screenshot_task_queue: @screenshot_task_queue,
136
127
  )
137
128
  # assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated');
138
129
  @targets[target_info.target_id] = target
139
130
  if await target.initialized_promise
140
- emit_event 'Events.Browser.TargetCreated', target
141
- context.emit_event 'Events.BrowserContext.TargetCreated', target
131
+ emit_event(BrowserEmittedEvents::TargetCreated, target)
132
+ context.emit_event(BrowserContextEmittedEvents::TargetCreated, target)
142
133
  end
143
134
  end
144
135
 
@@ -150,8 +141,8 @@ class Puppeteer::Browser
150
141
  @targets.delete(target_id)
151
142
  target.closed_callback
152
143
  if await target.initialized_promise
153
- emit_event 'Events.Browser.TargetDestroyed', target
154
- target.browser_context.emit_event 'Events.BrowserContext.TargetDestroyed', target
144
+ emit_event(BrowserEmittedEvents::TargetDestroyed, target)
145
+ target.browser_context.emit_event(BrowserContextEmittedEvents::TargetDestroyed, target)
155
146
  end
156
147
  end
157
148
 
@@ -169,8 +160,8 @@ class Puppeteer::Browser
169
160
  was_initialized = target.initialized?
170
161
  target.handle_target_info_changed(target_info)
171
162
  if was_initialized && previous_url != target.url
172
- emit_event 'Events.Browser.TargetChanged', target
173
- target.browser_context.emit_event 'Events.BrowserContext.TargetChanged', target
163
+ emit_event(BrowserEmittedEvents::TargetChanged, target)
164
+ target.browser_context.emit_event(BrowserContextEmittedEvents::TargetChanged, target)
174
165
  end
175
166
  end
176
167
 
@@ -222,12 +213,12 @@ class Puppeteer::Browser
222
213
 
223
214
  event_listening_ids = []
224
215
  target_promise = resolvable_future
225
- event_listening_ids << add_event_listener('Events.Browser.TargetCreated') do |target|
216
+ event_listening_ids << add_event_listener(BrowserEmittedEvents::TargetCreated) do |target|
226
217
  if predicate.call(target)
227
218
  target_promise.fulfill(target)
228
219
  end
229
220
  end
230
- event_listening_ids << add_event_listener('Events.Browser.TargetChanged') do |target|
221
+ event_listening_ids << add_event_listener(BrowserEmittedEvents::TargetChanged) do |target|
231
222
  if predicate.call(target)
232
223
  target_promise.fulfill(target)
233
224
  end
@@ -11,29 +11,22 @@ class Puppeteer::BrowserContext
11
11
  @id = context_id
12
12
  end
13
13
 
14
- EVENT_MAPPINGS = {
15
- disconnected: 'Events.BrowserContext.Disconnected',
16
- targetcreated: 'Events.BrowserContext.TargetCreated',
17
- targetchanged: 'Events.BrowserContext.TargetChanged',
18
- targetdestroyed: 'Events.BrowserContext.TargetDestroyed',
19
- }
20
-
21
14
  # @param event_name [Symbol] either of :disconnected, :targetcreated, :targetchanged, :targetdestroyed
22
15
  def on(event_name, &block)
23
- unless EVENT_MAPPINGS.has_key?(event_name.to_sym)
24
- raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{EVENT_MAPPINGS.keys.join(", ")}")
16
+ unless BrowserContextEmittedEvents.values.include?(event_name.to_s)
17
+ raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{BrowserContextEmittedEvents.values.to_a.join(", ")}")
25
18
  end
26
19
 
27
- add_event_listener(EVENT_MAPPINGS[event_name.to_sym], &block)
20
+ super(event_name.to_s, &block)
28
21
  end
29
22
 
30
23
  # @param event_name [Symbol]
31
24
  def once(event_name, &block)
32
- unless EVENT_MAPPINGS.has_key?(event_name.to_sym)
33
- raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{EVENT_MAPPINGS.keys.join(", ")}")
25
+ unless BrowserContextEmittedEvents.values.include?(event_name.to_s)
26
+ raise ArgumentError.new("Unknown event name: #{event_name}. Known events are #{BrowserContextEmittedEvents.values.to_a.join(", ")}")
34
27
  end
35
28
 
36
- observe_first(EVENT_MAPPINGS[event_name.to_sym], &block)
29
+ super(event_name.to_s, &block)
37
30
  end
38
31
 
39
32
  # @return {!Array<!Target>} target
@@ -64,42 +57,48 @@ class Puppeteer::BrowserContext
64
57
  !!@id
65
58
  end
66
59
 
67
- # /**
68
- # * @param {string} origin
69
- # * @param {!Array<string>} permissions
70
- # */
71
- # async overridePermissions(origin, permissions) {
72
- # const webPermissionToProtocol = new Map([
73
- # ['geolocation', 'geolocation'],
74
- # ['midi', 'midi'],
75
- # ['notifications', 'notifications'],
76
- # ['push', 'push'],
77
- # ['camera', 'videoCapture'],
78
- # ['microphone', 'audioCapture'],
79
- # ['background-sync', 'backgroundSync'],
80
- # ['ambient-light-sensor', 'sensors'],
81
- # ['accelerometer', 'sensors'],
82
- # ['gyroscope', 'sensors'],
83
- # ['magnetometer', 'sensors'],
84
- # ['accessibility-events', 'accessibilityEvents'],
85
- # ['clipboard-read', 'clipboardRead'],
86
- # ['clipboard-write', 'clipboardWrite'],
87
- # ['payment-handler', 'paymentHandler'],
88
- # // chrome-specific permissions we have.
89
- # ['midi-sysex', 'midiSysex'],
90
- # ]);
91
- # permissions = permissions.map(permission => {
92
- # const protocolPermission = webPermissionToProtocol.get(permission);
93
- # if (!protocolPermission)
94
- # throw new Error('Unknown permission: ' + permission);
95
- # return protocolPermission;
96
- # });
97
- # await this._connection.send('Browser.grantPermissions', {origin, browserContextId: this._id || undefined, permissions});
98
- # }
99
-
100
- # async clearPermissionOverrides() {
101
- # await this._connection.send('Browser.resetPermissions', {browserContextId: this._id || undefined});
102
- # }
60
+ WEB_PERMISSION_TO_PROTOCOL = {
61
+ 'geolocation' => 'geolocation',
62
+ 'midi' => 'midi',
63
+ 'notifications' => 'notifications',
64
+ # TODO: push isn't a valid type?
65
+ # 'push' => 'push',
66
+ 'camera' => 'videoCapture',
67
+ 'microphone' => 'audioCapture',
68
+ 'background-sync' => 'backgroundSync',
69
+ 'ambient-light-sensor' => 'sensors',
70
+ 'accelerometer' => 'sensors',
71
+ 'gyroscope' => 'sensors',
72
+ 'magnetometer' => 'sensors',
73
+ 'accessibility-events' => 'accessibilityEvents',
74
+ 'clipboard-read' => 'clipboardReadWrite',
75
+ 'clipboard-write' => 'clipboardReadWrite',
76
+ 'payment-handler' => 'paymentHandler',
77
+ 'idle-detection' => 'idleDetection',
78
+ # chrome-specific permissions we have.
79
+ 'midi-sysex' => 'midiSysex',
80
+ }.freeze
81
+
82
+ # @param origin [String]
83
+ # @param permissions [Array<String>]
84
+ def override_permissions(origin, permissions)
85
+ protocol_permissions = permissions.map do |permission|
86
+ WEB_PERMISSION_TO_PROTOCOL[permission] or raise ArgumentError.new("Unknown permission: #{permission}")
87
+ end
88
+ @connection.send_message('Browser.grantPermissions', {
89
+ origin: origin,
90
+ browserContextId: @id,
91
+ permissions: protocol_permissions,
92
+ }.compact)
93
+ end
94
+
95
+ def clear_permission_overrides
96
+ if @id
97
+ @connection.send_message('Browser.resetPermissions', browserContextId: @id)
98
+ else
99
+ @connection.send_message('Browser.resetPermissions')
100
+ end
101
+ end
103
102
 
104
103
  # @return [Future<Puppeteer::Page>]
105
104
  def new_page
@@ -14,16 +14,24 @@ class Puppeteer::BrowserRunner
14
14
  @proc = nil
15
15
  @connection = nil
16
16
  @closed = true
17
- @listeners = []
18
17
  end
19
18
 
20
19
  attr_reader :proc, :connection
21
20
 
22
21
  class BrowserProcess
23
22
  def initialize(env, executable_path, args)
23
+ @spawnargs =
24
+ if args && !args.empty?
25
+ [executable_path] + args
26
+ else
27
+ [executable_path]
28
+ end
29
+
24
30
  stdin, @stdout, @stderr, @thread = Open3.popen3(env, executable_path, *args)
25
31
  stdin.close
26
32
  @pid = @thread.pid
33
+ rescue Errno::ENOENT => err
34
+ raise LaunchError.new(err.message)
27
35
  end
28
36
 
29
37
  def kill
@@ -37,7 +45,13 @@ class Puppeteer::BrowserRunner
37
45
  @thread.join
38
46
  end
39
47
 
40
- attr_reader :stdout, :stderr
48
+ attr_reader :stdout, :stderr, :spawnargs
49
+ end
50
+
51
+ class LaunchError < StandardError
52
+ def initialize(reason)
53
+ super("Failed to launch browser! #{reason}")
54
+ end
41
55
  end
42
56
 
43
57
  # @param {!(Launcher.LaunchOptions)=} options
@@ -123,12 +137,12 @@ class Puppeteer::BrowserRunner
123
137
 
124
138
  # @return {Promise}
125
139
  def kill
126
- unless @closed
127
- @proc.kill
128
- end
129
140
  if @temp_directory
130
141
  FileUtils.rm_rf(@temp_directory)
131
142
  end
143
+ unless @closed
144
+ @proc.kill
145
+ end
132
146
  end
133
147
 
134
148