ferrum 0.7 → 0.10.2
Sign up to get free protection for your applications and to get access to all the features.
- 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).
|