puppeteer-ruby 0.0.8 → 0.0.13
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 +4 -4
- data/README.md +2 -0
- data/docs/Puppeteer.html +415 -97
- data/docs/Puppeteer/AsyncAwaitBehavior.html +1 -1
- data/docs/Puppeteer/Browser.html +261 -153
- data/docs/Puppeteer/BrowserContext.html +2 -2
- data/docs/Puppeteer/BrowserFetcher.html +1 -1
- data/docs/Puppeteer/BrowserRunner.html +1 -1
- data/docs/Puppeteer/BrowserRunner/BrowserProcess.html +1 -1
- data/docs/Puppeteer/CDPSession.html +2 -2
- data/docs/Puppeteer/CDPSession/Error.html +1 -1
- data/docs/Puppeteer/ConcurrentRubyUtils.html +14 -6
- data/docs/Puppeteer/Connection.html +66 -62
- data/docs/Puppeteer/Connection/MessageCallback.html +1 -1
- data/docs/Puppeteer/Connection/ProtocolError.html +1 -1
- data/docs/Puppeteer/Connection/RequestDebugPrinter.html +5 -5
- data/docs/Puppeteer/Connection/ResponseDebugPrinter.html +12 -12
- data/docs/Puppeteer/ConsoleMessage.html +1 -1
- data/docs/Puppeteer/ConsoleMessage/Location.html +1 -1
- data/docs/Puppeteer/DOMWorld.html +106 -32
- data/docs/Puppeteer/DOMWorld/DetachedError.html +1 -1
- data/docs/Puppeteer/DOMWorld/DocumentEvaluationError.html +1 -1
- data/docs/Puppeteer/DebugPrint.html +1 -1
- data/docs/Puppeteer/Device.html +1 -1
- data/docs/Puppeteer/Devices.html +1 -1
- data/docs/Puppeteer/ElementHandle.html +525 -207
- data/docs/Puppeteer/ElementHandle/BoundingBox.html +507 -0
- data/docs/Puppeteer/ElementHandle/BoxModel.html +404 -0
- data/docs/Puppeteer/ElementHandle/ElementNotFoundError.html +5 -5
- data/docs/Puppeteer/ElementHandle/ElementNotVisibleError.html +5 -5
- data/docs/Puppeteer/ElementHandle/Point.html +40 -29
- data/docs/Puppeteer/ElementHandle/ScrollIntoViewError.html +1 -1
- data/docs/Puppeteer/EmulationManager.html +1 -1
- data/docs/Puppeteer/EventCallbackable.html +83 -17
- data/docs/Puppeteer/EventCallbackable/EventListeners.html +1 -1
- data/docs/Puppeteer/ExecutionContext.html +1 -1
- data/docs/Puppeteer/ExecutionContext/EvaluationError.html +1 -1
- data/docs/Puppeteer/ExecutionContext/JavaScriptExpression.html +1 -1
- data/docs/Puppeteer/ExecutionContext/JavaScriptFunction.html +1 -1
- data/docs/Puppeteer/FileChooser.html +1 -1
- data/docs/Puppeteer/Frame.html +450 -292
- data/docs/Puppeteer/FrameManager.html +23 -27
- data/docs/Puppeteer/FrameManager/NavigationError.html +1 -1
- data/docs/Puppeteer/IfPresent.html +1 -1
- data/docs/Puppeteer/JSHandle.html +1 -1
- data/docs/Puppeteer/Keyboard.html +1 -1
- data/docs/Puppeteer/Keyboard/KeyDefinition.html +1 -1
- data/docs/Puppeteer/Keyboard/KeyDescription.html +1 -1
- data/docs/Puppeteer/Launcher.html +1 -1
- data/docs/Puppeteer/Launcher/Base.html +1 -1
- data/docs/Puppeteer/Launcher/Base/ExecutablePathNotFound.html +1 -1
- data/docs/Puppeteer/Launcher/BrowserOptions.html +1 -1
- data/docs/Puppeteer/Launcher/Chrome.html +36 -31
- data/docs/Puppeteer/Launcher/Chrome/DefaultArgs.html +1 -1
- data/docs/Puppeteer/Launcher/ChromeArgOptions.html +1 -1
- data/docs/Puppeteer/Launcher/LaunchOptions.html +1 -1
- data/docs/Puppeteer/LifecycleWatcher.html +1 -1
- data/docs/Puppeteer/LifecycleWatcher/ExpectedLifecycle.html +1 -1
- data/docs/Puppeteer/LifecycleWatcher/FrameDetachedError.html +1 -1
- data/docs/Puppeteer/LifecycleWatcher/TerminatedError.html +1 -1
- data/docs/Puppeteer/Mouse.html +31 -41
- data/docs/Puppeteer/Mouse/Button.html +1 -1
- data/docs/Puppeteer/NetworkManager.html +2 -2
- data/docs/Puppeteer/NetworkManager/Credentials.html +1 -1
- data/docs/Puppeteer/Page.html +502 -299
- data/docs/Puppeteer/Page/FileChooserTimeoutError.html +5 -5
- data/docs/Puppeteer/Page/ScreenshotOptions.html +1 -1
- data/docs/Puppeteer/Page/ScriptTag.html +24 -24
- data/docs/Puppeteer/Page/StyleTag.html +19 -19
- data/docs/Puppeteer/Page/TargetCrashedError.html +1 -1
- data/docs/Puppeteer/RemoteObject.html +110 -39
- data/docs/Puppeteer/Target.html +150 -198
- data/docs/Puppeteer/Target/InitializeFailure.html +1 -1
- data/docs/Puppeteer/Target/TargetInfo.html +1 -1
- data/docs/Puppeteer/TimeoutError.html +2 -2
- data/docs/Puppeteer/TimeoutSettings.html +1 -1
- data/docs/Puppeteer/TouchScreen.html +1 -1
- data/docs/Puppeteer/Viewport.html +81 -1
- data/docs/Puppeteer/WaitTask.html +1 -1
- data/docs/Puppeteer/WaitTask/TerminatedError.html +1 -1
- data/docs/Puppeteer/WaitTask/TimeoutError.html +1 -1
- data/docs/Puppeteer/WebSocket.html +26 -26
- data/docs/Puppeteer/WebSocket/DriverImpl.html +1 -1
- data/docs/Puppeteer/WebSocket/TransportError.html +124 -0
- data/docs/Puppeteer/WebSocketTransport.html +9 -9
- data/docs/Puppeteer/WebSocktTransportError.html +1 -1
- data/docs/_index.html +28 -21
- data/docs/class_list.html +1 -1
- data/docs/file.README.html +3 -1
- data/docs/index.html +3 -1
- data/docs/method_list.html +659 -515
- data/docs/top-level-namespace.html +1 -1
- data/lib/puppeteer.rb +36 -12
- data/lib/puppeteer/browser.rb +26 -6
- data/lib/puppeteer/concurrent_ruby_utils.rb +6 -2
- data/lib/puppeteer/connection.rb +13 -1
- data/lib/puppeteer/dom_world.rb +11 -12
- data/lib/puppeteer/element_handle.rb +66 -108
- data/lib/puppeteer/element_handle/bounding_box.rb +12 -0
- data/lib/puppeteer/element_handle/box_model.rb +19 -0
- data/lib/puppeteer/element_handle/point.rb +26 -0
- data/lib/puppeteer/errors.rb +1 -3
- data/lib/puppeteer/event_callbackable.rb +11 -0
- data/lib/puppeteer/frame.rb +20 -1
- data/lib/puppeteer/launcher.rb +6 -6
- data/lib/puppeteer/launcher/chrome.rb +10 -8
- data/lib/puppeteer/mouse.rb +3 -8
- data/lib/puppeteer/page.rb +43 -4
- data/lib/puppeteer/remote_object.rb +9 -0
- data/lib/puppeteer/target.rb +25 -25
- data/lib/puppeteer/version.rb +1 -1
- data/lib/puppeteer/viewport.rb +18 -0
- data/lib/puppeteer/web_socket.rb +3 -1
- data/lib/puppeteer/web_socket_transport.rb +8 -8
- data/puppeteer-ruby.png +0 -0
- metadata +9 -4
- data/Dockerfile +0 -6
- data/docker-compose.yml +0 -15
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
</div>
|
|
117
117
|
|
|
118
118
|
<div id="footer">
|
|
119
|
-
Generated on
|
|
119
|
+
Generated on Wed Jun 24 03:07:58 2020 by
|
|
120
120
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
121
121
|
0.9.24 (ruby-2.6.3).
|
|
122
122
|
</div>
|
data/lib/puppeteer.rb
CHANGED
|
@@ -63,17 +63,33 @@ class Puppeteer
|
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
# @param
|
|
67
|
-
# @param
|
|
68
|
-
# @param
|
|
66
|
+
# @param project_root [String]
|
|
67
|
+
# @param prefereed_revision [String]
|
|
68
|
+
# @param is_puppeteer_core [String]
|
|
69
69
|
def initialize(project_root:, preferred_revision:, is_puppeteer_core:)
|
|
70
70
|
@project_root = project_root
|
|
71
71
|
@preferred_revision = preferred_revision
|
|
72
72
|
@is_puppeteer_core = is_puppeteer_core
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
# @param
|
|
76
|
-
# @
|
|
75
|
+
# @param product [String]
|
|
76
|
+
# @param executable_path [String]
|
|
77
|
+
# @param ignore_default_args [Array<String>|nil]
|
|
78
|
+
# @param handle_SIGINT [Boolean]
|
|
79
|
+
# @param handle_SIGTERM [Boolean]
|
|
80
|
+
# @param handle_SIGHUP [Boolean]
|
|
81
|
+
# @param timeout [Integer]
|
|
82
|
+
# @param dumpio [Boolean]
|
|
83
|
+
# @param env [Hash]
|
|
84
|
+
# @param pipe [Boolean]
|
|
85
|
+
# @param args [Array<String>]
|
|
86
|
+
# @param user_data_dir [String]
|
|
87
|
+
# @param devtools [Boolean]
|
|
88
|
+
# @param headless [Boolean]
|
|
89
|
+
# @param ignore_https_errors [Boolean]
|
|
90
|
+
# @param default_viewport [Puppeteer::Viewport|nil]
|
|
91
|
+
# @param slow_mo [Integer]
|
|
92
|
+
# @return [Puppeteer::Browser]
|
|
77
93
|
def launch(
|
|
78
94
|
product: nil,
|
|
79
95
|
executable_path: nil,
|
|
@@ -125,8 +141,13 @@ class Puppeteer
|
|
|
125
141
|
end
|
|
126
142
|
end
|
|
127
143
|
|
|
128
|
-
# @param
|
|
129
|
-
# @
|
|
144
|
+
# @param browser_ws_endpoint [String]
|
|
145
|
+
# @param browser_url [String]
|
|
146
|
+
# @param transport [Puppeteer::WebSocketTransport]
|
|
147
|
+
# @param ignore_https_errors [Boolean]
|
|
148
|
+
# @param default_viewport [Puppeteer::Viewport|nil]
|
|
149
|
+
# @param slow_mo [Integer]
|
|
150
|
+
# @return [Puppeteer::Browser]
|
|
130
151
|
def connect(
|
|
131
152
|
browser_ws_endpoint: nil,
|
|
132
153
|
browser_url: nil,
|
|
@@ -151,7 +172,7 @@ class Puppeteer
|
|
|
151
172
|
end
|
|
152
173
|
end
|
|
153
174
|
|
|
154
|
-
# @return
|
|
175
|
+
# @return [String]
|
|
155
176
|
def executable_path
|
|
156
177
|
launcher.executable_path
|
|
157
178
|
end
|
|
@@ -165,12 +186,12 @@ class Puppeteer
|
|
|
165
186
|
)
|
|
166
187
|
end
|
|
167
188
|
|
|
168
|
-
# @return
|
|
189
|
+
# @return [String]
|
|
169
190
|
def product
|
|
170
191
|
launcher.product
|
|
171
192
|
end
|
|
172
193
|
|
|
173
|
-
# @return
|
|
194
|
+
# @return [Puppeteer::Devices]
|
|
174
195
|
def devices
|
|
175
196
|
Puppeteer::Devices
|
|
176
197
|
end
|
|
@@ -180,8 +201,11 @@ class Puppeteer
|
|
|
180
201
|
# # ???
|
|
181
202
|
# end
|
|
182
203
|
|
|
183
|
-
# @param
|
|
184
|
-
# @
|
|
204
|
+
# @param args [Array<String>]
|
|
205
|
+
# @param user_data_dir [String]
|
|
206
|
+
# @param devtools [Boolean]
|
|
207
|
+
# @param headless [Boolean]
|
|
208
|
+
# @return [Array<String>]
|
|
185
209
|
def default_args(args: nil, user_data_dir: nil, devtools: nil, headless: nil)
|
|
186
210
|
options = {
|
|
187
211
|
args: args,
|
data/lib/puppeteer/browser.rb
CHANGED
|
@@ -46,7 +46,7 @@ class Puppeteer::Browser
|
|
|
46
46
|
@contexts[context_id] = Puppeteer::BrowserContext.new(@connection, self. context_id)
|
|
47
47
|
end
|
|
48
48
|
@targets = {}
|
|
49
|
-
@connection.on_event 'Events.
|
|
49
|
+
@connection.on_event 'Events.Connection.Disconnected' do
|
|
50
50
|
emit_event 'Events.Browser.Disconnected'
|
|
51
51
|
end
|
|
52
52
|
@connection.on_event 'Target.targetCreated', &method(:handle_target_created)
|
|
@@ -54,6 +54,22 @@ class Puppeteer::Browser
|
|
|
54
54
|
@connection.on_event 'Target.targetInfoChanged', &method(:handle_target_info_changed)
|
|
55
55
|
end
|
|
56
56
|
|
|
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
|
+
# @param event_name [Symbol] either of :disconnected, :targetcreated, :targetchanged, :targetdestroyed
|
|
65
|
+
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(", ")}")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
add_event_listener(EVENT_MAPPINGS[event_name.to_sym], &block)
|
|
71
|
+
end
|
|
72
|
+
|
|
57
73
|
# @return [Puppeteer::BrowserRunner::BrowserProcess]
|
|
58
74
|
def process
|
|
59
75
|
@process
|
|
@@ -102,8 +118,7 @@ class Puppeteer::Browser
|
|
|
102
118
|
)
|
|
103
119
|
# assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated');
|
|
104
120
|
@targets[target_info.target_id] = target
|
|
105
|
-
|
|
106
|
-
target.on_initialize_succeeded do
|
|
121
|
+
if await target.initialized_promise
|
|
107
122
|
emit_event 'Events.Browser.TargetCreated', target
|
|
108
123
|
context.emit_event 'Events.BrowserContext.TargetCreated', target
|
|
109
124
|
end
|
|
@@ -118,10 +133,10 @@ class Puppeteer::Browser
|
|
|
118
133
|
def handle_target_destroyed(event)
|
|
119
134
|
target_id = event['targetId']
|
|
120
135
|
target = @targets[target_id]
|
|
121
|
-
target.
|
|
136
|
+
target.ignore_initialize_callback_promise
|
|
122
137
|
@targets.delete(target_id)
|
|
123
|
-
target.
|
|
124
|
-
target.
|
|
138
|
+
target.closed_callback
|
|
139
|
+
if await target.initialized_promise
|
|
125
140
|
emit_event 'Events.Browser.TargetDestroyed', target
|
|
126
141
|
target.browser_context.emit_event 'Events.BrowserContext.TargetDestroyed', target
|
|
127
142
|
end
|
|
@@ -192,6 +207,11 @@ class Puppeteer::Browser
|
|
|
192
207
|
targets.first { |target| target.type == 'browser' }
|
|
193
208
|
end
|
|
194
209
|
|
|
210
|
+
# used only in Target#opener
|
|
211
|
+
private def find_target_by_id(target_id)
|
|
212
|
+
@targets[target_id]
|
|
213
|
+
end
|
|
214
|
+
|
|
195
215
|
# @param {function(!Target):boolean} predicate
|
|
196
216
|
# @param {{timeout?: number}=} options
|
|
197
217
|
# @return {!Promise<!Target>}
|
|
@@ -29,8 +29,12 @@ module Puppeteer::ConcurrentRubyUtils
|
|
|
29
29
|
Concurrent::Promises.future(&block)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def resolvable_future
|
|
33
|
-
Concurrent::Promises.resolvable_future
|
|
32
|
+
def resolvable_future(&block)
|
|
33
|
+
future = Concurrent::Promises.resolvable_future
|
|
34
|
+
if block
|
|
35
|
+
block.call(future)
|
|
36
|
+
end
|
|
37
|
+
future
|
|
34
38
|
end
|
|
35
39
|
end
|
|
36
40
|
|
data/lib/puppeteer/connection.rb
CHANGED
|
@@ -44,7 +44,9 @@ class Puppeteer::Connection
|
|
|
44
44
|
|
|
45
45
|
@transport = transport
|
|
46
46
|
@transport.on_message do |data|
|
|
47
|
-
|
|
47
|
+
message = JSON.parse(data)
|
|
48
|
+
sleep_before_handling_message(message)
|
|
49
|
+
async_handle_message(message)
|
|
48
50
|
end
|
|
49
51
|
@transport.on_close do |reason, code|
|
|
50
52
|
handle_close(reason, code)
|
|
@@ -54,6 +56,16 @@ class Puppeteer::Connection
|
|
|
54
56
|
@closed = false
|
|
55
57
|
end
|
|
56
58
|
|
|
59
|
+
private def sleep_before_handling_message(message)
|
|
60
|
+
# Puppeteer doesn't handle any Network monitoring responses.
|
|
61
|
+
# So we don't have to sleep.
|
|
62
|
+
return if message['method']&.start_with?('Network.')
|
|
63
|
+
|
|
64
|
+
# For some reasons, sleeping a bit reduces trivial errors...
|
|
65
|
+
# 4ms is an interval of internal shared timer of WebKit.
|
|
66
|
+
sleep 0.004
|
|
67
|
+
end
|
|
68
|
+
|
|
57
69
|
def self.from_session(session)
|
|
58
70
|
session.connection
|
|
59
71
|
end
|
data/lib/puppeteer/dom_world.rb
CHANGED
|
@@ -97,17 +97,18 @@ class Puppeteer::DOMWorld
|
|
|
97
97
|
document.S(selector)
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
-
class DocumentEvaluationError < StandardError; end
|
|
101
|
-
|
|
102
100
|
private def evaluate_document
|
|
103
101
|
# sometimes execution_context.evaluate_handle('document') returns null object.
|
|
104
102
|
# D, [2020-04-24T02:17:51.023631 #220] DEBUG -- : RECV << {"id"=>20, "result"=>{"result"=>{"type"=>"object", "subtype"=>"null", "value"=>nil}}, "sessionId"=>"78E9CF1E14D81294E320E7C20E5CDE06"}
|
|
105
103
|
# retry if so.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
Timeout.timeout(3) do
|
|
105
|
+
loop do
|
|
106
|
+
handle = execution_context.evaluate_handle('document')
|
|
107
|
+
return handle if handle.is_a?(Puppeteer::ElementHandle)
|
|
108
|
+
end
|
|
109
109
|
end
|
|
110
|
-
|
|
110
|
+
rescue Timeout::Error
|
|
111
|
+
raise 'Bug of puppeteer-ruby...'
|
|
111
112
|
end
|
|
112
113
|
|
|
113
114
|
private def document
|
|
@@ -410,12 +411,10 @@ class Puppeteer::DOMWorld
|
|
|
410
411
|
# return new WaitTask(this, pageFunction, 'function', polling, timeout, ...args).promise;
|
|
411
412
|
# }
|
|
412
413
|
|
|
413
|
-
#
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
# return this.evaluate(() => document.title);
|
|
418
|
-
# }
|
|
414
|
+
# @return [String]
|
|
415
|
+
def title
|
|
416
|
+
evaluate('() => document.title')
|
|
417
|
+
end
|
|
419
418
|
|
|
420
419
|
# @param selector_or_xpath [String]
|
|
421
420
|
# @param is_xpath [Boolean]
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative './element_handle/bounding_box'
|
|
2
|
+
require_relative './element_handle/box_model'
|
|
3
|
+
require_relative './element_handle/point'
|
|
2
4
|
|
|
3
5
|
class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
4
6
|
include Puppeteer::IfPresent
|
|
@@ -53,29 +55,6 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
|
53
55
|
sleep 0.16
|
|
54
56
|
end
|
|
55
57
|
|
|
56
|
-
class Point
|
|
57
|
-
def initialize(x:, y:)
|
|
58
|
-
@x = x
|
|
59
|
-
@y = y
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def +(other)
|
|
63
|
-
Point.new(
|
|
64
|
-
x: @x + other.x,
|
|
65
|
-
y: @y + other.y,
|
|
66
|
-
)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def /(num)
|
|
70
|
-
Point.new(
|
|
71
|
-
x: @x / num,
|
|
72
|
-
y: @y / num,
|
|
73
|
-
)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
attr_reader :x, :y
|
|
77
|
-
end
|
|
78
|
-
|
|
79
58
|
class ElementNotVisibleError < StandardError
|
|
80
59
|
def initialize
|
|
81
60
|
super("Node is either not visible or not an HTMLElement")
|
|
@@ -105,15 +84,6 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
|
105
84
|
quads.first.reduce(:+) / 4
|
|
106
85
|
end
|
|
107
86
|
|
|
108
|
-
# /**
|
|
109
|
-
# * @return {!Promise<void|Protocol.DOM.getBoxModelReturnValue>}
|
|
110
|
-
# */
|
|
111
|
-
# _getBoxModel() {
|
|
112
|
-
# return this._client.send('DOM.getBoxModel', {
|
|
113
|
-
# objectId: this._remoteObject.objectId
|
|
114
|
-
# }).catch(error => debugError(error));
|
|
115
|
-
# }
|
|
116
|
-
|
|
117
87
|
# @param quad [Array<number>]
|
|
118
88
|
# @return [Array<Point>]
|
|
119
89
|
private def from_protocol_quad(quad)
|
|
@@ -265,89 +235,77 @@ class Puppeteer::ElementHandle < Puppeteer::JSHandle
|
|
|
265
235
|
press(key, delay: delay)
|
|
266
236
|
end
|
|
267
237
|
|
|
268
|
-
#
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
# return {x, y, width, height};
|
|
284
|
-
# }
|
|
285
|
-
|
|
286
|
-
# /**
|
|
287
|
-
# * @return {!Promise<?BoxModel>}
|
|
288
|
-
# */
|
|
289
|
-
# async boxModel() {
|
|
290
|
-
# const result = await this._getBoxModel();
|
|
291
|
-
|
|
292
|
-
# if (!result)
|
|
293
|
-
# return null;
|
|
294
|
-
|
|
295
|
-
# const {content, padding, border, margin, width, height} = result.model;
|
|
296
|
-
# return {
|
|
297
|
-
# content: this._fromProtocolQuad(content),
|
|
298
|
-
# padding: this._fromProtocolQuad(padding),
|
|
299
|
-
# border: this._fromProtocolQuad(border),
|
|
300
|
-
# margin: this._fromProtocolQuad(margin),
|
|
301
|
-
# width,
|
|
302
|
-
# height
|
|
303
|
-
# };
|
|
304
|
-
# }
|
|
305
|
-
|
|
306
|
-
# /**
|
|
307
|
-
# *
|
|
308
|
-
# * @param {!Object=} options
|
|
309
|
-
# * @returns {!Promise<string|!Buffer>}
|
|
310
|
-
# */
|
|
311
|
-
# async screenshot(options = {}) {
|
|
312
|
-
# let needsViewportReset = false;
|
|
313
|
-
|
|
314
|
-
# let boundingBox = await this.boundingBox();
|
|
315
|
-
# assert(boundingBox, 'Node is either not visible or not an HTMLElement');
|
|
316
|
-
|
|
317
|
-
# const viewport = this._page.viewport();
|
|
318
|
-
|
|
319
|
-
# if (viewport && (boundingBox.width > viewport.width || boundingBox.height > viewport.height)) {
|
|
320
|
-
# const newViewport = {
|
|
321
|
-
# width: Math.max(viewport.width, Math.ceil(boundingBox.width)),
|
|
322
|
-
# height: Math.max(viewport.height, Math.ceil(boundingBox.height)),
|
|
323
|
-
# };
|
|
324
|
-
# await this._page.setViewport(Object.assign({}, viewport, newViewport));
|
|
238
|
+
# @return [BoundingBox|nil]
|
|
239
|
+
def bounding_box
|
|
240
|
+
if_present(box_model) do |result_model|
|
|
241
|
+
quads = result_model.border
|
|
242
|
+
|
|
243
|
+
x = quads.map(&:x).min
|
|
244
|
+
y = quads.map(&:y).min
|
|
245
|
+
BoundingBox.new(
|
|
246
|
+
x: x,
|
|
247
|
+
y: y,
|
|
248
|
+
width: quads.map(&:x).max - x,
|
|
249
|
+
height: quads.map(&:y).max - y,
|
|
250
|
+
)
|
|
251
|
+
end
|
|
252
|
+
end
|
|
325
253
|
|
|
326
|
-
#
|
|
327
|
-
|
|
254
|
+
# @return [BoxModel|nil]
|
|
255
|
+
def box_model
|
|
256
|
+
if_present(@remote_object.box_model(@client)) do |result|
|
|
257
|
+
BoxModel.new(result['model'])
|
|
258
|
+
end
|
|
259
|
+
end
|
|
328
260
|
|
|
329
|
-
|
|
261
|
+
def screenshot(options = {})
|
|
262
|
+
needs_viewport_reset = false
|
|
330
263
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
264
|
+
box = bounding_box
|
|
265
|
+
unless box
|
|
266
|
+
raise ElementNotVisibleError.new
|
|
267
|
+
end
|
|
335
268
|
|
|
336
|
-
|
|
269
|
+
viewport = @page.viewport
|
|
270
|
+
if viewport && (box.width > viewport.width || box.height > viewport.height)
|
|
271
|
+
new_viewport = viewport.merge(
|
|
272
|
+
width: [viewport.width, box.width.to_i].min,
|
|
273
|
+
height: [viewport.height, box.height.to_i].min,
|
|
274
|
+
)
|
|
275
|
+
@page.viewport = new_viewport
|
|
337
276
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
277
|
+
needs_viewport_reset = true
|
|
278
|
+
end
|
|
279
|
+
scroll_into_view_if_needed
|
|
341
280
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
281
|
+
box = bounding_box
|
|
282
|
+
unless box
|
|
283
|
+
raise ElementNotVisibleError.new
|
|
284
|
+
end
|
|
285
|
+
if box.width == 0
|
|
286
|
+
raise 'Node has 0 width.'
|
|
287
|
+
end
|
|
288
|
+
if box.height == 0
|
|
289
|
+
raise 'Node has 0 height.'
|
|
290
|
+
end
|
|
345
291
|
|
|
346
|
-
|
|
347
|
-
|
|
292
|
+
layout_metrics = @client.send_message('Page.getLayoutMetrics')
|
|
293
|
+
page_x = layout_metrics["layoutViewport"]["pageX"]
|
|
294
|
+
page_y = layout_metrics["layoutViewport"]["pageY"]
|
|
295
|
+
|
|
296
|
+
clip = {
|
|
297
|
+
x: page_x + box.x,
|
|
298
|
+
y: page_y + box.y,
|
|
299
|
+
width: box.width,
|
|
300
|
+
height: box.height,
|
|
301
|
+
}
|
|
348
302
|
|
|
349
|
-
|
|
350
|
-
|
|
303
|
+
@page.screenshot({ clip: clip }.merge(options))
|
|
304
|
+
ensure
|
|
305
|
+
if needs_viewport_reset
|
|
306
|
+
@page.viewport = viewport
|
|
307
|
+
end
|
|
308
|
+
end
|
|
351
309
|
|
|
352
310
|
# `$()` in JavaScript. $ is not allowed to use as a method name in Ruby.
|
|
353
311
|
# @param selector [String]
|