ferrum 0.7 → 0.10.2
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/LICENSE +1 -1
- data/README.md +325 -86
- data/lib/ferrum.rb +35 -7
- data/lib/ferrum/browser.rb +14 -10
- data/lib/ferrum/browser/client.rb +8 -6
- data/lib/ferrum/browser/command.rb +26 -25
- data/lib/ferrum/browser/options/base.rb +46 -0
- data/lib/ferrum/browser/options/chrome.rb +73 -0
- data/lib/ferrum/browser/options/firefox.rb +34 -0
- data/lib/ferrum/browser/process.rb +24 -12
- data/lib/ferrum/browser/subscriber.rb +5 -1
- data/lib/ferrum/browser/web_socket.rb +23 -4
- data/lib/ferrum/browser/xvfb.rb +37 -0
- data/lib/ferrum/context.rb +3 -3
- data/lib/ferrum/cookies.rb +7 -0
- data/lib/ferrum/dialog.rb +2 -2
- data/lib/ferrum/frame.rb +20 -3
- data/lib/ferrum/frame/dom.rb +34 -37
- data/lib/ferrum/frame/runtime.rb +90 -84
- data/lib/ferrum/keyboard.rb +3 -3
- data/lib/ferrum/mouse.rb +14 -3
- data/lib/ferrum/network.rb +23 -6
- data/lib/ferrum/network/error.rb +8 -15
- data/lib/ferrum/network/intercepted_request.rb +1 -1
- data/lib/ferrum/node.rb +70 -26
- data/lib/ferrum/page.rb +45 -17
- data/lib/ferrum/page/frames.rb +17 -3
- data/lib/ferrum/page/screenshot.rb +64 -12
- data/lib/ferrum/rbga.rb +38 -0
- data/lib/ferrum/version.rb +1 -1
- metadata +12 -9
- data/lib/ferrum/browser/chrome.rb +0 -76
- data/lib/ferrum/browser/firefox.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2256dbc8ed2c2fca2e3209c13e29009c69b4c2ccf328e8a73ade73ed69c89f0
|
4
|
+
data.tar.gz: 8d5604f8d4f8120b699ec3e341c37f77f25e90a794d3206660ecc0465b22e7b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7aa18fd5a01f387c27ade8ecdf6aa30df8118f4e90badddc242ed979e5be49c890036049f284555a937ccc79699bcbc954d62c077f45ff0770d9eeeec255a6ea
|
7
|
+
data.tar.gz: 25c4cc92e59a297a344cf85301a21c3f9e634f25ea685eb6c9d2f4ea1896fcba2898dc5f4cfcc8f3af358001a0e451034bb79bf24981e16a17a51cdd3f07d6a3
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,62 +1,83 @@
|
|
1
|
-
# Ferrum -
|
1
|
+
# Ferrum - high-level API to control Chrome in Ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
<img align="right" width="95" height="95"
|
3
|
+
<img align="right"
|
4
|
+
width="320" height="241"
|
6
5
|
alt="Ferrum logo"
|
7
|
-
src="https://raw.githubusercontent.com/
|
6
|
+
src="https://raw.githubusercontent.com/rubycdp/ferrum/master/logo.svg?sanitize=true">
|
7
|
+
|
8
|
+
#### As simple as Puppeteer, though even simpler.
|
8
9
|
|
9
|
-
|
10
|
+
It is Ruby clean and high-level API to Chrome. Runs headless by default, but you
|
11
|
+
can configure it to run in a headful mode. All you need is Ruby and
|
12
|
+
[Chrome](https://www.google.com/chrome/) or
|
13
|
+
[Chromium](https://www.chromium.org/). Ferrum connects to the browser by [CDP
|
14
|
+
protocol](https://chromedevtools.github.io/devtools-protocol/) and there's _no_
|
15
|
+
Selenium/WebDriver/ChromeDriver dependency. The emphasis was made on a raw CDP
|
16
|
+
protocol because Chrome allows you to do so many things that are barely
|
17
|
+
supported by WebDriver because it should have consistent design with other
|
18
|
+
browsers.
|
10
19
|
|
11
|
-
|
12
|
-
|
13
|
-
|
20
|
+
* [Cuprite](https://github.com/rubycdp/cuprite) is a pure Ruby driver for
|
21
|
+
[Capybara](https://github.com/teamcapybara/capybara) based on Ferrum. If you are
|
22
|
+
going to crawl sites you better use Ferrum or
|
23
|
+
[Vessel](https://github.com/rubycdp/vessel) because you crawl, not test.
|
14
24
|
|
15
|
-
[
|
16
|
-
|
17
|
-
|
18
|
-
is what Ruby was missing, so here it comes.
|
25
|
+
* [Vessel](https://github.com/rubycdp/vessel) high-level web crawling framework
|
26
|
+
based on Ferrum. It looks like [Scrapy](https://scrapy.org/) except that it uses
|
27
|
+
a real browser in order to grab data.
|
19
28
|
|
20
|
-
[
|
21
|
-
|
29
|
+
Web design by [Evrone](https://evrone.com/), what else
|
30
|
+
[we build with Ruby on Rails](https://evrone.com/ruby), what else
|
31
|
+
[we do at Evrone](https://evrone.com/cases#case-studies).
|
22
32
|
|
23
|
-
If you like this project, please consider to _[become a backer](https://www.patreon.com/rferrum)_
|
24
|
-
on Patreon.
|
25
33
|
|
26
34
|
## Index
|
27
35
|
|
28
|
-
* [
|
29
|
-
* [
|
30
|
-
* [
|
31
|
-
* [
|
32
|
-
* [
|
33
|
-
* [
|
34
|
-
* [
|
35
|
-
* [
|
36
|
-
* [
|
37
|
-
* [
|
38
|
-
* [
|
39
|
-
* [
|
36
|
+
* [Install](https://github.com/rubycdp/ferrum#install)
|
37
|
+
* [Examples](https://github.com/rubycdp/ferrum#examples)
|
38
|
+
* [Docker](https://github.com/rubycdp/ferrum#docker)
|
39
|
+
* [Customization](https://github.com/rubycdp/ferrum#customization)
|
40
|
+
* [Navigation](https://github.com/rubycdp/ferrum#navigation)
|
41
|
+
* [Finders](https://github.com/rubycdp/ferrum#finders)
|
42
|
+
* [Screenshots](https://github.com/rubycdp/ferrum#screenshots)
|
43
|
+
* [Network](https://github.com/rubycdp/ferrum#network)
|
44
|
+
* [Mouse](https://github.com/rubycdp/ferrum#mouse)
|
45
|
+
* [Keyboard](https://github.com/rubycdp/ferrum#keyboard)
|
46
|
+
* [Cookies](https://github.com/rubycdp/ferrum#cookies)
|
47
|
+
* [Headers](https://github.com/rubycdp/ferrum#headers)
|
48
|
+
* [JavaScript](https://github.com/rubycdp/ferrum#javascript)
|
49
|
+
* [Frames](https://github.com/rubycdp/ferrum#frames)
|
50
|
+
* [Frame](https://github.com/rubycdp/ferrum#frame)
|
51
|
+
* [Dialog](https://github.com/rubycdp/ferrum#dialog)
|
52
|
+
* [Thread safety](https://github.com/rubycdp/ferrum#thread-safety)
|
53
|
+
* [Development](https://github.com/rubycdp/ferrum#development)
|
54
|
+
* [Contributing](https://github.com/rubycdp/ferrum#contributing)
|
55
|
+
* [License](https://github.com/rubycdp/ferrum#license)
|
56
|
+
|
40
57
|
|
41
58
|
## Install
|
42
59
|
|
43
60
|
There's no official Chrome or Chromium package for Linux don't install it this
|
44
|
-
way because it either
|
45
|
-
|
61
|
+
way because it's either outdated or unofficial, both are bad. Download it from
|
62
|
+
official [source](https://www.chromium.org/getting-involved/download-chromium).
|
46
63
|
Chrome binary should be in the `PATH` or `BROWSER_PATH` or you can pass it as an
|
47
|
-
option to browser instance `:browser_path
|
64
|
+
option to browser instance see `:browser_path` in
|
65
|
+
[Customization](https://github.com/rubycdp/ferrum#customization).
|
48
66
|
|
49
|
-
Add this to your Gemfile
|
67
|
+
Add this to your `Gemfile` and run `bundle install`.
|
50
68
|
|
51
69
|
``` ruby
|
52
70
|
gem "ferrum"
|
53
71
|
```
|
54
72
|
|
73
|
+
|
74
|
+
## Examples
|
75
|
+
|
55
76
|
Navigate to a website and save a screenshot:
|
56
77
|
|
57
78
|
```ruby
|
58
79
|
browser = Ferrum::Browser.new
|
59
|
-
browser.
|
80
|
+
browser.go_to("https://google.com")
|
60
81
|
browser.screenshot(path: "google.png")
|
61
82
|
browser.quit
|
62
83
|
```
|
@@ -65,10 +86,10 @@ Interact with a page:
|
|
65
86
|
|
66
87
|
```ruby
|
67
88
|
browser = Ferrum::Browser.new
|
68
|
-
browser.
|
69
|
-
input = browser.at_xpath("//
|
89
|
+
browser.go_to("https://google.com")
|
90
|
+
input = browser.at_xpath("//input[@name='q']")
|
70
91
|
input.focus.type("Ruby headless driver for Chrome", :Enter)
|
71
|
-
browser.at_css("a > h3").text # => "
|
92
|
+
browser.at_css("a > h3").text # => "rubycdp/ferrum: Ruby Chrome/Chromium driver - GitHub"
|
72
93
|
browser.quit
|
73
94
|
```
|
74
95
|
|
@@ -76,7 +97,7 @@ Evaluate some JavaScript and get full width/height:
|
|
76
97
|
|
77
98
|
```ruby
|
78
99
|
browser = Ferrum::Browser.new
|
79
|
-
browser.
|
100
|
+
browser.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
|
80
101
|
width, height = browser.evaluate <<~JS
|
81
102
|
[document.documentElement.offsetWidth,
|
82
103
|
document.documentElement.offsetHeight]
|
@@ -90,7 +111,7 @@ Do any mouse movements you like:
|
|
90
111
|
```ruby
|
91
112
|
# Trace a 100x100 square
|
92
113
|
browser = Ferrum::Browser.new
|
93
|
-
browser.
|
114
|
+
browser.go_to("https://google.com")
|
94
115
|
browser.mouse
|
95
116
|
.move(x: 0, y: 0)
|
96
117
|
.down
|
@@ -103,7 +124,17 @@ browser.mouse
|
|
103
124
|
browser.quit
|
104
125
|
```
|
105
126
|
|
106
|
-
|
127
|
+
|
128
|
+
## Docker
|
129
|
+
|
130
|
+
In docker as root you must pass the no-sandbox browser option:
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
Ferrum::Browser.new(browser_options: { 'no-sandbox': nil })
|
134
|
+
```
|
135
|
+
|
136
|
+
|
137
|
+
## Customization
|
107
138
|
|
108
139
|
You can customize options with the following code in your test setup:
|
109
140
|
|
@@ -113,6 +144,7 @@ Ferrum::Browser.new(options)
|
|
113
144
|
|
114
145
|
* options `Hash`
|
115
146
|
* `:headless` (Boolean) - Set browser as headless or not, `true` by default.
|
147
|
+
* `:xvfb` (Boolean) - Run browser in a virtual framebuffer, `false` by default.
|
116
148
|
* `:window_size` (Array) - The dimensions of the browser window in which to
|
117
149
|
test, expressed as a 2-element array, e.g. [1024, 768]. Default: [1024, 768]
|
118
150
|
* `:extensions` (Array[String | Hash]) - An array of paths to files or JS
|
@@ -120,32 +152,39 @@ Ferrum::Browser.new(options)
|
|
120
152
|
`["/path/to/script.js", { source: "window.secret = 'top'" }]`
|
121
153
|
* `:logger` (Object responding to `puts`) - When present, debug output is
|
122
154
|
written to this object.
|
123
|
-
* `:slowmo` (Integer | Float) - Set a delay to wait before sending command.
|
155
|
+
* `:slowmo` (Integer | Float) - Set a delay in seconds to wait before sending command.
|
124
156
|
Usefull companion of headless option, so that you have time to see changes.
|
125
157
|
* `:timeout` (Numeric) - The number of seconds we'll wait for a response when
|
126
158
|
communicating with browser. Default is 5.
|
127
159
|
* `:js_errors` (Boolean) - When true, JavaScript errors get re-raised in Ruby.
|
160
|
+
* `:pending_connection_errors` (Boolean) - When main frame is still waiting for slow responses while timeout is
|
161
|
+
reached `PendingConnectionsError` is raised. It's better to figure out why you have slow responses and fix or
|
162
|
+
block them rather than turn this setting off. Default is true.
|
128
163
|
* `:browser_name` (Symbol) - `:chrome` by default, only experimental support
|
129
164
|
for `:firefox` for now.
|
130
|
-
* `:browser_path` (String) - Path to
|
165
|
+
* `:browser_path` (String) - Path to Chrome binary, you can also set ENV
|
131
166
|
variable as `BROWSER_PATH=some/path/chrome bundle exec rspec`.
|
132
167
|
* `:browser_options` (Hash) - Additional command line options,
|
133
168
|
[see them all](https://peter.sh/experiments/chromium-command-line-switches/)
|
134
169
|
e.g. `{ "ignore-certificate-errors" => nil }`
|
170
|
+
* `:ignore_default_browser_options` (Boolean) - Ferrum has a number of default
|
171
|
+
options it passes to the browser, if you set this to `true` then only
|
172
|
+
options you put in `:browser_options` will be passed to the browser,
|
173
|
+
except required ones of course.
|
135
174
|
* `:port` (Integer) - Remote debugging port for headless Chrome
|
136
175
|
* `:host` (String) - Remote debugging address for headless Chrome
|
137
176
|
* `:url` (String) - URL for a running instance of Chrome. If this is set, a
|
138
177
|
browser process will not be spawned.
|
139
178
|
* `:process_timeout` (Integer) - How long to wait for the Chrome process to
|
140
179
|
respond on startup
|
141
|
-
|
142
|
-
|
143
|
-
|
180
|
+
* `:ws_max_receive_size` (Integer) - How big messages to accept from Chrome
|
181
|
+
over the web socket, in bytes. Defaults to 64MB. Incoming messages larger
|
182
|
+
than this will cause a `Ferrum::DeadBrowserError`.
|
144
183
|
|
145
184
|
|
146
185
|
## Navigation
|
147
186
|
|
148
|
-
####
|
187
|
+
#### go_to(url) : `String`
|
149
188
|
|
150
189
|
Navigate page to.
|
151
190
|
|
@@ -153,7 +192,7 @@ Navigate page to.
|
|
153
192
|
configuring driver.
|
154
193
|
|
155
194
|
```ruby
|
156
|
-
browser.
|
195
|
+
browser.go_to("https://github.com/")
|
157
196
|
```
|
158
197
|
|
159
198
|
#### back
|
@@ -161,7 +200,7 @@ browser.goto("https://github.com/")
|
|
161
200
|
Navigate to the previous page in history.
|
162
201
|
|
163
202
|
```ruby
|
164
|
-
browser.
|
203
|
+
browser.go_to("https://github.com/")
|
165
204
|
browser.at_xpath("//a").click
|
166
205
|
browser.back
|
167
206
|
```
|
@@ -171,7 +210,7 @@ browser.back
|
|
171
210
|
Navigate to the next page in history.
|
172
211
|
|
173
212
|
```ruby
|
174
|
-
browser.
|
213
|
+
browser.go_to("https://github.com/")
|
175
214
|
browser.at_xpath("//a").click
|
176
215
|
browser.back
|
177
216
|
browser.forward
|
@@ -182,10 +221,19 @@ browser.forward
|
|
182
221
|
Reload current page.
|
183
222
|
|
184
223
|
```ruby
|
185
|
-
browser.
|
224
|
+
browser.go_to("https://github.com/")
|
186
225
|
browser.refresh
|
187
226
|
```
|
188
227
|
|
228
|
+
#### stop
|
229
|
+
|
230
|
+
Stop all navigations and loading pending resources on the page
|
231
|
+
|
232
|
+
```ruby
|
233
|
+
browser.go_to("https://github.com/")
|
234
|
+
browser.stop
|
235
|
+
```
|
236
|
+
|
189
237
|
|
190
238
|
## Finders
|
191
239
|
|
@@ -199,7 +247,7 @@ provided node.
|
|
199
247
|
* :within `Node` | `nil`
|
200
248
|
|
201
249
|
```ruby
|
202
|
-
browser.
|
250
|
+
browser.go_to("https://github.com/")
|
203
251
|
browser.at_css("a[aria-label='Issues you created']") # => Node
|
204
252
|
```
|
205
253
|
|
@@ -214,7 +262,7 @@ document or provided node.
|
|
214
262
|
* :within `Node` | `nil`
|
215
263
|
|
216
264
|
```ruby
|
217
|
-
browser.
|
265
|
+
browser.go_to("https://github.com/")
|
218
266
|
browser.css("a[aria-label='Issues you created']") # => [Node]
|
219
267
|
```
|
220
268
|
|
@@ -227,7 +275,7 @@ Find node by xpath.
|
|
227
275
|
* :within `Node` | `nil`
|
228
276
|
|
229
277
|
```ruby
|
230
|
-
browser.
|
278
|
+
browser.go_to("https://github.com/")
|
231
279
|
browser.at_xpath("//a[@aria-label='Issues you created']") # => Node
|
232
280
|
```
|
233
281
|
|
@@ -240,7 +288,7 @@ Find nodes by xpath.
|
|
240
288
|
* :within `Node` | `nil`
|
241
289
|
|
242
290
|
```ruby
|
243
|
-
browser.
|
291
|
+
browser.go_to("https://github.com/")
|
244
292
|
browser.xpath("//a[@aria-label='Issues you created']") # => [Node]
|
245
293
|
```
|
246
294
|
|
@@ -249,7 +297,7 @@ browser.xpath("//a[@aria-label='Issues you created']") # => [Node]
|
|
249
297
|
Returns current top window location href.
|
250
298
|
|
251
299
|
```ruby
|
252
|
-
browser.
|
300
|
+
browser.go_to("https://google.com/")
|
253
301
|
browser.current_url # => "https://www.google.com/"
|
254
302
|
```
|
255
303
|
|
@@ -258,7 +306,7 @@ browser.current_url # => "https://www.google.com/"
|
|
258
306
|
Returns current top window title
|
259
307
|
|
260
308
|
```ruby
|
261
|
-
browser.
|
309
|
+
browser.go_to("https://google.com/")
|
262
310
|
browser.current_title # => "Google"
|
263
311
|
```
|
264
312
|
|
@@ -267,7 +315,7 @@ browser.current_title # => "Google"
|
|
267
315
|
Returns current page's html.
|
268
316
|
|
269
317
|
```ruby
|
270
|
-
browser.
|
318
|
+
browser.go_to("https://google.com/")
|
271
319
|
browser.body # => '<html itemscope="" itemtype="http://schema.org/WebPage" lang="ru"><head>...
|
272
320
|
```
|
273
321
|
|
@@ -288,18 +336,21 @@ Saves screenshot on a disk or returns it as base64.
|
|
288
336
|
* :full `Boolean` whether you need full page screenshot or a viewport
|
289
337
|
* :selector `String` css selector for given element
|
290
338
|
* :scale `Float` zoom in/out
|
339
|
+
* :background_color `Ferrum::RGBA.new(0, 0, 0, 0.0)` to have specific background color
|
291
340
|
|
292
341
|
```ruby
|
293
|
-
browser.
|
342
|
+
browser.go_to("https://google.com/")
|
294
343
|
# Save on the disk in PNG
|
295
344
|
browser.screenshot(path: "google.png") # => 134660
|
296
345
|
# Save on the disk in JPG
|
297
346
|
browser.screenshot(path: "google.jpg") # => 30902
|
298
347
|
# Save to Base64 the whole page not only viewport and reduce quality
|
299
348
|
browser.screenshot(full: true, quality: 60) # "iVBORw0KGgoAAAANSUhEUgAABAAAAAMACAYAAAC6uhUNAAAAAXNSR0IArs4c6Q...
|
349
|
+
# Save with specific background color
|
350
|
+
browser.screenshot(background_color: Ferrum::RGBA.new(0, 0, 0, 0.0))
|
300
351
|
```
|
301
352
|
|
302
|
-
#### pdf(\*\*options) : `String` | `
|
353
|
+
#### pdf(\*\*options) : `String` | `Boolean`
|
303
354
|
|
304
355
|
Saves PDF on a disk or returns it as base64.
|
305
356
|
|
@@ -317,9 +368,21 @@ Saves PDF on a disk or returns it as base64.
|
|
317
368
|
* See other [native options](https://chromedevtools.github.io/devtools-protocol/tot/Page#method-printToPDF) you can pass
|
318
369
|
|
319
370
|
```ruby
|
320
|
-
browser.
|
371
|
+
browser.go_to("https://google.com/")
|
321
372
|
# Save to disk as a PDF
|
322
|
-
browser.pdf(path: "google.pdf", paper_width: 1.0, paper_height: 1.0) # =>
|
373
|
+
browser.pdf(path: "google.pdf", paper_width: 1.0, paper_height: 1.0) # => true
|
374
|
+
```
|
375
|
+
|
376
|
+
#### mhtml(\*\*options) : `String` | `Integer`
|
377
|
+
|
378
|
+
Saves MHTML on a disk or returns it as a string.
|
379
|
+
|
380
|
+
* options `Hash`
|
381
|
+
* :path `String` to save a file on the disk.
|
382
|
+
|
383
|
+
```ruby
|
384
|
+
browser.go_to("https://google.com/")
|
385
|
+
browser.mhtml(path: "google.mhtml") # => 87742
|
323
386
|
```
|
324
387
|
|
325
388
|
|
@@ -333,7 +396,7 @@ Returns all information about network traffic as `Network::Exchange` instance
|
|
333
396
|
which in general is a wrapper around `request`, `response` and `error`.
|
334
397
|
|
335
398
|
```ruby
|
336
|
-
browser.
|
399
|
+
browser.go_to("https://github.com/")
|
337
400
|
browser.network.traffic # => [#<Ferrum::Network::Exchange, ...]
|
338
401
|
```
|
339
402
|
|
@@ -342,7 +405,7 @@ browser.network.traffic # => [#<Ferrum::Network::Exchange, ...]
|
|
342
405
|
Page request of the main frame.
|
343
406
|
|
344
407
|
```ruby
|
345
|
-
browser.
|
408
|
+
browser.go_to("https://github.com/")
|
346
409
|
browser.network.request # => #<Ferrum::Network::Request...
|
347
410
|
```
|
348
411
|
|
@@ -351,7 +414,7 @@ browser.network.request # => #<Ferrum::Network::Request...
|
|
351
414
|
Page response of the main frame.
|
352
415
|
|
353
416
|
```ruby
|
354
|
-
browser.
|
417
|
+
browser.go_to("https://github.com/")
|
355
418
|
browser.network.response # => #<Ferrum::Network::Response...
|
356
419
|
```
|
357
420
|
|
@@ -361,7 +424,7 @@ Contains the status code of the main page response (e.g., 200 for a
|
|
361
424
|
success). This is just a shortcut for `response.status`.
|
362
425
|
|
363
426
|
```ruby
|
364
|
-
browser.
|
427
|
+
browser.go_to("https://github.com/")
|
365
428
|
browser.network.status # => 200
|
366
429
|
```
|
367
430
|
|
@@ -378,7 +441,7 @@ Waits for network idle or raises `Ferrum::TimeoutError` error
|
|
378
441
|
by default
|
379
442
|
|
380
443
|
```ruby
|
381
|
-
browser.
|
444
|
+
browser.go_to("https://example.com/")
|
382
445
|
browser.at_xpath("//a[text() = 'No UI changes button']").click
|
383
446
|
browser.network.wait_for_idle
|
384
447
|
```
|
@@ -391,7 +454,7 @@ Clear browser's cache or collected traffic.
|
|
391
454
|
|
392
455
|
```ruby
|
393
456
|
traffic = browser.network.traffic # => []
|
394
|
-
browser.
|
457
|
+
browser.go_to("https://github.com/")
|
395
458
|
traffic.size # => 51
|
396
459
|
browser.network.clear(:traffic)
|
397
460
|
traffic.size # => 0
|
@@ -419,25 +482,52 @@ browser.on(:request) do |request|
|
|
419
482
|
request.continue
|
420
483
|
end
|
421
484
|
end
|
422
|
-
browser.
|
485
|
+
browser.go_to("https://google.com")
|
423
486
|
```
|
424
487
|
|
425
|
-
#### authorize(\*\*options)
|
488
|
+
#### authorize(\*\*options, &block)
|
426
489
|
|
427
|
-
If site uses authorization you can provide credentials using this method.
|
490
|
+
If site or proxy uses authorization you can provide credentials using this method.
|
428
491
|
|
429
492
|
* options `Hash`
|
430
493
|
* :type `Symbol` `:server` | `:proxy` site or proxy authorization
|
431
494
|
* :user `String`
|
432
495
|
* :password `String`
|
496
|
+
* &block accepts authenticated request, which you must subsequently allow or deny, if you don't
|
497
|
+
care about unwanted requests just call `request.continue`.
|
433
498
|
|
434
499
|
```ruby
|
435
|
-
browser.network.authorize(user: "login", password: "pass")
|
436
|
-
browser.
|
500
|
+
browser.network.authorize(user: "login", password: "pass") { |req| req.continue }
|
501
|
+
browser.go_to("http://example.com/authenticated")
|
437
502
|
puts browser.network.status # => 200
|
438
503
|
puts browser.body # => Welcome, authenticated client
|
439
504
|
```
|
440
505
|
|
506
|
+
Since Chrome implements authorize using request interception you must continue or abort authorized requests. If you
|
507
|
+
already have code that uses interception you can use `authorize` without block, but if not you are obliged to pass
|
508
|
+
block, so this is version doesn't pass block and can work just fine:
|
509
|
+
|
510
|
+
```ruby
|
511
|
+
browser = Ferrum::Browser.new
|
512
|
+
browser.network.intercept
|
513
|
+
browser.on(:request) do |request|
|
514
|
+
if request.resource_type == "Image"
|
515
|
+
request.abort
|
516
|
+
else
|
517
|
+
request.continue
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
browser.network.authorize(user: "login", password: "pass", type: :proxy)
|
522
|
+
|
523
|
+
browser.go_to("https://google.com")
|
524
|
+
|
525
|
+
```
|
526
|
+
|
527
|
+
You used to call `authorize` method without block, but since it's implemented using request interception there could be
|
528
|
+
a collision with another part of your code that also uses request interception, so that authorize allows the request
|
529
|
+
while your code denies but it's too late. The block is mandatory now.
|
530
|
+
|
441
531
|
|
442
532
|
### Mouse
|
443
533
|
|
@@ -453,7 +543,7 @@ Scroll page to a given x, y
|
|
453
543
|
displayed in the upper left
|
454
544
|
|
455
545
|
```ruby
|
456
|
-
browser.
|
546
|
+
browser.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
|
457
547
|
browser.mouse.scroll_to(0, 400)
|
458
548
|
```
|
459
549
|
|
@@ -558,6 +648,8 @@ Sets given values as cookie
|
|
558
648
|
* :value `String`
|
559
649
|
* :domain `String`
|
560
650
|
* :expires `Integer`
|
651
|
+
* :samesite `String`
|
652
|
+
* :httponly `Boolean`
|
561
653
|
|
562
654
|
```ruby
|
563
655
|
browser.cookies.set(name: "stealth", value: "omg", domain: "google.com") # => true
|
@@ -677,7 +769,7 @@ browser.add_style_tag(content: "h1 { font-size: 40px; }") # => true
|
|
677
769
|
|
678
770
|
```ruby
|
679
771
|
browser.bypass_csp # => true
|
680
|
-
browser.
|
772
|
+
browser.go_to("https://github.com/ruby-concurrency/concurrent-ruby/blob/master/docs-source/promises.in.md")
|
681
773
|
browser.refresh
|
682
774
|
browser.add_script_tag(content: "window.__injected = 42")
|
683
775
|
browser.evaluate("window.__injected") # => 42
|
@@ -686,17 +778,146 @@ browser.evaluate("window.__injected") # => 42
|
|
686
778
|
|
687
779
|
## Frames
|
688
780
|
|
689
|
-
#### frames
|
690
|
-
|
691
|
-
|
781
|
+
#### frames : `Array[Frame] | []`
|
782
|
+
|
783
|
+
Returns all the frames current page have.
|
784
|
+
|
785
|
+
```ruby
|
786
|
+
browser.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
787
|
+
browser.frames # =>
|
788
|
+
# [
|
789
|
+
# #<Ferrum::Frame @id="C6D104CE454A025FBCF22B98DE612B12" @parent_id=nil @name=nil @state=:stopped_loading @execution_id=1>,
|
790
|
+
# #<Ferrum::Frame @id="C09C4E4404314AAEAE85928EAC109A93" @parent_id="C6D104CE454A025FBCF22B98DE612B12" @state=:stopped_loading @execution_id=2>,
|
791
|
+
# #<Ferrum::Frame @id="2E9C7F476ED09D87A42F2FEE3C6FBC3C" @parent_id="C6D104CE454A025FBCF22B98DE612B12" @state=:stopped_loading @execution_id=3>,
|
792
|
+
# ...
|
793
|
+
# ]
|
794
|
+
```
|
795
|
+
|
796
|
+
#### main_frame : `Frame`
|
797
|
+
|
798
|
+
Returns page's main frame, the top of the tree and the parent of all frames.
|
799
|
+
|
800
|
+
#### frame_by(\*\*options) : `Frame | nil`
|
692
801
|
|
693
|
-
|
802
|
+
Find frame by given options.
|
803
|
+
|
804
|
+
* options `Hash`
|
805
|
+
* :id `String` - Unique frame's id that browser provides
|
806
|
+
* :name `String` - Frame's name if there's one
|
694
807
|
|
695
808
|
```ruby
|
696
|
-
browser.
|
809
|
+
browser.frame_by(id: "C6D104CE454A025FBCF22B98DE612B12")
|
810
|
+
```
|
811
|
+
|
812
|
+
|
813
|
+
## Frame
|
814
|
+
|
815
|
+
#### id : `String`
|
816
|
+
|
817
|
+
Frame's unique id.
|
818
|
+
|
819
|
+
#### parent_id : `String | nil`
|
820
|
+
|
821
|
+
Parent frame id if this one is nested in another one.
|
822
|
+
|
823
|
+
#### execution_id : `Integer`
|
824
|
+
|
825
|
+
Execution context id which is used by JS, each frame has it's own context in
|
826
|
+
which JS evaluates.
|
827
|
+
|
828
|
+
#### name : `String | nil`
|
829
|
+
|
830
|
+
If frame was given a name it should be here.
|
831
|
+
|
832
|
+
#### state : `Symbol | nil`
|
833
|
+
|
834
|
+
One of the states frame's in:
|
835
|
+
|
836
|
+
* `:started_loading`
|
837
|
+
* `:navigated`
|
838
|
+
* `:stopped_loading`
|
839
|
+
|
840
|
+
#### url : `String`
|
841
|
+
|
842
|
+
Returns current frame's location href.
|
843
|
+
|
844
|
+
```ruby
|
845
|
+
browser.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
|
846
|
+
frame = browser.frames[1]
|
847
|
+
frame.url # => https://interactive-examples.mdn.mozilla.net/pages/tabbed/iframe.html
|
848
|
+
```
|
849
|
+
|
850
|
+
#### title
|
851
|
+
|
852
|
+
Returns current frame's title.
|
853
|
+
|
854
|
+
```ruby
|
855
|
+
browser.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
|
697
856
|
frame = browser.frames[1]
|
698
|
-
|
699
|
-
|
857
|
+
frame.title # => HTML Demo: <iframe>
|
858
|
+
```
|
859
|
+
|
860
|
+
#### main? : `Boolean`
|
861
|
+
|
862
|
+
If current frame is the main frame of the page (top of the tree).
|
863
|
+
|
864
|
+
```ruby
|
865
|
+
browser.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
866
|
+
frame = browser.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
|
867
|
+
frame.main? # => false
|
868
|
+
```
|
869
|
+
|
870
|
+
#### current_url : `String`
|
871
|
+
|
872
|
+
Returns current frame's top window location href.
|
873
|
+
|
874
|
+
```ruby
|
875
|
+
browser.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
876
|
+
frame = browser.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
|
877
|
+
frame.current_url # => "https://www.w3schools.com/tags/tag_frame.asp"
|
878
|
+
```
|
879
|
+
|
880
|
+
#### current_title : `String`
|
881
|
+
|
882
|
+
Returns current frame's top window title.
|
883
|
+
|
884
|
+
```ruby
|
885
|
+
browser.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
886
|
+
frame = browser.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
|
887
|
+
frame.current_title # => "HTML frame tag"
|
888
|
+
```
|
889
|
+
|
890
|
+
#### body : `String`
|
891
|
+
|
892
|
+
Returns current frame's html.
|
893
|
+
|
894
|
+
```ruby
|
895
|
+
browser.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
896
|
+
frame = browser.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
|
897
|
+
frame.body # => "<html><head></head><body></body></html>"
|
898
|
+
```
|
899
|
+
|
900
|
+
#### doctype
|
901
|
+
|
902
|
+
Returns current frame's doctype.
|
903
|
+
|
904
|
+
```ruby
|
905
|
+
browser.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
906
|
+
browser.main_frame.doctype # => "<!DOCTYPE html>"
|
907
|
+
```
|
908
|
+
|
909
|
+
#### set_content(html)
|
910
|
+
|
911
|
+
Sets a content of a given frame.
|
912
|
+
|
913
|
+
* html `String`
|
914
|
+
|
915
|
+
```ruby
|
916
|
+
browser.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
|
917
|
+
frame = browser.frames[1]
|
918
|
+
frame.body # <html lang="en"><head><style>body {transition: opacity ease-in 0.2s; }...
|
919
|
+
frame.set_content("<html><head></head><body><p>lol</p></body></html>")
|
920
|
+
frame.body # => <html><head></head><body><p>lol</p></body></html>
|
700
921
|
```
|
701
922
|
|
702
923
|
|
@@ -721,7 +942,7 @@ browser.on(:dialog) do |dialog|
|
|
721
942
|
dialog.dismiss
|
722
943
|
end
|
723
944
|
end
|
724
|
-
browser.
|
945
|
+
browser.go_to("https://google.com")
|
725
946
|
```
|
726
947
|
|
727
948
|
|
@@ -738,13 +959,13 @@ context = browser.contexts.create
|
|
738
959
|
|
739
960
|
t1 = Thread.new(context) do |c|
|
740
961
|
page = c.create_page
|
741
|
-
page.
|
962
|
+
page.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
|
742
963
|
page.screenshot(path: "t1.png")
|
743
964
|
end
|
744
965
|
|
745
966
|
t2 = Thread.new(context) do |c|
|
746
967
|
page = c.create_page
|
747
|
-
page.
|
968
|
+
page.go_to("https://www.google.com/search?q=Ruby+static+typing")
|
748
969
|
page.screenshot(path: "t2.png")
|
749
970
|
end
|
750
971
|
|
@@ -763,7 +984,7 @@ browser = Ferrum::Browser.new
|
|
763
984
|
t1 = Thread.new(browser) do |b|
|
764
985
|
context = b.contexts.create
|
765
986
|
page = context.create_page
|
766
|
-
page.
|
987
|
+
page.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
|
767
988
|
page.screenshot(path: "t1.png")
|
768
989
|
context.dispose
|
769
990
|
end
|
@@ -771,7 +992,7 @@ end
|
|
771
992
|
t2 = Thread.new(browser) do |b|
|
772
993
|
context = b.contexts.create
|
773
994
|
page = context.create_page
|
774
|
-
page.
|
995
|
+
page.go_to("https://www.google.com/search?q=Ruby+static+typing")
|
775
996
|
page.screenshot(path: "t2.png")
|
776
997
|
context.dispose
|
777
998
|
end
|
@@ -781,3 +1002,21 @@ t2.join
|
|
781
1002
|
|
782
1003
|
browser.quit
|
783
1004
|
```
|
1005
|
+
|
1006
|
+
## Development
|
1007
|
+
|
1008
|
+
After checking out the repo, run `bundle install` to install dependencies.
|
1009
|
+
|
1010
|
+
Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
1011
|
+
|
1012
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
1013
|
+
|
1014
|
+
|
1015
|
+
## Contributing
|
1016
|
+
|
1017
|
+
Bug reports and pull requests are welcome on [GitHub](https://github.com/rubycdp/ferrum).
|
1018
|
+
|
1019
|
+
## License
|
1020
|
+
|
1021
|
+
The gem is available as open source under the terms of the
|
1022
|
+
[MIT License](https://opensource.org/licenses/MIT).
|