From 7f4c5bf27aa0800fcbf97785c887aa228e7e18e0 Mon Sep 17 00:00:00 2001 From: Dmitry Vorotilin Date: Sun, 8 May 2022 13:45:03 +0200 Subject: [PATCH 1/3] 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 From d98fc13d306bff8f697e24cf07f05870eab60668 Mon Sep 17 00:00:00 2001 From: Dmitry Vorotilin Date: Sun, 8 May 2022 13:54:00 +0200 Subject: [PATCH 2/3] Fix rubocop --- lib/ferrum/browser.rb | 2 +- lib/ferrum/browser/command.rb | 2 +- lib/ferrum/network.rb | 8 ++++---- spec/browser_spec.rb | 4 ++-- spec/network_spec.rb | 6 +++--- spec/spec_helper.rb | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/ferrum/browser.rb b/lib/ferrum/browser.rb index 8926195f..ec266a81 100644 --- a/lib/ferrum/browser.rb +++ b/lib/ferrum/browser.rb @@ -67,7 +67,7 @@ def initialize(options = nil) self.base_url = @options[:base_url] if @options.key?(:base_url) - if ENV["FERRUM_DEBUG"] && !@logger + if ENV.fetch("FERRUM_DEBUG", nil) && !@logger $stdout.sync = true @logger = $stdout @options[:logger] = @logger diff --git a/lib/ferrum/browser/command.rb b/lib/ferrum/browser/command.rb index f8613a69..187e1c8c 100644 --- a/lib/ferrum/browser/command.rb +++ b/lib/ferrum/browser/command.rb @@ -29,7 +29,7 @@ def initialize(defaults, options, user_data_dir) @defaults = defaults @options = options @user_data_dir = user_data_dir - @path = options[:browser_path] || ENV["BROWSER_PATH"] || defaults.detect_path + @path = options[:browser_path] || ENV.fetch("BROWSER_PATH", nil) || defaults.detect_path raise Cliver::Dependency::NotFound, NOT_FOUND unless @path merge_options diff --git a/lib/ferrum/network.rb b/lib/ferrum/network.rb index 8b7d2dcc..eb6ec0b8 100644 --- a/lib/ferrum/network.rb +++ b/lib/ferrum/network.rb @@ -151,16 +151,16 @@ 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) + 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 + params[:connectionType] = connection_type if connection_type && ALLOWED_CONNECTION_TYPE.include?(connection_type) @page.command("Network.emulateNetworkConditions", params) true diff --git a/spec/browser_spec.rb b/spec/browser_spec.rb index 7bc6672e..ca3e4826 100644 --- a/spec/browser_spec.rb +++ b/spec/browser_spec.rb @@ -369,11 +369,11 @@ module Ferrum it "allows the driver to have a custom host", skip: ENV["BROWSER_TEST_HOST"].nil? do # Use custom host "pointing" to localhost in /etc/hosts or iptables for this. # https://superuser.com/questions/516208/how-to-change-ip-address-to-point-to-localhost - browser = Browser.new(host: ENV["BROWSER_TEST_HOST"], port: 12_345) + browser = Browser.new(host: ENV.fetch("BROWSER_TEST_HOST"), port: 12_345) browser.go_to(base_url) expect do - TCPServer.new(ENV["BROWSER_TEST_HOST"], 12_345) + TCPServer.new(ENV.fetch("BROWSER_TEST_HOST"), 12_345) end.to raise_error(Errno::EADDRINUSE) ensure browser&.quit diff --git a/spec/network_spec.rb b/spec/network_spec.rb index 96dbaea0..30fe7183 100644 --- a/spec/network_spec.rb +++ b/spec/network_spec.rb @@ -407,9 +407,9 @@ module Ferrum 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} - ) + Ferrum::StatusError, + %r{Request to http://.*/ferrum/with_js failed to reach server, check DNS and server status} + ) expect(page.body).to eq("") end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index cc28af7a..4e2260e6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -54,7 +54,7 @@ end config.after(:each) do |example| - save_exception_artifacts(browser, example.metadata, ferrum_logger) if ENV["CI"] && example.exception + save_exception_artifacts(browser, example.metadata, ferrum_logger) if ENV.fetch("CI", nil) && example.exception reset end From 508f510f0e3e680815b68a8e308352d03ffd6b3f Mon Sep 17 00:00:00 2001 From: Dmitry Vorotilin Date: Sun, 8 May 2022 13:58:00 +0200 Subject: [PATCH 3/3] Fix specs for Ruby 3.0 --- lib/ferrum/network.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ferrum/network.rb b/lib/ferrum/network.rb index eb6ec0b8..63f7f941 100644 --- a/lib/ferrum/network.rb +++ b/lib/ferrum/network.rb @@ -162,7 +162,7 @@ def emulate_network_conditions(offline: false, latency: 0, params[:connectionType] = connection_type if connection_type && ALLOWED_CONNECTION_TYPE.include?(connection_type) - @page.command("Network.emulateNetworkConditions", params) + @page.command("Network.emulateNetworkConditions", **params) true end