diff --git a/CHANGELOG.md b/CHANGELOG.md index cb1c5263..713cbb00 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 f1a3d378..ee7ab7d6 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/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 1722be94..63f7f941 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 + } + + params[:connectionType] = connection_type if connection_type && ALLOWED_CONNECTION_TYPE.include?(connection_type) + + @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/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 16c29cd4..30fe7183 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..4e2260e6 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 @@ -53,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