ferrum 0.12 → 0.14
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 +28 -22
- data/lib/ferrum/browser/client.rb +6 -5
- data/lib/ferrum/browser/command.rb +9 -6
- data/lib/ferrum/browser/options/base.rb +1 -4
- data/lib/ferrum/browser/options/chrome.rb +22 -10
- data/lib/ferrum/browser/options/firefox.rb +3 -6
- data/lib/ferrum/browser/options.rb +84 -0
- data/lib/ferrum/browser/process.rb +6 -7
- data/lib/ferrum/browser/version_info.rb +71 -0
- data/lib/ferrum/browser/web_socket.rb +1 -1
- data/lib/ferrum/browser/xvfb.rb +1 -1
- data/lib/ferrum/browser.rb +184 -64
- data/lib/ferrum/context.rb +3 -2
- data/lib/ferrum/contexts.rb +2 -2
- data/lib/ferrum/cookies/cookie.rb +183 -0
- data/lib/ferrum/cookies.rb +122 -49
- data/lib/ferrum/dialog.rb +30 -0
- data/lib/ferrum/frame/dom.rb +177 -0
- data/lib/ferrum/frame/runtime.rb +41 -61
- data/lib/ferrum/frame.rb +91 -3
- data/lib/ferrum/headers.rb +28 -0
- data/lib/ferrum/keyboard.rb +45 -2
- data/lib/ferrum/mouse.rb +84 -0
- data/lib/ferrum/network/exchange.rb +104 -5
- data/lib/ferrum/network/intercepted_request.rb +3 -12
- data/lib/ferrum/network/request.rb +58 -19
- data/lib/ferrum/network/request_params.rb +57 -0
- data/lib/ferrum/network/response.rb +106 -4
- data/lib/ferrum/network.rb +193 -8
- data/lib/ferrum/node.rb +21 -1
- data/lib/ferrum/page/animation.rb +16 -0
- data/lib/ferrum/page/frames.rb +66 -11
- data/lib/ferrum/page/screenshot.rb +97 -0
- data/lib/ferrum/page/tracing.rb +26 -0
- data/lib/ferrum/page.rb +158 -45
- data/lib/ferrum/proxy.rb +91 -2
- data/lib/ferrum/target.rb +6 -4
- data/lib/ferrum/version.rb +1 -1
- metadata +7 -101
data/lib/ferrum/cookies.rb
CHANGED
@@ -1,68 +1,119 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "ferrum/cookies/cookie"
|
4
|
+
|
3
5
|
module Ferrum
|
4
6
|
class Cookies
|
5
|
-
|
6
|
-
attr_reader :attributes
|
7
|
-
|
8
|
-
def initialize(attributes)
|
9
|
-
@attributes = attributes
|
10
|
-
end
|
11
|
-
|
12
|
-
def name
|
13
|
-
@attributes["name"]
|
14
|
-
end
|
15
|
-
|
16
|
-
def value
|
17
|
-
@attributes["value"]
|
18
|
-
end
|
19
|
-
|
20
|
-
def domain
|
21
|
-
@attributes["domain"]
|
22
|
-
end
|
23
|
-
|
24
|
-
def path
|
25
|
-
@attributes["path"]
|
26
|
-
end
|
27
|
-
|
28
|
-
def samesite
|
29
|
-
@attributes["sameSite"]
|
30
|
-
end
|
31
|
-
|
32
|
-
def size
|
33
|
-
@attributes["size"]
|
34
|
-
end
|
7
|
+
include Enumerable
|
35
8
|
|
36
|
-
|
37
|
-
|
38
|
-
|
9
|
+
def initialize(page)
|
10
|
+
@page = page
|
11
|
+
end
|
39
12
|
|
40
|
-
|
41
|
-
|
42
|
-
|
13
|
+
#
|
14
|
+
# Enumerates over all cookies.
|
15
|
+
#
|
16
|
+
# @yield [cookie]
|
17
|
+
# The given block will be passed each cookie.
|
18
|
+
#
|
19
|
+
# @yieldparam [Cookie] cookie
|
20
|
+
# A cookie in the browser.
|
21
|
+
#
|
22
|
+
# @return [Enumerator]
|
23
|
+
# If no block is given, an Enumerator object will be returned.
|
24
|
+
#
|
25
|
+
def each
|
26
|
+
return enum_for(__method__) unless block_given?
|
43
27
|
|
44
|
-
|
45
|
-
@attributes["session"]
|
46
|
-
end
|
28
|
+
cookies = @page.command("Network.getAllCookies")["cookies"]
|
47
29
|
|
48
|
-
|
49
|
-
|
30
|
+
cookies.each do |c|
|
31
|
+
yield Cookie.new(c)
|
50
32
|
end
|
51
33
|
end
|
52
34
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
35
|
+
#
|
36
|
+
# Returns cookies hash.
|
37
|
+
#
|
38
|
+
# @return [Hash{String => Cookie}]
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# browser.cookies.all # => {
|
42
|
+
# # "NID" => #<Ferrum::Cookies::Cookie:0x0000558624b37a40 @attributes={
|
43
|
+
# # "name"=>"NID", "value"=>"...", "domain"=>".google.com", "path"=>"/",
|
44
|
+
# # "expires"=>1583211046.575681, "size"=>178, "httpOnly"=>true, "secure"=>false, "session"=>false
|
45
|
+
# # }>
|
46
|
+
# # }
|
47
|
+
#
|
57
48
|
def all
|
58
|
-
|
59
|
-
|
49
|
+
each.to_h do |cookie|
|
50
|
+
[cookie.name, cookie]
|
51
|
+
end
|
60
52
|
end
|
61
53
|
|
54
|
+
#
|
55
|
+
# Returns cookie.
|
56
|
+
#
|
57
|
+
# @param [String] name
|
58
|
+
# The cookie name to fetch.
|
59
|
+
#
|
60
|
+
# @return [Cookie, nil]
|
61
|
+
# The cookie with the matching name.
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
# browser.cookies["NID"] # =>
|
65
|
+
# # <Ferrum::Cookies::Cookie:0x0000558624b67a88 @attributes={
|
66
|
+
# # "name"=>"NID", "value"=>"...", "domain"=>".google.com",
|
67
|
+
# # "path"=>"/", "expires"=>1583211046.575681, "size"=>178,
|
68
|
+
# # "httpOnly"=>true, "secure"=>false, "session"=>false
|
69
|
+
# # }>
|
70
|
+
#
|
62
71
|
def [](name)
|
63
|
-
|
72
|
+
find { |cookie| cookie.name == name }
|
64
73
|
end
|
65
74
|
|
75
|
+
#
|
76
|
+
# Sets a cookie.
|
77
|
+
#
|
78
|
+
# @param [Hash{Symbol => Object}, Cookie] options
|
79
|
+
#
|
80
|
+
# @option options [String] :name
|
81
|
+
# The cookie param name.
|
82
|
+
#
|
83
|
+
# @option options [String] :value
|
84
|
+
# The cookie param value.
|
85
|
+
#
|
86
|
+
# @option options [String] :domain
|
87
|
+
# The domain the cookie belongs to.
|
88
|
+
#
|
89
|
+
# @option options [String] :path
|
90
|
+
# The path that the cookie is bound to.
|
91
|
+
#
|
92
|
+
# @option options [Integer] :expires
|
93
|
+
# When the cookie will expire.
|
94
|
+
#
|
95
|
+
# @option options [Integer] :size
|
96
|
+
# The size of the cookie.
|
97
|
+
#
|
98
|
+
# @option options [Boolean] :httponly
|
99
|
+
# Specifies whether the cookie `HttpOnly`.
|
100
|
+
#
|
101
|
+
# @option options [Boolean] :secure
|
102
|
+
# Specifies whether the cookie is marked as `Secure`.
|
103
|
+
#
|
104
|
+
# @option options [String] :samesite
|
105
|
+
# Specifies whether the cookie is `SameSite`.
|
106
|
+
#
|
107
|
+
# @option options [Boolean] :session
|
108
|
+
# Specifies whether the cookie is a session cookie.
|
109
|
+
#
|
110
|
+
# @example
|
111
|
+
# browser.cookies.set(name: "stealth", value: "omg", domain: "google.com") # => true
|
112
|
+
#
|
113
|
+
# @example
|
114
|
+
# nid_cookie = browser.cookies["NID"] # => <Ferrum::Cookies::Cookie:0x0000558624b67a88>
|
115
|
+
# browser.cookies.set(nid_cookie) # => true
|
116
|
+
#
|
66
117
|
def set(options)
|
67
118
|
cookie = (
|
68
119
|
options.is_a?(Cookie) ? options.attributes : options
|
@@ -79,7 +130,21 @@ module Ferrum
|
|
79
130
|
@page.command("Network.setCookie", **cookie)["success"]
|
80
131
|
end
|
81
132
|
|
82
|
-
#
|
133
|
+
#
|
134
|
+
# Removes given cookie.
|
135
|
+
#
|
136
|
+
# @param [String] name
|
137
|
+
#
|
138
|
+
# @param [Hash{Symbol => Object}] options
|
139
|
+
# Additional keyword arguments.
|
140
|
+
#
|
141
|
+
# @option options [String] :domain
|
142
|
+
#
|
143
|
+
# @option options [String] :url
|
144
|
+
#
|
145
|
+
# @example
|
146
|
+
# browser.cookies.remove(name: "stealth", domain: "google.com") # => true
|
147
|
+
#
|
83
148
|
def remove(name:, **options)
|
84
149
|
raise "Specify :domain or :url option" if !options[:domain] && !options[:url] && !default_domain
|
85
150
|
|
@@ -91,6 +156,14 @@ module Ferrum
|
|
91
156
|
true
|
92
157
|
end
|
93
158
|
|
159
|
+
#
|
160
|
+
# Removes all cookies for current page.
|
161
|
+
#
|
162
|
+
# @return [true]
|
163
|
+
#
|
164
|
+
# @example
|
165
|
+
# browser.cookies.clear # => true
|
166
|
+
#
|
94
167
|
def clear
|
95
168
|
@page.command("Network.clearBrowserCookies")
|
96
169
|
true
|
data/lib/ferrum/dialog.rb
CHANGED
@@ -10,6 +10,22 @@ module Ferrum
|
|
10
10
|
@default_prompt = params["defaultPrompt"]
|
11
11
|
end
|
12
12
|
|
13
|
+
#
|
14
|
+
# Accept dialog with given text or default prompt if applicable
|
15
|
+
#
|
16
|
+
# @param [String, nil] prompt_text
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# browser = Ferrum::Browser.new
|
20
|
+
# browser.on(:dialog) do |dialog|
|
21
|
+
# if dialog.match?(/bla-bla/)
|
22
|
+
# dialog.accept
|
23
|
+
# else
|
24
|
+
# dialog.dismiss
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# browser.go_to("https://google.com")
|
28
|
+
#
|
13
29
|
def accept(prompt_text = nil)
|
14
30
|
options = { accept: true }
|
15
31
|
response = prompt_text || default_prompt
|
@@ -17,6 +33,20 @@ module Ferrum
|
|
17
33
|
@page.command("Page.handleJavaScriptDialog", slowmoable: true, **options)
|
18
34
|
end
|
19
35
|
|
36
|
+
#
|
37
|
+
# Dismiss dialog.
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# browser = Ferrum::Browser.new
|
41
|
+
# browser.on(:dialog) do |dialog|
|
42
|
+
# if dialog.match?(/bla-bla/)
|
43
|
+
# dialog.accept
|
44
|
+
# else
|
45
|
+
# dialog.dismiss
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
# browser.go_to("https://google.com")
|
49
|
+
#
|
20
50
|
def dismiss
|
21
51
|
@page.command("Page.handleJavaScriptDialog", slowmoable: true, accept: false)
|
22
52
|
end
|
data/lib/ferrum/frame/dom.rb
CHANGED
@@ -20,10 +20,59 @@
|
|
20
20
|
module Ferrum
|
21
21
|
class Frame
|
22
22
|
module DOM
|
23
|
+
SCRIPT_SRC_TAG = <<~JS
|
24
|
+
const script = document.createElement("script");
|
25
|
+
script.src = arguments[0];
|
26
|
+
script.type = arguments[1];
|
27
|
+
script.onload = arguments[2];
|
28
|
+
document.head.appendChild(script);
|
29
|
+
JS
|
30
|
+
SCRIPT_TEXT_TAG = <<~JS
|
31
|
+
const script = document.createElement("script");
|
32
|
+
script.text = arguments[0];
|
33
|
+
script.type = arguments[1];
|
34
|
+
document.head.appendChild(script);
|
35
|
+
arguments[2]();
|
36
|
+
JS
|
37
|
+
STYLE_TAG = <<~JS
|
38
|
+
const style = document.createElement("style");
|
39
|
+
style.type = "text/css";
|
40
|
+
style.appendChild(document.createTextNode(arguments[0]));
|
41
|
+
document.head.appendChild(style);
|
42
|
+
arguments[1]();
|
43
|
+
JS
|
44
|
+
LINK_TAG = <<~JS
|
45
|
+
const link = document.createElement("link");
|
46
|
+
link.rel = "stylesheet";
|
47
|
+
link.href = arguments[0];
|
48
|
+
link.onload = arguments[1];
|
49
|
+
document.head.appendChild(link);
|
50
|
+
JS
|
51
|
+
|
52
|
+
#
|
53
|
+
# Returns current top window `location href`.
|
54
|
+
#
|
55
|
+
# @return [String]
|
56
|
+
# The window's current URL.
|
57
|
+
#
|
58
|
+
# @example
|
59
|
+
# browser.go_to("https://google.com/")
|
60
|
+
# browser.current_url # => "https://www.google.com/"
|
61
|
+
#
|
23
62
|
def current_url
|
24
63
|
evaluate("window.top.location.href")
|
25
64
|
end
|
26
65
|
|
66
|
+
#
|
67
|
+
# Returns current top window title.
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
# The window's current title.
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
# browser.go_to("https://google.com/")
|
74
|
+
# browser.current_title # => "Google"
|
75
|
+
#
|
27
76
|
def current_title
|
28
77
|
evaluate("window.top.document.title")
|
29
78
|
end
|
@@ -32,10 +81,36 @@ module Ferrum
|
|
32
81
|
evaluate("document.doctype && new XMLSerializer().serializeToString(document.doctype)")
|
33
82
|
end
|
34
83
|
|
84
|
+
#
|
85
|
+
# Returns current page's html.
|
86
|
+
#
|
87
|
+
# @return [String]
|
88
|
+
# The HTML source of the current page.
|
89
|
+
#
|
90
|
+
# @example
|
91
|
+
# browser.go_to("https://google.com/")
|
92
|
+
# browser.body # => '<html itemscope="" itemtype="http://schema.org/WebPage" lang="ru"><head>...
|
93
|
+
#
|
35
94
|
def body
|
36
95
|
evaluate("document.documentElement.outerHTML")
|
37
96
|
end
|
38
97
|
|
98
|
+
#
|
99
|
+
# Finds nodes by using a XPath selector.
|
100
|
+
#
|
101
|
+
# @param [String] selector
|
102
|
+
# The XPath selector.
|
103
|
+
#
|
104
|
+
# @param [Node, nil] within
|
105
|
+
# The parent node to search within.
|
106
|
+
#
|
107
|
+
# @return [Array<Node>]
|
108
|
+
# The matching nodes.
|
109
|
+
#
|
110
|
+
# @example
|
111
|
+
# browser.go_to("https://github.com/")
|
112
|
+
# browser.xpath("//a[@aria-label='Issues you created']") # => [Node]
|
113
|
+
#
|
39
114
|
def xpath(selector, within: nil)
|
40
115
|
expr = <<~JS
|
41
116
|
function(selector, within) {
|
@@ -54,6 +129,22 @@ module Ferrum
|
|
54
129
|
evaluate_func(expr, selector, within)
|
55
130
|
end
|
56
131
|
|
132
|
+
#
|
133
|
+
# Finds a node by using a XPath selector.
|
134
|
+
#
|
135
|
+
# @param [String] selector
|
136
|
+
# The XPath selector.
|
137
|
+
#
|
138
|
+
# @param [Node, nil] within
|
139
|
+
# The parent node to search within.
|
140
|
+
#
|
141
|
+
# @return [Node, nil]
|
142
|
+
# The matching node.
|
143
|
+
#
|
144
|
+
# @example
|
145
|
+
# browser.go_to("https://github.com/")
|
146
|
+
# browser.at_xpath("//a[@aria-label='Issues you created']") # => Node
|
147
|
+
#
|
57
148
|
def at_xpath(selector, within: nil)
|
58
149
|
expr = <<~JS
|
59
150
|
function(selector, within) {
|
@@ -65,6 +156,22 @@ module Ferrum
|
|
65
156
|
evaluate_func(expr, selector, within)
|
66
157
|
end
|
67
158
|
|
159
|
+
#
|
160
|
+
# Finds nodes by using a CSS path selector.
|
161
|
+
#
|
162
|
+
# @param [String] selector
|
163
|
+
# The CSS path selector.
|
164
|
+
#
|
165
|
+
# @param [Node, nil] within
|
166
|
+
# The parent node to search within.
|
167
|
+
#
|
168
|
+
# @return [Array<Node>]
|
169
|
+
# The matching nodes.
|
170
|
+
#
|
171
|
+
# @example
|
172
|
+
# browser.go_to("https://github.com/")
|
173
|
+
# browser.css("a[aria-label='Issues you created']") # => [Node]
|
174
|
+
#
|
68
175
|
def css(selector, within: nil)
|
69
176
|
expr = <<~JS
|
70
177
|
function(selector, within) {
|
@@ -76,6 +183,22 @@ module Ferrum
|
|
76
183
|
evaluate_func(expr, selector, within)
|
77
184
|
end
|
78
185
|
|
186
|
+
#
|
187
|
+
# Finds a node by using a CSS path selector.
|
188
|
+
#
|
189
|
+
# @param [String] selector
|
190
|
+
# The CSS path selector.
|
191
|
+
#
|
192
|
+
# @param [Node, nil] within
|
193
|
+
# The parent node to search within.
|
194
|
+
#
|
195
|
+
# @return [Node, nil]
|
196
|
+
# The matching node.
|
197
|
+
#
|
198
|
+
# @example
|
199
|
+
# browser.go_to("https://github.com/")
|
200
|
+
# browser.at_css("a[aria-label='Issues you created']") # => Node
|
201
|
+
#
|
79
202
|
def at_css(selector, within: nil)
|
80
203
|
expr = <<~JS
|
81
204
|
function(selector, within) {
|
@@ -86,6 +209,60 @@ module Ferrum
|
|
86
209
|
|
87
210
|
evaluate_func(expr, selector, within)
|
88
211
|
end
|
212
|
+
|
213
|
+
#
|
214
|
+
# Adds a `<script>` tag to the document.
|
215
|
+
#
|
216
|
+
# @param [String, nil] url
|
217
|
+
#
|
218
|
+
# @param [String, nil] path
|
219
|
+
#
|
220
|
+
# @param [String, nil] content
|
221
|
+
#
|
222
|
+
# @param [String] type
|
223
|
+
#
|
224
|
+
# @example
|
225
|
+
# browser.add_script_tag(url: "http://example.com/stylesheet.css") # => true
|
226
|
+
#
|
227
|
+
def add_script_tag(url: nil, path: nil, content: nil, type: "text/javascript")
|
228
|
+
expr, *args = if url
|
229
|
+
[SCRIPT_SRC_TAG, url, type]
|
230
|
+
elsif path || content
|
231
|
+
if path
|
232
|
+
content = File.read(path)
|
233
|
+
content += "\n//# sourceURL=#{path}"
|
234
|
+
end
|
235
|
+
[SCRIPT_TEXT_TAG, content, type]
|
236
|
+
end
|
237
|
+
|
238
|
+
evaluate_async(expr, @page.timeout, *args)
|
239
|
+
end
|
240
|
+
|
241
|
+
#
|
242
|
+
# Adds a `<style>` tag to the document.
|
243
|
+
#
|
244
|
+
# @param [String, nil] url
|
245
|
+
#
|
246
|
+
# @param [String, nil] path
|
247
|
+
#
|
248
|
+
# @param [String, nil] content
|
249
|
+
#
|
250
|
+
# @example
|
251
|
+
# browser.add_style_tag(content: "h1 { font-size: 40px; }") # => true
|
252
|
+
#
|
253
|
+
def add_style_tag(url: nil, path: nil, content: nil)
|
254
|
+
expr, *args = if url
|
255
|
+
[LINK_TAG, url]
|
256
|
+
elsif path || content
|
257
|
+
if path
|
258
|
+
content = File.read(path)
|
259
|
+
content += "\n//# sourceURL=#{path}"
|
260
|
+
end
|
261
|
+
[STYLE_TAG, content]
|
262
|
+
end
|
263
|
+
|
264
|
+
evaluate_async(expr, @page.timeout, *args)
|
265
|
+
end
|
89
266
|
end
|
90
267
|
end
|
91
268
|
end
|
data/lib/ferrum/frame/runtime.rb
CHANGED
@@ -16,40 +16,38 @@ module Ferrum
|
|
16
16
|
INTERMITTENT_ATTEMPTS = ENV.fetch("FERRUM_INTERMITTENT_ATTEMPTS", 6).to_i
|
17
17
|
INTERMITTENT_SLEEP = ENV.fetch("FERRUM_INTERMITTENT_SLEEP", 0.1).to_f
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
arguments[2]();
|
32
|
-
JS
|
33
|
-
STYLE_TAG = <<~JS
|
34
|
-
const style = document.createElement("style");
|
35
|
-
style.type = "text/css";
|
36
|
-
style.appendChild(document.createTextNode(arguments[0]));
|
37
|
-
document.head.appendChild(style);
|
38
|
-
arguments[1]();
|
39
|
-
JS
|
40
|
-
LINK_TAG = <<~JS
|
41
|
-
const link = document.createElement("link");
|
42
|
-
link.rel = "stylesheet";
|
43
|
-
link.href = arguments[0];
|
44
|
-
link.onload = arguments[1];
|
45
|
-
document.head.appendChild(link);
|
46
|
-
JS
|
47
|
-
|
19
|
+
#
|
20
|
+
# Evaluate and return result for given JS expression.
|
21
|
+
#
|
22
|
+
# @param [String] expression
|
23
|
+
# The JavaScript to evaluate.
|
24
|
+
#
|
25
|
+
# @param [Array] args
|
26
|
+
# Additional arguments to pass to the JavaScript code.
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# browser.evaluate("[window.scrollX, window.scrollY]")
|
30
|
+
#
|
48
31
|
def evaluate(expression, *args)
|
49
32
|
expression = format("function() { return %s }", expression)
|
50
33
|
call(expression: expression, arguments: args)
|
51
34
|
end
|
52
35
|
|
36
|
+
#
|
37
|
+
# Evaluate asynchronous expression and return result.
|
38
|
+
#
|
39
|
+
# @param [String] expression
|
40
|
+
# The JavaScript to evaluate.
|
41
|
+
#
|
42
|
+
# @param [Integer] wait
|
43
|
+
# How long we should wait for Promise to resolve or reject.
|
44
|
+
#
|
45
|
+
# @param [Array] args
|
46
|
+
# Additional arguments to pass to the JavaScript code.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# browser.evaluate_async(%(arguments[0]({foo: "bar"})), 5) # => { "foo" => "bar" }
|
50
|
+
#
|
53
51
|
def evaluate_async(expression, wait, *args)
|
54
52
|
template = <<~JS
|
55
53
|
function() {
|
@@ -70,6 +68,18 @@ module Ferrum
|
|
70
68
|
call(expression: expression, arguments: args, awaitPromise: true)
|
71
69
|
end
|
72
70
|
|
71
|
+
#
|
72
|
+
# Execute expression. Doesn't return the result.
|
73
|
+
#
|
74
|
+
# @param [String] expression
|
75
|
+
# The JavaScript to evaluate.
|
76
|
+
#
|
77
|
+
# @param [Array] args
|
78
|
+
# Additional arguments to pass to the JavaScript code.
|
79
|
+
#
|
80
|
+
# @example
|
81
|
+
# browser.execute(%(1 + 1)) # => true
|
82
|
+
#
|
73
83
|
def execute(expression, *args)
|
74
84
|
expression = format("function() { %s }", expression)
|
75
85
|
call(expression: expression, arguments: args, handle: false, returnByValue: true)
|
@@ -87,42 +97,12 @@ module Ferrum
|
|
87
97
|
call(expression: expression, on: node, wait: wait, **options)
|
88
98
|
end
|
89
99
|
|
90
|
-
def add_script_tag(url: nil, path: nil, content: nil, type: "text/javascript")
|
91
|
-
expr, *args = if url
|
92
|
-
[SCRIPT_SRC_TAG, url, type]
|
93
|
-
elsif path || content
|
94
|
-
if path
|
95
|
-
content = File.read(path)
|
96
|
-
content += "\n//# sourceURL=#{path}"
|
97
|
-
end
|
98
|
-
[SCRIPT_TEXT_TAG, content, type]
|
99
|
-
end
|
100
|
-
|
101
|
-
evaluate_async(expr, @page.timeout, *args)
|
102
|
-
end
|
103
|
-
|
104
|
-
def add_style_tag(url: nil, path: nil, content: nil)
|
105
|
-
expr, *args = if url
|
106
|
-
[LINK_TAG, url]
|
107
|
-
elsif path || content
|
108
|
-
if path
|
109
|
-
content = File.read(path)
|
110
|
-
content += "\n//# sourceURL=#{path}"
|
111
|
-
end
|
112
|
-
[STYLE_TAG, content]
|
113
|
-
end
|
114
|
-
|
115
|
-
evaluate_async(expr, @page.timeout, *args)
|
116
|
-
end
|
117
|
-
|
118
100
|
private
|
119
101
|
|
120
102
|
def call(expression:, arguments: [], on: nil, wait: 0, handle: true, **options)
|
121
103
|
errors = [NodeNotFoundError, NoExecutionContextError]
|
122
|
-
sleep = INTERMITTENT_SLEEP
|
123
|
-
attempts = INTERMITTENT_ATTEMPTS
|
124
104
|
|
125
|
-
Utils::Attempt.with_retry(errors: errors, max:
|
105
|
+
Utils::Attempt.with_retry(errors: errors, max: INTERMITTENT_ATTEMPTS, wait: INTERMITTENT_SLEEP) do
|
126
106
|
params = options.dup
|
127
107
|
|
128
108
|
if on
|
@@ -132,7 +112,7 @@ module Ferrum
|
|
132
112
|
end
|
133
113
|
|
134
114
|
if params[:executionContextId].nil? && params[:objectId].nil?
|
135
|
-
params = params.merge(executionContextId: execution_id)
|
115
|
+
params = params.merge(executionContextId: execution_id!)
|
136
116
|
end
|
137
117
|
|
138
118
|
response = @page.command("Runtime.callFunctionOn",
|