ferrum 0.14 → 0.15
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 +277 -154
- data/lib/ferrum/browser/command.rb +4 -0
- data/lib/ferrum/browser/options/chrome.rb +8 -3
- data/lib/ferrum/browser/options.rb +38 -25
- data/lib/ferrum/browser/process.rb +43 -16
- data/lib/ferrum/browser.rb +26 -50
- data/lib/ferrum/client/subscriber.rb +76 -0
- data/lib/ferrum/{browser → client}/web_socket.rb +35 -21
- data/lib/ferrum/client.rb +169 -0
- data/lib/ferrum/context.rb +19 -15
- data/lib/ferrum/contexts.rb +46 -12
- data/lib/ferrum/cookies.rb +1 -1
- data/lib/ferrum/downloads.rb +60 -0
- data/lib/ferrum/errors.rb +2 -1
- data/lib/ferrum/headers.rb +1 -1
- data/lib/ferrum/network/exchange.rb +10 -1
- data/lib/ferrum/network/intercepted_request.rb +5 -5
- data/lib/ferrum/network/request.rb +9 -0
- data/lib/ferrum/network.rb +11 -9
- data/lib/ferrum/page/frames.rb +5 -5
- data/lib/ferrum/page/screenshot.rb +36 -24
- data/lib/ferrum/page.rb +177 -119
- data/lib/ferrum/proxy.rb +1 -1
- data/lib/ferrum/target.rb +25 -5
- data/lib/ferrum/utils/elapsed_time.rb +0 -2
- data/lib/ferrum/utils/event.rb +19 -0
- data/lib/ferrum/utils/platform.rb +4 -0
- data/lib/ferrum/utils/thread.rb +18 -0
- data/lib/ferrum/version.rb +1 -1
- data/lib/ferrum.rb +3 -0
- metadata +14 -17
- data/lib/ferrum/browser/client.rb +0 -103
- data/lib/ferrum/browser/subscriber.rb +0 -36
data/README.md
CHANGED
|
@@ -25,6 +25,8 @@ going to crawl sites you better use Ferrum or
|
|
|
25
25
|
* [Vessel](https://github.com/rubycdp/vessel) high-level web crawling framework
|
|
26
26
|
based on Ferrum and Mechanize.
|
|
27
27
|
|
|
28
|
+
The development is done in [](https://jb.gg/ruby)
|
|
29
|
+
provided by [OSS license](https://jb.gg/OpenSourceSupport).
|
|
28
30
|
|
|
29
31
|
## Index
|
|
30
32
|
|
|
@@ -35,8 +37,8 @@ based on Ferrum and Mechanize.
|
|
|
35
37
|
* [Navigation](https://github.com/rubycdp/ferrum#navigation)
|
|
36
38
|
* [Finders](https://github.com/rubycdp/ferrum#finders)
|
|
37
39
|
* [Screenshots](https://github.com/rubycdp/ferrum#screenshots)
|
|
38
|
-
* [Cleaning Up](https://github.com/rubycdp/ferrum#cleaning-up)
|
|
39
40
|
* [Network](https://github.com/rubycdp/ferrum#network)
|
|
41
|
+
* [Downloads](https://github.com/rubycdp/ferrum#downloads)
|
|
40
42
|
* [Proxy](https://github.com/rubycdp/ferrum#proxy)
|
|
41
43
|
* [Mouse](https://github.com/rubycdp/ferrum#mouse)
|
|
42
44
|
* [Keyboard](https://github.com/rubycdp/ferrum#keyboard)
|
|
@@ -49,6 +51,7 @@ based on Ferrum and Mechanize.
|
|
|
49
51
|
* [Animation](https://github.com/rubycdp/ferrum#animation)
|
|
50
52
|
* [Node](https://github.com/rubycdp/ferrum#node)
|
|
51
53
|
* [Tracing](https://github.com/rubycdp/ferrum#tracing)
|
|
54
|
+
* [Clean Up](https://github.com/rubycdp/ferrum#clean-up)
|
|
52
55
|
* [Thread safety](https://github.com/rubycdp/ferrum#thread-safety)
|
|
53
56
|
* [Development](https://github.com/rubycdp/ferrum#development)
|
|
54
57
|
* [Contributing](https://github.com/rubycdp/ferrum#contributing)
|
|
@@ -61,7 +64,7 @@ There's no official Chrome or Chromium package for Linux don't install it this
|
|
|
61
64
|
way because it's either outdated or unofficial, both are bad. Download it from
|
|
62
65
|
official source for [Chrome](https://www.google.com/chrome/) or
|
|
63
66
|
[Chromium](https://www.chromium.org/getting-involved/download-chromium).
|
|
64
|
-
Chrome binary should be in the `PATH` or `BROWSER_PATH`
|
|
67
|
+
Chrome binary should be in the `PATH` or `BROWSER_PATH` and you can pass it as an
|
|
65
68
|
option to browser instance see `:browser_path` in
|
|
66
69
|
[Customization](https://github.com/rubycdp/ferrum#customization).
|
|
67
70
|
|
|
@@ -83,14 +86,17 @@ browser.screenshot(path: "google.png")
|
|
|
83
86
|
browser.quit
|
|
84
87
|
```
|
|
85
88
|
|
|
86
|
-
|
|
89
|
+
When you work with browser instance Ferrum creates and maintains a default page for you, in fact all the methods above
|
|
90
|
+
are sent to the `page` instance that is created in the `default_context` of the `browser` instance. You can interact
|
|
91
|
+
with a page created manually and this is preferred:
|
|
87
92
|
|
|
88
93
|
```ruby
|
|
89
94
|
browser = Ferrum::Browser.new
|
|
90
|
-
browser.
|
|
91
|
-
|
|
95
|
+
page = browser.create_page
|
|
96
|
+
page.go_to("https://google.com")
|
|
97
|
+
input = page.at_xpath("//input[@name='q']")
|
|
92
98
|
input.focus.type("Ruby headless driver for Chrome", :Enter)
|
|
93
|
-
|
|
99
|
+
page.at_css("a > h3").text # => "rubycdp/ferrum: Ruby Chrome/Chromium driver - GitHub"
|
|
94
100
|
browser.quit
|
|
95
101
|
```
|
|
96
102
|
|
|
@@ -98,8 +104,9 @@ Evaluate some JavaScript and get full width/height:
|
|
|
98
104
|
|
|
99
105
|
```ruby
|
|
100
106
|
browser = Ferrum::Browser.new
|
|
101
|
-
browser.
|
|
102
|
-
|
|
107
|
+
page = browser.create_page
|
|
108
|
+
page.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
|
|
109
|
+
width, height = page.evaluate <<~JS
|
|
103
110
|
[document.documentElement.offsetWidth,
|
|
104
111
|
document.documentElement.offsetHeight]
|
|
105
112
|
JS
|
|
@@ -112,8 +119,9 @@ Do any mouse movements you like:
|
|
|
112
119
|
```ruby
|
|
113
120
|
# Trace a 100x100 square
|
|
114
121
|
browser = Ferrum::Browser.new
|
|
115
|
-
browser.
|
|
116
|
-
|
|
122
|
+
page = browser.create_page
|
|
123
|
+
page.go_to("https://google.com")
|
|
124
|
+
page.mouse
|
|
117
125
|
.move(x: 0, y: 0)
|
|
118
126
|
.down
|
|
119
127
|
.move(x: 0, y: 100)
|
|
@@ -148,6 +156,7 @@ Ferrum::Browser.new(options)
|
|
|
148
156
|
* `:headless` (String | Boolean) - Set browser as headless or not, `true` by default. You can set `"new"` to support
|
|
149
157
|
[new headless mode](https://developer.chrome.com/articles/new-headless/).
|
|
150
158
|
* `:xvfb` (Boolean) - Run browser in a virtual framebuffer, `false` by default.
|
|
159
|
+
* `:flatten` (Boolean) - Use one websocket connection to the browser and all the pages in flatten mode.
|
|
151
160
|
* `:window_size` (Array) - The dimensions of the browser window in which to
|
|
152
161
|
test, expressed as a 2-element array, e.g. [1024, 768]. Default: [1024, 768]
|
|
153
162
|
* `:extensions` (Array[String | Hash]) - An array of paths to files or JS
|
|
@@ -178,6 +187,8 @@ Ferrum::Browser.new(options)
|
|
|
178
187
|
* `:host` (String) - Remote debugging address for headless Chrome.
|
|
179
188
|
* `:url` (String) - URL for a running instance of Chrome. If this is set, a
|
|
180
189
|
browser process will not be spawned.
|
|
190
|
+
* `:ws_url` (String) - Websocket url for a running instance of Chrome. If this is set, a
|
|
191
|
+
browser process will not be spawned.
|
|
181
192
|
* `:process_timeout` (Integer) - How long to wait for the Chrome process to
|
|
182
193
|
respond on startup.
|
|
183
194
|
* `:ws_max_receive_size` (Integer) - How big messages to accept from Chrome
|
|
@@ -198,7 +209,7 @@ Navigate page to.
|
|
|
198
209
|
configuring driver.
|
|
199
210
|
|
|
200
211
|
```ruby
|
|
201
|
-
|
|
212
|
+
page.go_to("https://github.com/")
|
|
202
213
|
```
|
|
203
214
|
|
|
204
215
|
#### back
|
|
@@ -206,9 +217,9 @@ browser.go_to("https://github.com/")
|
|
|
206
217
|
Navigate to the previous page in history.
|
|
207
218
|
|
|
208
219
|
```ruby
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
220
|
+
page.go_to("https://github.com/")
|
|
221
|
+
page.at_xpath("//a").click
|
|
222
|
+
page.back
|
|
212
223
|
```
|
|
213
224
|
|
|
214
225
|
#### forward
|
|
@@ -216,10 +227,10 @@ browser.back
|
|
|
216
227
|
Navigate to the next page in history.
|
|
217
228
|
|
|
218
229
|
```ruby
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
230
|
+
page.go_to("https://github.com/")
|
|
231
|
+
page.at_xpath("//a").click
|
|
232
|
+
page.back
|
|
233
|
+
page.forward
|
|
223
234
|
```
|
|
224
235
|
|
|
225
236
|
#### refresh
|
|
@@ -227,8 +238,8 @@ browser.forward
|
|
|
227
238
|
Reload current page.
|
|
228
239
|
|
|
229
240
|
```ruby
|
|
230
|
-
|
|
231
|
-
|
|
241
|
+
page.go_to("https://github.com/")
|
|
242
|
+
page.refresh
|
|
232
243
|
```
|
|
233
244
|
|
|
234
245
|
#### stop
|
|
@@ -236,8 +247,8 @@ browser.refresh
|
|
|
236
247
|
Stop all navigations and loading pending resources on the page
|
|
237
248
|
|
|
238
249
|
```ruby
|
|
239
|
-
|
|
240
|
-
|
|
250
|
+
page.go_to("https://github.com/")
|
|
251
|
+
page.stop
|
|
241
252
|
```
|
|
242
253
|
|
|
243
254
|
#### position = \*\*options
|
|
@@ -260,6 +271,37 @@ Get the position for the browser window
|
|
|
260
271
|
browser.position # => [10, 20]
|
|
261
272
|
```
|
|
262
273
|
|
|
274
|
+
#### window_bounds = \*\*options
|
|
275
|
+
|
|
276
|
+
Set window bounds
|
|
277
|
+
|
|
278
|
+
* options `Hash`
|
|
279
|
+
* :left `Integer`
|
|
280
|
+
* :top `Integer`
|
|
281
|
+
* :width `Integer`
|
|
282
|
+
* :height `Integer`
|
|
283
|
+
* :window_state `String`
|
|
284
|
+
|
|
285
|
+
```ruby
|
|
286
|
+
browser.window_bounds = { left: 10, top: 20, width: 1024, height: 768, window_state: "normal" }
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
#### window_bounds : `Hash<String, Integer | String>`
|
|
290
|
+
|
|
291
|
+
Get window bounds
|
|
292
|
+
|
|
293
|
+
```ruby
|
|
294
|
+
browser.window_bounds # => { "left": 0, "top": 1286, "width": 10, "height": 10, "windowState": "normal" }
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### window_id : `Integer`
|
|
298
|
+
|
|
299
|
+
Current window id
|
|
300
|
+
|
|
301
|
+
```ruby
|
|
302
|
+
browser.window_id # => 1
|
|
303
|
+
```
|
|
304
|
+
|
|
263
305
|
## Finders
|
|
264
306
|
|
|
265
307
|
#### at_css(selector, \*\*options) : `Node` | `nil`
|
|
@@ -272,8 +314,8 @@ provided node.
|
|
|
272
314
|
* :within `Node` | `nil`
|
|
273
315
|
|
|
274
316
|
```ruby
|
|
275
|
-
|
|
276
|
-
|
|
317
|
+
page.go_to("https://github.com/")
|
|
318
|
+
page.at_css("a[aria-label='Issues you created']") # => Node
|
|
277
319
|
```
|
|
278
320
|
|
|
279
321
|
|
|
@@ -287,8 +329,8 @@ document or provided node.
|
|
|
287
329
|
* :within `Node` | `nil`
|
|
288
330
|
|
|
289
331
|
```ruby
|
|
290
|
-
|
|
291
|
-
|
|
332
|
+
page.go_to("https://github.com/")
|
|
333
|
+
page.css("a[aria-label='Issues you created']") # => [Node]
|
|
292
334
|
```
|
|
293
335
|
|
|
294
336
|
#### at_xpath(selector, \*\*options) : `Node` | `nil`
|
|
@@ -300,8 +342,8 @@ Find node by xpath.
|
|
|
300
342
|
* :within `Node` | `nil`
|
|
301
343
|
|
|
302
344
|
```ruby
|
|
303
|
-
|
|
304
|
-
|
|
345
|
+
page.go_to("https://github.com/")
|
|
346
|
+
page.at_xpath("//a[@aria-label='Issues you created']") # => Node
|
|
305
347
|
```
|
|
306
348
|
|
|
307
349
|
#### xpath(selector, \*\*options) : `Array<Node>` | `[]`
|
|
@@ -313,8 +355,8 @@ Find nodes by xpath.
|
|
|
313
355
|
* :within `Node` | `nil`
|
|
314
356
|
|
|
315
357
|
```ruby
|
|
316
|
-
|
|
317
|
-
|
|
358
|
+
page.go_to("https://github.com/")
|
|
359
|
+
page.xpath("//a[@aria-label='Issues you created']") # => [Node]
|
|
318
360
|
```
|
|
319
361
|
|
|
320
362
|
#### current_url : `String`
|
|
@@ -322,8 +364,8 @@ browser.xpath("//a[@aria-label='Issues you created']") # => [Node]
|
|
|
322
364
|
Returns current top window location href.
|
|
323
365
|
|
|
324
366
|
```ruby
|
|
325
|
-
|
|
326
|
-
|
|
367
|
+
page.go_to("https://google.com/")
|
|
368
|
+
page.current_url # => "https://www.google.com/"
|
|
327
369
|
```
|
|
328
370
|
|
|
329
371
|
#### current_title : `String`
|
|
@@ -331,8 +373,8 @@ browser.current_url # => "https://www.google.com/"
|
|
|
331
373
|
Returns current top window title
|
|
332
374
|
|
|
333
375
|
```ruby
|
|
334
|
-
|
|
335
|
-
|
|
376
|
+
page.go_to("https://google.com/")
|
|
377
|
+
page.current_title # => "Google"
|
|
336
378
|
```
|
|
337
379
|
|
|
338
380
|
#### body : `String`
|
|
@@ -340,8 +382,8 @@ browser.current_title # => "Google"
|
|
|
340
382
|
Returns current page's html.
|
|
341
383
|
|
|
342
384
|
```ruby
|
|
343
|
-
|
|
344
|
-
|
|
385
|
+
page.go_to("https://google.com/")
|
|
386
|
+
page.body # => '<html itemscope="" itemtype="http://schema.org/WebPage" lang="ru"><head>...
|
|
345
387
|
```
|
|
346
388
|
|
|
347
389
|
|
|
@@ -359,20 +401,29 @@ Saves screenshot on a disk or returns it as base64.
|
|
|
359
401
|
* :format `String` "jpeg" | "png"
|
|
360
402
|
* :quality `Integer` 0-100 works for jpeg only
|
|
361
403
|
* :full `Boolean` whether you need full page screenshot or a viewport
|
|
362
|
-
* :selector `String` css selector for given element
|
|
404
|
+
* :selector `String` css selector for given element, optional
|
|
405
|
+
* :area `Hash` area for screenshot, optional
|
|
406
|
+
* :x `Integer`
|
|
407
|
+
* :y `Integer`
|
|
408
|
+
* :width `Integer`
|
|
409
|
+
* :height `Integer`
|
|
363
410
|
* :scale `Float` zoom in/out
|
|
364
411
|
* :background_color `Ferrum::RGBA.new(0, 0, 0, 0.0)` to have specific background color
|
|
365
412
|
|
|
366
413
|
```ruby
|
|
367
|
-
|
|
414
|
+
page.go_to("https://google.com/")
|
|
368
415
|
# Save on the disk in PNG
|
|
369
|
-
|
|
416
|
+
page.screenshot(path: "google.png") # => 134660
|
|
370
417
|
# Save on the disk in JPG
|
|
371
|
-
|
|
418
|
+
page.screenshot(path: "google.jpg") # => 30902
|
|
372
419
|
# Save to Base64 the whole page not only viewport and reduce quality
|
|
373
|
-
|
|
420
|
+
page.screenshot(full: true, quality: 60, encoding: :base64) # "iVBORw0KGgoAAAANSUhEUgAABAAAAAMACAYAAAC6uhUNAAAAAXNSR0IArs4c6Q...
|
|
421
|
+
# Save on the disk with the selected element in PNG
|
|
422
|
+
page.screenshot(path: "google.png", selector: 'textarea') # => 11340
|
|
423
|
+
# Save to Base64 with an area of the page in PNG
|
|
424
|
+
page.screenshot(path: "google.png", area: { x: 0, y: 0, width: 400, height: 300 }) # => 54239
|
|
374
425
|
# Save with specific background color
|
|
375
|
-
|
|
426
|
+
page.screenshot(background_color: Ferrum::RGBA.new(0, 0, 0, 0.0))
|
|
376
427
|
```
|
|
377
428
|
|
|
378
429
|
#### pdf(\*\*options) : `String` | `Boolean`
|
|
@@ -393,9 +444,9 @@ Saves PDF on a disk or returns it as base64.
|
|
|
393
444
|
* See other [native options](https://chromedevtools.github.io/devtools-protocol/tot/Page#method-printToPDF) you can pass
|
|
394
445
|
|
|
395
446
|
```ruby
|
|
396
|
-
|
|
447
|
+
page.go_to("https://google.com/")
|
|
397
448
|
# Save to disk as a PDF
|
|
398
|
-
|
|
449
|
+
page.pdf(path: "google.pdf", paper_width: 1.0, paper_height: 1.0) # => true
|
|
399
450
|
```
|
|
400
451
|
|
|
401
452
|
#### mhtml(\*\*options) : `String` | `Integer`
|
|
@@ -406,33 +457,14 @@ Saves MHTML on a disk or returns it as a string.
|
|
|
406
457
|
* :path `String` to save a file on the disk.
|
|
407
458
|
|
|
408
459
|
```ruby
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
## Cleaning Up
|
|
415
|
-
|
|
416
|
-
#### reset
|
|
417
|
-
|
|
418
|
-
Closes browser tabs opened by the `Browser` instance.
|
|
419
|
-
|
|
420
|
-
```ruby
|
|
421
|
-
# connect to a long-running Chrome process
|
|
422
|
-
browser = Ferrum::Browser.new(url: 'http://localhost:9222')
|
|
423
|
-
|
|
424
|
-
browser.go_to("https://github.com/")
|
|
425
|
-
|
|
426
|
-
# clean up, lest the tab stays there hanging forever
|
|
427
|
-
browser.reset
|
|
428
|
-
|
|
429
|
-
browser.quit
|
|
460
|
+
page.go_to("https://google.com/")
|
|
461
|
+
page.mhtml(path: "google.mhtml") # => 87742
|
|
430
462
|
```
|
|
431
463
|
|
|
432
464
|
|
|
433
465
|
## Network
|
|
434
466
|
|
|
435
|
-
`
|
|
467
|
+
`page.network`
|
|
436
468
|
|
|
437
469
|
#### traffic `Array<Network::Exchange>`
|
|
438
470
|
|
|
@@ -440,8 +472,8 @@ Returns all information about network traffic as `Network::Exchange` instance
|
|
|
440
472
|
which in general is a wrapper around `request`, `response` and `error`.
|
|
441
473
|
|
|
442
474
|
```ruby
|
|
443
|
-
|
|
444
|
-
|
|
475
|
+
page.go_to("https://github.com/")
|
|
476
|
+
page.network.traffic # => [#<Ferrum::Network::Exchange, ...]
|
|
445
477
|
```
|
|
446
478
|
|
|
447
479
|
#### request : `Network::Request`
|
|
@@ -449,8 +481,8 @@ browser.network.traffic # => [#<Ferrum::Network::Exchange, ...]
|
|
|
449
481
|
Page request of the main frame.
|
|
450
482
|
|
|
451
483
|
```ruby
|
|
452
|
-
|
|
453
|
-
|
|
484
|
+
page.go_to("https://github.com/")
|
|
485
|
+
page.network.request # => #<Ferrum::Network::Request...
|
|
454
486
|
```
|
|
455
487
|
|
|
456
488
|
#### response : `Network::Response`
|
|
@@ -458,8 +490,8 @@ browser.network.request # => #<Ferrum::Network::Request...
|
|
|
458
490
|
Page response of the main frame.
|
|
459
491
|
|
|
460
492
|
```ruby
|
|
461
|
-
|
|
462
|
-
|
|
493
|
+
page.go_to("https://github.com/")
|
|
494
|
+
page.network.response # => #<Ferrum::Network::Response...
|
|
463
495
|
```
|
|
464
496
|
|
|
465
497
|
#### status : `Integer`
|
|
@@ -468,8 +500,8 @@ Contains the status code of the main page response (e.g., 200 for a
|
|
|
468
500
|
success). This is just a shortcut for `response.status`.
|
|
469
501
|
|
|
470
502
|
```ruby
|
|
471
|
-
|
|
472
|
-
|
|
503
|
+
page.go_to("https://github.com/")
|
|
504
|
+
page.network.status # => 200
|
|
473
505
|
```
|
|
474
506
|
|
|
475
507
|
#### wait_for_idle(\*\*options)
|
|
@@ -485,22 +517,22 @@ Waits for network idle or raises `Ferrum::TimeoutError` error
|
|
|
485
517
|
by default
|
|
486
518
|
|
|
487
519
|
```ruby
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
520
|
+
page.go_to("https://example.com/")
|
|
521
|
+
page.at_xpath("//a[text() = 'No UI changes button']").click
|
|
522
|
+
page.network.wait_for_idle
|
|
491
523
|
```
|
|
492
524
|
|
|
493
525
|
#### clear(type)
|
|
494
526
|
|
|
495
|
-
Clear
|
|
527
|
+
Clear page's cache or collected traffic.
|
|
496
528
|
|
|
497
529
|
* type `Symbol` it is either `:traffic` or `:cache`
|
|
498
530
|
|
|
499
531
|
```ruby
|
|
500
|
-
traffic =
|
|
501
|
-
|
|
532
|
+
traffic = page.network.traffic # => []
|
|
533
|
+
page.go_to("https://github.com/")
|
|
502
534
|
traffic.size # => 51
|
|
503
|
-
|
|
535
|
+
page.network.clear(:traffic)
|
|
504
536
|
traffic.size # => 0
|
|
505
537
|
```
|
|
506
538
|
|
|
@@ -516,8 +548,9 @@ continue them.
|
|
|
516
548
|
|
|
517
549
|
```ruby
|
|
518
550
|
browser = Ferrum::Browser.new
|
|
519
|
-
browser.
|
|
520
|
-
|
|
551
|
+
page = browser.create_page
|
|
552
|
+
page.network.intercept
|
|
553
|
+
page.on(:request) do |request|
|
|
521
554
|
if request.match?(/bla-bla/)
|
|
522
555
|
request.abort
|
|
523
556
|
elsif request.match?(/lorem/)
|
|
@@ -526,7 +559,7 @@ browser.on(:request) do |request|
|
|
|
526
559
|
request.continue
|
|
527
560
|
end
|
|
528
561
|
end
|
|
529
|
-
|
|
562
|
+
page.go_to("https://google.com")
|
|
530
563
|
```
|
|
531
564
|
|
|
532
565
|
#### authorize(\*\*options, &block)
|
|
@@ -541,10 +574,10 @@ If site or proxy uses authorization you can provide credentials using this metho
|
|
|
541
574
|
care about unwanted requests just call `request.continue`.
|
|
542
575
|
|
|
543
576
|
```ruby
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
puts
|
|
547
|
-
puts
|
|
577
|
+
page.network.authorize(user: "login", password: "pass") { |req| req.continue }
|
|
578
|
+
page.go_to("http://example.com/authenticated")
|
|
579
|
+
puts page.network.status # => 200
|
|
580
|
+
puts page.body # => Welcome, authenticated client
|
|
548
581
|
```
|
|
549
582
|
|
|
550
583
|
Since Chrome implements authorize using request interception you must continue or abort authorized requests. If you
|
|
@@ -553,8 +586,9 @@ block, so this is version doesn't pass block and can work just fine:
|
|
|
553
586
|
|
|
554
587
|
```ruby
|
|
555
588
|
browser = Ferrum::Browser.new
|
|
556
|
-
browser.
|
|
557
|
-
|
|
589
|
+
page = browser.create_page
|
|
590
|
+
page.network.intercept
|
|
591
|
+
page.on(:request) do |request|
|
|
558
592
|
if request.resource_type == "Image"
|
|
559
593
|
request.abort
|
|
560
594
|
else
|
|
@@ -562,9 +596,9 @@ browser.on(:request) do |request|
|
|
|
562
596
|
end
|
|
563
597
|
end
|
|
564
598
|
|
|
565
|
-
|
|
599
|
+
page.network.authorize(user: "login", password: "pass", type: :proxy)
|
|
566
600
|
|
|
567
|
-
|
|
601
|
+
page.go_to("https://google.com")
|
|
568
602
|
```
|
|
569
603
|
|
|
570
604
|
You used to call `authorize` method without block, but since it's implemented using request interception there could be
|
|
@@ -587,8 +621,8 @@ Activates emulation of network conditions.
|
|
|
587
621
|
bluetooth, ethernet, wifi, wimax, other. `nil` by default
|
|
588
622
|
|
|
589
623
|
```ruby
|
|
590
|
-
|
|
591
|
-
|
|
624
|
+
page.network.emulate_network_conditions(connection_type: "cellular2g")
|
|
625
|
+
page.go_to("https://github.com/")
|
|
592
626
|
```
|
|
593
627
|
|
|
594
628
|
#### offline_mode
|
|
@@ -596,8 +630,8 @@ browser.go_to("https://github.com/")
|
|
|
596
630
|
Activates offline mode for a page.
|
|
597
631
|
|
|
598
632
|
```ruby
|
|
599
|
-
|
|
600
|
-
|
|
633
|
+
page.network.offline_mode
|
|
634
|
+
page.go_to("https://github.com/") # => Ferrum::StatusError (Request to https://github.com/ failed(net::ERR_INTERNET_DISCONNECTED))
|
|
601
635
|
```
|
|
602
636
|
|
|
603
637
|
#### cache(disable: `Boolean`)
|
|
@@ -605,21 +639,65 @@ browser.go_to("https://github.com/") # => Ferrum::StatusError (Request to https:
|
|
|
605
639
|
Toggles ignoring cache for each request. If true, cache will not be used.
|
|
606
640
|
|
|
607
641
|
```ruby
|
|
608
|
-
|
|
642
|
+
page.network.cache(disable: true)
|
|
609
643
|
```
|
|
610
644
|
|
|
645
|
+
|
|
646
|
+
## Downloads
|
|
647
|
+
|
|
648
|
+
`page.downloads`
|
|
649
|
+
|
|
650
|
+
#### files `Array<Hash>`
|
|
651
|
+
|
|
652
|
+
Returns all information about downloaded files as a `Hash`.
|
|
653
|
+
|
|
654
|
+
```ruby
|
|
655
|
+
page.go_to("http://localhost/attachment.pdf")
|
|
656
|
+
page.downloads.files # => [{"frameId"=>"E3316DF1B5383D38F8ADF7485005FDE3", "guid"=>"11a68745-98ac-4d54-9b57-9f9016c268b3", "url"=>"http://localhost/attachment.pdf", "suggestedFilename"=>"attachment.pdf", "totalBytes"=>4911, "receivedBytes"=>4911, "state"=>"completed"}]
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
#### wait(timeout)
|
|
660
|
+
|
|
661
|
+
Waits until the download is finished.
|
|
662
|
+
|
|
663
|
+
```ruby
|
|
664
|
+
page.go_to("http://localhost/attachment.pdf")
|
|
665
|
+
page.downloads.wait
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
or
|
|
669
|
+
|
|
670
|
+
```ruby
|
|
671
|
+
page.go_to("http://localhost/page")
|
|
672
|
+
page.downloads.wait { page.at_css("#download").click }
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
#### set_behavior(\*\*options)
|
|
676
|
+
|
|
677
|
+
Sets behavior in case of file to be downloaded.
|
|
678
|
+
|
|
679
|
+
* options `Hash`
|
|
680
|
+
* :save_path `String` absolute path of where to store the file
|
|
681
|
+
* :behavior `Symbol` `deny | allow | allowAndName | default`, `allow` by default
|
|
682
|
+
|
|
683
|
+
```ruby
|
|
684
|
+
page.go_to("https://example.com/")
|
|
685
|
+
page.downloads.set_behavior(save_path: "/tmp", behavior: :allow)
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
|
|
611
689
|
## Proxy
|
|
612
690
|
|
|
613
691
|
You can set a proxy with a `:proxy` option:
|
|
614
692
|
|
|
615
693
|
```ruby
|
|
616
|
-
|
|
694
|
+
Ferrum::Browser.new(proxy: { host: "x.x.x.x", port: "8800", user: "user", password: "pa$$" })
|
|
617
695
|
```
|
|
618
696
|
|
|
619
697
|
`:bypass` can specify semi-colon-separated list of hosts for which proxy shouldn't be used:
|
|
620
698
|
|
|
621
699
|
```ruby
|
|
622
|
-
|
|
700
|
+
Ferrum::Browser.new(proxy: { host: "x.x.x.x", port: "8800", bypass: "*.google.com;*foo.com" })
|
|
623
701
|
```
|
|
624
702
|
|
|
625
703
|
In general passing a proxy option when instantiating a browser results in a browser running with proxy command line
|
|
@@ -643,7 +721,7 @@ end
|
|
|
643
721
|
|
|
644
722
|
### Mouse
|
|
645
723
|
|
|
646
|
-
`
|
|
724
|
+
`page.mouse`
|
|
647
725
|
|
|
648
726
|
#### scroll_to(x, y)
|
|
649
727
|
|
|
@@ -655,8 +733,8 @@ Scroll page to a given x, y
|
|
|
655
733
|
displayed in the upper left
|
|
656
734
|
|
|
657
735
|
```ruby
|
|
658
|
-
|
|
659
|
-
|
|
736
|
+
page.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
|
|
737
|
+
page.mouse.scroll_to(0, 400)
|
|
660
738
|
```
|
|
661
739
|
|
|
662
740
|
#### click(\*\*options) : `Mouse`
|
|
@@ -700,7 +778,7 @@ Mouse move to given x and y.
|
|
|
700
778
|
|
|
701
779
|
### Keyboard
|
|
702
780
|
|
|
703
|
-
|
|
781
|
+
`page.keyboard`
|
|
704
782
|
|
|
705
783
|
#### down(key) : `Keyboard`
|
|
706
784
|
|
|
@@ -730,14 +808,14 @@ Returns bitfield for a given keys
|
|
|
730
808
|
|
|
731
809
|
## Cookies
|
|
732
810
|
|
|
733
|
-
`
|
|
811
|
+
`page.cookies`
|
|
734
812
|
|
|
735
813
|
#### all : `Hash<String, Cookie>`
|
|
736
814
|
|
|
737
815
|
Returns cookies hash
|
|
738
816
|
|
|
739
817
|
```ruby
|
|
740
|
-
|
|
818
|
+
page.cookies.all # => {"NID"=>#<Ferrum::Cookies::Cookie:0x0000558624b37a40 @attributes={"name"=>"NID", "value"=>"...", "domain"=>".google.com", "path"=>"/", "expires"=>1583211046.575681, "size"=>178, "httpOnly"=>true, "secure"=>false, "session"=>false}>}
|
|
741
819
|
```
|
|
742
820
|
|
|
743
821
|
#### [](value) : `Cookie`
|
|
@@ -747,7 +825,7 @@ Returns cookie
|
|
|
747
825
|
* value `String`
|
|
748
826
|
|
|
749
827
|
```ruby
|
|
750
|
-
|
|
828
|
+
page.cookies["NID"] # => <Ferrum::Cookies::Cookie:0x0000558624b67a88 @attributes={"name"=>"NID", "value"=>"...", "domain"=>".google.com", "path"=>"/", "expires"=>1583211046.575681, "size"=>178, "httpOnly"=>true, "secure"=>false, "session"=>false}>
|
|
751
829
|
```
|
|
752
830
|
|
|
753
831
|
#### set(value) : `Boolean`
|
|
@@ -763,14 +841,14 @@ Sets a cookie
|
|
|
763
841
|
* :httponly `Boolean`
|
|
764
842
|
|
|
765
843
|
```ruby
|
|
766
|
-
|
|
844
|
+
page.cookies.set(name: "stealth", value: "omg", domain: "google.com") # => true
|
|
767
845
|
```
|
|
768
846
|
|
|
769
847
|
* value `Cookie`
|
|
770
848
|
|
|
771
849
|
```ruby
|
|
772
|
-
nid_cookie =
|
|
773
|
-
|
|
850
|
+
nid_cookie = page.cookies["NID"] # => <Ferrum::Cookies::Cookie:0x0000558624b67a88>
|
|
851
|
+
page.cookies.set(nid_cookie) # => true
|
|
774
852
|
```
|
|
775
853
|
|
|
776
854
|
#### remove(\*\*options) : `Boolean`
|
|
@@ -783,7 +861,7 @@ Removes given cookie
|
|
|
783
861
|
* :url `String`
|
|
784
862
|
|
|
785
863
|
```ruby
|
|
786
|
-
|
|
864
|
+
page.cookies.remove(name: "stealth", domain: "google.com") # => true
|
|
787
865
|
```
|
|
788
866
|
|
|
789
867
|
#### clear : `Boolean`
|
|
@@ -791,12 +869,12 @@ browser.cookies.remove(name: "stealth", domain: "google.com") # => true
|
|
|
791
869
|
Removes all cookies for current page
|
|
792
870
|
|
|
793
871
|
```ruby
|
|
794
|
-
|
|
872
|
+
page.cookies.clear # => true
|
|
795
873
|
```
|
|
796
874
|
|
|
797
875
|
## Headers
|
|
798
876
|
|
|
799
|
-
`
|
|
877
|
+
`page.headers`
|
|
800
878
|
|
|
801
879
|
#### get : `Hash`
|
|
802
880
|
|
|
@@ -830,7 +908,7 @@ Evaluate and return result for given JS expression
|
|
|
830
908
|
simple value.
|
|
831
909
|
|
|
832
910
|
```ruby
|
|
833
|
-
|
|
911
|
+
page.evaluate("[window.scrollX, window.scrollY]")
|
|
834
912
|
```
|
|
835
913
|
|
|
836
914
|
#### evaluate_async(expression, wait_time, \*args)
|
|
@@ -843,7 +921,7 @@ Evaluate asynchronous expression and return result
|
|
|
843
921
|
simple value.
|
|
844
922
|
|
|
845
923
|
```ruby
|
|
846
|
-
|
|
924
|
+
page.evaluate_async(%(arguments[0]({foo: "bar"})), 5) # => { "foo" => "bar" }
|
|
847
925
|
```
|
|
848
926
|
|
|
849
927
|
#### execute(expression, \*args)
|
|
@@ -855,7 +933,7 @@ Execute expression. Doesn't return the result
|
|
|
855
933
|
simple value.
|
|
856
934
|
|
|
857
935
|
```ruby
|
|
858
|
-
|
|
936
|
+
page.execute(%(1 + 1)) # => true
|
|
859
937
|
```
|
|
860
938
|
|
|
861
939
|
#### evaluate_on_new_document(expression)
|
|
@@ -881,7 +959,7 @@ JS
|
|
|
881
959
|
* :type `String` - `text/javascript` by default
|
|
882
960
|
|
|
883
961
|
```ruby
|
|
884
|
-
|
|
962
|
+
page.add_script_tag(url: "http://example.com/stylesheet.css") # => true
|
|
885
963
|
```
|
|
886
964
|
|
|
887
965
|
#### add_style_tag(\*\*options) : `Boolean`
|
|
@@ -892,7 +970,7 @@ browser.add_script_tag(url: "http://example.com/stylesheet.css") # => true
|
|
|
892
970
|
* :content `String`
|
|
893
971
|
|
|
894
972
|
```ruby
|
|
895
|
-
|
|
973
|
+
page.add_style_tag(content: "h1 { font-size: 40px; }") # => true
|
|
896
974
|
|
|
897
975
|
```
|
|
898
976
|
#### bypass_csp(\*\*options) : `Boolean`
|
|
@@ -901,11 +979,39 @@ browser.add_style_tag(content: "h1 { font-size: 40px; }") # => true
|
|
|
901
979
|
* :enabled `Boolean`, `true` by default
|
|
902
980
|
|
|
903
981
|
```ruby
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
982
|
+
page.bypass_csp # => true
|
|
983
|
+
page.go_to("https://github.com/ruby-concurrency/concurrent-ruby/blob/master/docs-source/promises.in.md")
|
|
984
|
+
page.refresh
|
|
985
|
+
page.add_script_tag(content: "window.__injected = 42")
|
|
986
|
+
page.evaluate("window.__injected") # => 42
|
|
987
|
+
```
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
## Emulation
|
|
991
|
+
|
|
992
|
+
#### disable_javascript
|
|
993
|
+
|
|
994
|
+
Disables Javascripts from the loaded HTML source.
|
|
995
|
+
You can still evaluate JavaScript with `evaluate` or `execute`.
|
|
996
|
+
Returns nothing.
|
|
997
|
+
|
|
998
|
+
```ruby
|
|
999
|
+
page.disable_javascript
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
#### set_viewport
|
|
1004
|
+
|
|
1005
|
+
Overrides device screen dimensions and emulates viewport.
|
|
1006
|
+
|
|
1007
|
+
* options `Hash`
|
|
1008
|
+
* :width `Integer`, viewport width. `0` by default
|
|
1009
|
+
* :height `Integer`, viewport height. `0` by default
|
|
1010
|
+
* :scale_factor `Float`, device scale factor. `0` by default
|
|
1011
|
+
* :mobile `Boolean`, whether to emulate mobile device. `false` by default
|
|
1012
|
+
|
|
1013
|
+
```ruby
|
|
1014
|
+
page.set_viewport(width: 1000, height: 600, scale_factor: 3)
|
|
909
1015
|
```
|
|
910
1016
|
|
|
911
1017
|
|
|
@@ -916,8 +1022,8 @@ browser.evaluate("window.__injected") # => 42
|
|
|
916
1022
|
Returns all the frames current page have.
|
|
917
1023
|
|
|
918
1024
|
```ruby
|
|
919
|
-
|
|
920
|
-
|
|
1025
|
+
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
|
1026
|
+
page.frames # =>
|
|
921
1027
|
# [
|
|
922
1028
|
# #<Ferrum::Frame @id="C6D104CE454A025FBCF22B98DE612B12" @parent_id=nil @name=nil @state=:stopped_loading @execution_id=1>,
|
|
923
1029
|
# #<Ferrum::Frame @id="C09C4E4404314AAEAE85928EAC109A93" @parent_id="C6D104CE454A025FBCF22B98DE612B12" @state=:stopped_loading @execution_id=2>,
|
|
@@ -939,7 +1045,7 @@ Find frame by given options.
|
|
|
939
1045
|
* :name `String` - Frame's name if there's one
|
|
940
1046
|
|
|
941
1047
|
```ruby
|
|
942
|
-
|
|
1048
|
+
page.frame_by(id: "C6D104CE454A025FBCF22B98DE612B12")
|
|
943
1049
|
```
|
|
944
1050
|
|
|
945
1051
|
|
|
@@ -975,8 +1081,8 @@ One of the states frame's in:
|
|
|
975
1081
|
Returns current frame's location href.
|
|
976
1082
|
|
|
977
1083
|
```ruby
|
|
978
|
-
|
|
979
|
-
frame =
|
|
1084
|
+
page.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
|
|
1085
|
+
frame = page.frames[1]
|
|
980
1086
|
frame.url # => https://interactive-examples.mdn.mozilla.net/pages/tabbed/iframe.html
|
|
981
1087
|
```
|
|
982
1088
|
|
|
@@ -985,8 +1091,8 @@ frame.url # => https://interactive-examples.mdn.mozilla.net/pages/tabbed/iframe.
|
|
|
985
1091
|
Returns current frame's title.
|
|
986
1092
|
|
|
987
1093
|
```ruby
|
|
988
|
-
|
|
989
|
-
frame =
|
|
1094
|
+
page.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
|
|
1095
|
+
frame = page.frames[1]
|
|
990
1096
|
frame.title # => HTML Demo: <iframe>
|
|
991
1097
|
```
|
|
992
1098
|
|
|
@@ -995,8 +1101,8 @@ frame.title # => HTML Demo: <iframe>
|
|
|
995
1101
|
If current frame is the main frame of the page (top of the tree).
|
|
996
1102
|
|
|
997
1103
|
```ruby
|
|
998
|
-
|
|
999
|
-
frame =
|
|
1104
|
+
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
|
1105
|
+
frame = page.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
|
|
1000
1106
|
frame.main? # => false
|
|
1001
1107
|
```
|
|
1002
1108
|
|
|
@@ -1005,8 +1111,8 @@ frame.main? # => false
|
|
|
1005
1111
|
Returns current frame's top window location href.
|
|
1006
1112
|
|
|
1007
1113
|
```ruby
|
|
1008
|
-
|
|
1009
|
-
frame =
|
|
1114
|
+
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
|
1115
|
+
frame = page.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
|
|
1010
1116
|
frame.current_url # => "https://www.w3schools.com/tags/tag_frame.asp"
|
|
1011
1117
|
```
|
|
1012
1118
|
|
|
@@ -1015,8 +1121,8 @@ frame.current_url # => "https://www.w3schools.com/tags/tag_frame.asp"
|
|
|
1015
1121
|
Returns current frame's top window title.
|
|
1016
1122
|
|
|
1017
1123
|
```ruby
|
|
1018
|
-
|
|
1019
|
-
frame =
|
|
1124
|
+
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
|
1125
|
+
frame = page.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
|
|
1020
1126
|
frame.current_title # => "HTML frame tag"
|
|
1021
1127
|
```
|
|
1022
1128
|
|
|
@@ -1025,8 +1131,8 @@ frame.current_title # => "HTML frame tag"
|
|
|
1025
1131
|
Returns current frame's html.
|
|
1026
1132
|
|
|
1027
1133
|
```ruby
|
|
1028
|
-
|
|
1029
|
-
frame =
|
|
1134
|
+
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
|
1135
|
+
frame = page.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
|
|
1030
1136
|
frame.body # => "<html><head></head><body></body></html>"
|
|
1031
1137
|
```
|
|
1032
1138
|
|
|
@@ -1035,8 +1141,8 @@ frame.body # => "<html><head></head><body></body></html>"
|
|
|
1035
1141
|
Returns current frame's doctype.
|
|
1036
1142
|
|
|
1037
1143
|
```ruby
|
|
1038
|
-
|
|
1039
|
-
|
|
1144
|
+
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
|
|
1145
|
+
page.main_frame.doctype # => "<!DOCTYPE html>"
|
|
1040
1146
|
```
|
|
1041
1147
|
|
|
1042
1148
|
#### content = html
|
|
@@ -1046,8 +1152,8 @@ Sets a content of a given frame.
|
|
|
1046
1152
|
* html `String`
|
|
1047
1153
|
|
|
1048
1154
|
```ruby
|
|
1049
|
-
|
|
1050
|
-
frame =
|
|
1155
|
+
page.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
|
|
1156
|
+
frame = page.frames[1]
|
|
1051
1157
|
frame.body # <html lang="en"><head><style>body {transition: opacity ease-in 0.2s; }...
|
|
1052
1158
|
frame.content = "<html><head></head><body><p>lol</p></body></html>"
|
|
1053
1159
|
frame.body # => <html><head></head><body><p>lol</p></body></html>
|
|
@@ -1067,15 +1173,14 @@ Accept dialog with given text or default prompt if applicable
|
|
|
1067
1173
|
Dismiss dialog
|
|
1068
1174
|
|
|
1069
1175
|
```ruby
|
|
1070
|
-
|
|
1071
|
-
browser.on(:dialog) do |dialog|
|
|
1176
|
+
page.on(:dialog) do |dialog|
|
|
1072
1177
|
if dialog.match?(/bla-bla/)
|
|
1073
1178
|
dialog.accept
|
|
1074
1179
|
else
|
|
1075
1180
|
dialog.dismiss
|
|
1076
1181
|
end
|
|
1077
1182
|
end
|
|
1078
|
-
|
|
1183
|
+
page.go_to("https://google.com")
|
|
1079
1184
|
```
|
|
1080
1185
|
|
|
1081
1186
|
|
|
@@ -1095,10 +1200,9 @@ Sets playback rate of CSS animations
|
|
|
1095
1200
|
* value `Integer`
|
|
1096
1201
|
|
|
1097
1202
|
```ruby
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
browser.playback_rate # => 2000
|
|
1203
|
+
page.playback_rate = 2000
|
|
1204
|
+
page.go_to("https://google.com")
|
|
1205
|
+
page.playback_rate # => 2000
|
|
1102
1206
|
```
|
|
1103
1207
|
|
|
1104
1208
|
|
|
@@ -1112,7 +1216,7 @@ Returns [Frame](https://github.com/rubycdp/ferrum#frame) object for current node
|
|
|
1112
1216
|
[Finders](https://github.com/rubycdp/ferrum#Finders) for that object:
|
|
1113
1217
|
|
|
1114
1218
|
```ruby
|
|
1115
|
-
frame =
|
|
1219
|
+
frame = page.at_xpath("//iframe").frame # => Frame
|
|
1116
1220
|
frame.at_css("//a[text() = 'Log in']") # => Node
|
|
1117
1221
|
```
|
|
1118
1222
|
|
|
@@ -1143,15 +1247,15 @@ frame.at_css("//a[text() = 'Log in']") # => Node
|
|
|
1143
1247
|
(chainable) Selects options by passed attribute.
|
|
1144
1248
|
|
|
1145
1249
|
```ruby
|
|
1146
|
-
|
|
1147
|
-
|
|
1250
|
+
page.at_xpath("//*[select]").select(["1"]) # => Node (select)
|
|
1251
|
+
page.at_xpath("//*[select]").select(["text"], by: :text) # => Node (select)
|
|
1148
1252
|
```
|
|
1149
1253
|
|
|
1150
1254
|
Accept string, array or strings:
|
|
1151
1255
|
```ruby
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1256
|
+
page.at_xpath("//*[select]").select("1")
|
|
1257
|
+
page.at_xpath("//*[select]").select("1", "2")
|
|
1258
|
+
page.at_xpath("//*[select]").select(["1", "2"])
|
|
1155
1259
|
```
|
|
1156
1260
|
|
|
1157
1261
|
|
|
@@ -1182,6 +1286,25 @@ Accepts block, records trace and by default returns trace data from `Tracing.tra
|
|
|
1182
1286
|
only one trace config can be active at a time per browser.
|
|
1183
1287
|
|
|
1184
1288
|
|
|
1289
|
+
## Clean Up
|
|
1290
|
+
|
|
1291
|
+
#### reset
|
|
1292
|
+
|
|
1293
|
+
Closes browser tabs opened by the `Browser` instance.
|
|
1294
|
+
|
|
1295
|
+
```ruby
|
|
1296
|
+
# connect to a long-running Chrome process
|
|
1297
|
+
browser = Ferrum::Browser.new(url: 'http://localhost:9222')
|
|
1298
|
+
|
|
1299
|
+
browser.go_to("https://github.com/")
|
|
1300
|
+
|
|
1301
|
+
# clean up, lest the tab stays there hanging forever
|
|
1302
|
+
browser.reset
|
|
1303
|
+
|
|
1304
|
+
browser.quit
|
|
1305
|
+
```
|
|
1306
|
+
|
|
1307
|
+
|
|
1185
1308
|
## Thread safety ##
|
|
1186
1309
|
|
|
1187
1310
|
Ferrum is fully thread-safe. You can create one browser or a few as you wish and
|