Skip to content

Commit 70b5d85

Browse files
authored
Merge pull request #264 from rubycdp/offline
Fix #158 Switch browser to offline mode
2 parents 8357994 + 508f510 commit 70b5d85

File tree

8 files changed

+77
-6
lines changed

8 files changed

+77
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ a block with this page, after which the page is closed.
2020
- Windows support
2121
- Show warning and accept dialog if no handler given
2222
- `Ferrum::Cookies#set` ability to set cookie using `Ferrum::Cookies::Cookie` object
23+
- `Ferrum::Network#emulate_network_conditions` activates emulation of network conditions
24+
- `Ferrum::Network#offline_mode` puts browser into offline mode
2325

2426
### Changed
2527

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,13 +561,41 @@ end
561561
browser.network.authorize(user: "login", password: "pass", type: :proxy)
562562

563563
browser.go_to("https://google.com")
564-
565564
```
566565

567566
You used to call `authorize` method without block, but since it's implemented using request interception there could be
568567
a collision with another part of your code that also uses request interception, so that authorize allows the request
569568
while your code denies but it's too late. The block is mandatory now.
570569

570+
#### emulate_network_conditions(\*\*options)
571+
572+
Activates emulation of network conditions.
573+
574+
* options `Hash`
575+
* :offline `Boolean` emulate internet disconnection, `false` by default
576+
* :latency `Integer` minimum latency from request sent to response headers received (ms), `0` by
577+
default
578+
* :download_throughput `Integer` maximal aggregated download throughput (bytes/sec), `-1`
579+
by default, disables download throttling
580+
* :upload_throughput `Integer` maximal aggregated upload throughput (bytes/sec), `-1`
581+
by default, disables download throttling
582+
* :connection_type `String` connection type if known, one of: none, cellular2g, cellular3g, cellular4g,
583+
bluetooth, ethernet, wifi, wimax, other. `nil` by default
584+
585+
```ruby
586+
browser.network.emulate_network_conditions(connection_type: "cellular2g")
587+
browser.go_to("https://github.com/")
588+
```
589+
590+
#### offline_mode
591+
592+
Activates offline mode for a page.
593+
594+
```ruby
595+
browser.network.offline_mode
596+
browser.go_to("https://github.com/") # => Ferrum::StatusError (Request to https://github.com/ failed to reach server, check DNS and server status)
597+
```
598+
571599

572600
## Proxy
573601

lib/ferrum/browser.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def initialize(options = nil)
6767

6868
self.base_url = @options[:base_url] if @options.key?(:base_url)
6969

70-
if ENV["FERRUM_DEBUG"] && !@logger
70+
if ENV.fetch("FERRUM_DEBUG", nil) && !@logger
7171
$stdout.sync = true
7272
@logger = $stdout
7373
@options[:logger] = @logger

lib/ferrum/browser/command.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def initialize(defaults, options, user_data_dir)
2929
@defaults = defaults
3030
@options = options
3131
@user_data_dir = user_data_dir
32-
@path = options[:browser_path] || ENV["BROWSER_PATH"] || defaults.detect_path
32+
@path = options[:browser_path] || ENV.fetch("BROWSER_PATH", nil) || defaults.detect_path
3333
raise Cliver::Dependency::NotFound, NOT_FOUND unless @path
3434

3535
merge_options

lib/ferrum/network.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Network
1717
AUTHORIZE_BLOCK_MISSING = "Block is missing, call `authorize(...) { |r| r.continue } "\
1818
"or subscribe to `on(:request)` events before calling it"
1919
AUTHORIZE_TYPE_WRONG = ":type should be in #{AUTHORIZE_TYPE}"
20+
ALLOWED_CONNECTION_TYPE = %w[none cellular2g cellular3g cellular4g bluetooth ethernet wifi wimax other].freeze
2021

2122
attr_reader :traffic
2223

@@ -150,6 +151,25 @@ def build_exchange(id)
150151
Network::Exchange.new(@page, id).tap { |e| @traffic << e }
151152
end
152153

154+
def emulate_network_conditions(offline: false, latency: 0,
155+
download_throughput: -1, upload_throughput: -1,
156+
connection_type: nil)
157+
params = {
158+
offline: offline, latency: latency,
159+
downloadThroughput: download_throughput,
160+
uploadThroughput: upload_throughput
161+
}
162+
163+
params[:connectionType] = connection_type if connection_type && ALLOWED_CONNECTION_TYPE.include?(connection_type)
164+
165+
@page.command("Network.emulateNetworkConditions", **params)
166+
true
167+
end
168+
169+
def offline_mode
170+
emulate_network_conditions(offline: true, latency: 0, download_throughput: 0, upload_throughput: 0)
171+
end
172+
153173
private
154174

155175
def subscribe_request_will_be_sent

spec/browser_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,11 @@ module Ferrum
369369
it "allows the driver to have a custom host", skip: ENV["BROWSER_TEST_HOST"].nil? do
370370
# Use custom host "pointing" to localhost in /etc/hosts or iptables for this.
371371
# https://superuser.com/questions/516208/how-to-change-ip-address-to-point-to-localhost
372-
browser = Browser.new(host: ENV["BROWSER_TEST_HOST"], port: 12_345)
372+
browser = Browser.new(host: ENV.fetch("BROWSER_TEST_HOST"), port: 12_345)
373373
browser.go_to(base_url)
374374

375375
expect do
376-
TCPServer.new(ENV["BROWSER_TEST_HOST"], 12_345)
376+
TCPServer.new(ENV.fetch("BROWSER_TEST_HOST"), 12_345)
377377
end.to raise_error(Errno::EADDRINUSE)
378378
ensure
379379
browser&.quit

spec/network_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,5 +393,25 @@ module Ferrum
393393
expect(page.body).to include("Authorized POST request")
394394
end
395395
end
396+
397+
it "#emulate_network_conditions", skip: "doesn't work for now" do
398+
page.network.emulate_network_conditions(latency: 500)
399+
400+
start = Utils::ElapsedTime.monotonic_time
401+
page.go_to("/ferrum/with_js")
402+
403+
expect(Utils::ElapsedTime.elapsed_time(start)).to eq(2000)
404+
end
405+
406+
it "#offline_mode" do
407+
page.network.offline_mode
408+
409+
expect { page.go_to("/ferrum/with_js") }.to raise_error(
410+
Ferrum::StatusError,
411+
%r{Request to http://.*/ferrum/with_js failed to reach server, check DNS and server status}
412+
)
413+
414+
expect(page.body).to eq("<html><head></head><body></body></html>")
415+
end
396416
end
397417
end

spec/spec_helper.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
base_url = Ferrum::Server.server.base_url
3131
options = { base_url: base_url }
3232
options.merge!(headless: false) if ENV["HEADLESS"] == "false"
33+
options.merge!(slowmo: ENV["SLOWMO"].to_f) if ENV["SLOWMO"].to_f > 0
3334

3435
if ENV["CI"]
3536
ferrum_logger = StringIO.new
@@ -53,7 +54,7 @@
5354
end
5455

5556
config.after(:each) do |example|
56-
save_exception_artifacts(browser, example.metadata, ferrum_logger) if ENV["CI"] && example.exception
57+
save_exception_artifacts(browser, example.metadata, ferrum_logger) if ENV.fetch("CI", nil) && example.exception
5758

5859
reset
5960
end

0 commit comments

Comments
 (0)