From 7f4c5bf27aa0800fcbf97785c887aa228e7e18e0 Mon Sep 17 00:00:00 2001 From: Dmitry Vorotilin Date: Sun, 8 May 2022 13:45:03 +0200 Subject: [PATCH] Switch browser to offline mode --- CHANGELOG.md | 2 ++ README.md | 30 +++++++++++++++++++++++++++++- lib/ferrum/network.rb | 20 ++++++++++++++++++++ spec/network_spec.rb | 20 ++++++++++++++++++++ spec/spec_helper.rb | 1 + 5 files changed, 72 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3db7763e..44598e5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ a block with this page, after which the page is closed. - Windows support - Show warning and accept dialog if no handler given - `Ferrum::Cookies#set` ability to set cookie using `Ferrum::Cookies::Cookie` object +- `Ferrum::Network#emulate_network_conditions` activates emulation of network conditions +- `Ferrum::Network#offline_mode` puts browser into offline mode ### Changed diff --git a/README.md b/README.md index 6f4b9bb8..d1a01364 100644 --- a/README.md +++ b/README.md @@ -561,13 +561,41 @@ end browser.network.authorize(user: "login", password: "pass", type: :proxy) browser.go_to("https://google.com") - ``` You used to call `authorize` method without block, but since it's implemented using request interception there could be a collision with another part of your code that also uses request interception, so that authorize allows the request while your code denies but it's too late. The block is mandatory now. +#### emulate_network_conditions(\*\*options) + +Activates emulation of network conditions. + +* options `Hash` + * :offline `Boolean` emulate internet disconnection, `false` by default + * :latency `Integer` minimum latency from request sent to response headers received (ms), `0` by + default + * :download_throughput `Integer` maximal aggregated download throughput (bytes/sec), `-1` + by default, disables download throttling + * :upload_throughput `Integer` maximal aggregated upload throughput (bytes/sec), `-1` + by default, disables download throttling + * :connection_type `String` connection type if known, one of: none, cellular2g, cellular3g, cellular4g, + bluetooth, ethernet, wifi, wimax, other. `nil` by default + +```ruby +browser.network.emulate_network_conditions(connection_type: "cellular2g") +browser.go_to("https://github.com/") +``` + +#### offline_mode + +Activates offline mode for a page. + +```ruby +browser.network.offline_mode +browser.go_to("https://github.com/") # => Ferrum::StatusError (Request to https://github.com/ failed to reach server, check DNS and server status) +``` + ## Proxy diff --git a/lib/ferrum/network.rb b/lib/ferrum/network.rb index 1722be94..8b7d2dcc 100644 --- a/lib/ferrum/network.rb +++ b/lib/ferrum/network.rb @@ -17,6 +17,7 @@ class Network AUTHORIZE_BLOCK_MISSING = "Block is missing, call `authorize(...) { |r| r.continue } "\ "or subscribe to `on(:request)` events before calling it" AUTHORIZE_TYPE_WRONG = ":type should be in #{AUTHORIZE_TYPE}" + ALLOWED_CONNECTION_TYPE = %w[none cellular2g cellular3g cellular4g bluetooth ethernet wifi wimax other].freeze attr_reader :traffic @@ -150,6 +151,25 @@ def build_exchange(id) Network::Exchange.new(@page, id).tap { |e| @traffic << e } end + def emulate_network_conditions(offline: false, latency: 0, download_throughput: -1, upload_throughput: -1, connection_type: nil) + params = { + offline: offline, latency: latency, + downloadThroughput: download_throughput, + uploadThroughput: upload_throughput + } + + if connection_type && ALLOWED_CONNECTION_TYPE.include?(connection_type) + params[:connectionType] = connection_type + end + + @page.command("Network.emulateNetworkConditions", params) + true + end + + def offline_mode + emulate_network_conditions(offline: true, latency: 0, download_throughput: 0, upload_throughput: 0) + end + private def subscribe_request_will_be_sent diff --git a/spec/network_spec.rb b/spec/network_spec.rb index 16c29cd4..96dbaea0 100644 --- a/spec/network_spec.rb +++ b/spec/network_spec.rb @@ -393,5 +393,25 @@ module Ferrum expect(page.body).to include("Authorized POST request") end end + + it "#emulate_network_conditions", skip: "doesn't work for now" do + page.network.emulate_network_conditions(latency: 500) + + start = Utils::ElapsedTime.monotonic_time + page.go_to("/ferrum/with_js") + + expect(Utils::ElapsedTime.elapsed_time(start)).to eq(2000) + end + + it "#offline_mode" do + page.network.offline_mode + + expect { page.go_to("/ferrum/with_js") }.to raise_error( + Ferrum::StatusError, + %r{Request to http://.*/ferrum/with_js failed to reach server, check DNS and server status} + ) + + expect(page.body).to eq("") + end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2f9dad2b..cc28af7a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -30,6 +30,7 @@ base_url = Ferrum::Server.server.base_url options = { base_url: base_url } options.merge!(headless: false) if ENV["HEADLESS"] == "false" + options.merge!(slowmo: ENV["SLOWMO"].to_f) if ENV["SLOWMO"].to_f > 0 if ENV["CI"] ferrum_logger = StringIO.new