diff --git a/.config.example.yml b/.config.example.yml index 9ee7ffe..94675f5 100644 --- a/.config.example.yml +++ b/.config.example.yml @@ -33,6 +33,14 @@ stop_on_error: 1 proxy: host: '10.10.2.70' port: 8080 + # In some cases you may also need to tell the browser (driver) not to use the + # proxy for local or specific connections. For this simply provide a comma + # separated list of addresses. + # + # IMPORTANT NOTE! phantomjs does not currently support this option. If you + # have to go via a proxy server for external connections, but not local ones + # you will be limited to using either the Chrome or Firefox drivers. + no_proxy: '127.0.0.1,192.168.0.1' # If you select the browserstack driver, there are a number of options you # can pass through to setup your browserstack tests, username and auth_key diff --git a/lib/quke/configuration.rb b/lib/quke/configuration.rb index 1dcc71b..7e28faa 100644 --- a/lib/quke/configuration.rb +++ b/lib/quke/configuration.rb @@ -169,7 +169,8 @@ def proxy_data(data) data = {} if data.nil? data.merge( 'host' => (data['host'] || '').downcase.strip, - 'port' => (data['port'] || '0').to_s.downcase.strip.to_i + 'port' => (data['port'] || '0').to_s.downcase.strip.to_i, + 'no_proxy' => (data['no_proxy'] || '').downcase.strip ) end diff --git a/lib/quke/driver_configuration.rb b/lib/quke/driver_configuration.rb index dbc9466..c24edd0 100644 --- a/lib/quke/driver_configuration.rb +++ b/lib/quke/driver_configuration.rb @@ -118,7 +118,10 @@ def phantomjs # Capybara::Selenium::Driver.new( # app, # browser: :chrome, - # switches: ["--proxy-server=localhost:8080"] + # switches: [ + # "--proxy-server=localhost:8080", + # "--proxy-bypass-list=127.0.0.1,192.168.0.1" + # ] # ) # # Rather than setting the switches manually Quke::DriverConfiguration.chrome @@ -131,13 +134,20 @@ def phantomjs # switches: my_driver_config.chrome # ) # + # rubocop:disable Metrics/AbcSize def chrome - if config.use_proxy? - ["--proxy-server=#{config.proxy['host']}:#{config.proxy['port']}"] - else - [] - end + result = [] + + host = config.proxy['host'] + port = config.proxy['port'] + no_proxy = config.proxy['no_proxy'].tr(',', ';') + + result.push("--proxy-server=#{host}:#{port}") if config.use_proxy? + result.push("--proxy-bypass-list=#{no_proxy}") unless config.proxy['no_proxy'].empty? + + result end + # rubocop:enable Metrics/AbcSize # Returns an instance of Selenium::WebDriver::Remote::Capabilities to be # used when registering an instance of Capybara::Selenium::Driver, @@ -169,12 +179,16 @@ def chrome def firefox profile = Selenium::WebDriver::Firefox::Profile.new - if config.use_proxy? - profile.proxy = Selenium::WebDriver::Proxy.new( - http: "#{config.proxy['host']}:#{config.proxy['port']}", - ssl: "#{config.proxy['host']}:#{config.proxy['port']}" - ) - end + settings = {} + host = config.proxy['host'] + port = config.proxy['port'] + no_proxy = config.proxy['no_proxy'] + + settings[:http] = "#{host}:#{port}" if config.use_proxy? + settings[:ssl] = settings[:http] if config.use_proxy? + settings[:no_proxy] = no_proxy unless config.proxy['no_proxy'].empty? + + profile.proxy = Selenium::WebDriver::Proxy.new(settings) if config.use_proxy? profile end diff --git a/lib/quke/driver_registration.rb b/lib/quke/driver_registration.rb index fbd1f80..fe75b77 100644 --- a/lib/quke/driver_registration.rb +++ b/lib/quke/driver_registration.rb @@ -43,6 +43,9 @@ def register(driver) # poltergeist, and we can even pass on options to phantomjs to configure how # it runs. def phantomjs + # For future reference the options we pass through to phantomjs appear to + # mirror those you can actually supply on the command line. + # http://phantomjs.org/api/command-line.html Capybara.register_driver :phantomjs do |app| # We ignore the next line (and those like it in the subsequent methods) # from code coverage because we never actually execute them from Quke. @@ -65,6 +68,8 @@ def firefox # object. # https://github.com/SeleniumHQ/selenium/wiki/Ruby-Bindings#firefox # http://www.rubydoc.info/gems/selenium-webdriver/0.0.28/Selenium/WebDriver/Firefox/Profile + # http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp + # http://preferential.mozdev.org/preferences.html Capybara.register_driver :firefox do |app| # :simplecov_ignore: Capybara::Selenium::Driver.new(app, profile: config.firefox) @@ -81,6 +86,7 @@ def chrome # Capybara to Selenium-webdriver, which in turn passes it to chromium # https://github.com/SeleniumHQ/selenium/wiki/Ruby-Bindings#chrome # http://peter.sh/experiments/chromium-command-line-switches/ + # https://www.chromium.org/developers/design-documents/network-settings Capybara.register_driver :chrome do |app| # :simplecov_ignore: Capybara::Selenium::Driver.new( diff --git a/lib/quke/version.rb b/lib/quke/version.rb index 31933fd..ba37a2c 100644 --- a/lib/quke/version.rb +++ b/lib/quke/version.rb @@ -1,3 +1,3 @@ module Quke #:nodoc: - VERSION = '0.2.6'.freeze + VERSION = '0.2.7'.freeze end diff --git a/spec/data/.as_string.yml b/spec/data/.as_string.yml index 9385799..7f56a47 100644 --- a/spec/data/.as_string.yml +++ b/spec/data/.as_string.yml @@ -5,5 +5,4 @@ pause: '1' stop_on_error: 'true' proxy: - host: '10.10.2.70' port: '8080' diff --git a/spec/data/.proxy.yml b/spec/data/.proxy.yml new file mode 100644 index 0000000..14bdcdb --- /dev/null +++ b/spec/data/.proxy.yml @@ -0,0 +1,4 @@ +proxy: + host: '10.10.2.70' + port: 8080 + no_proxy: '127.0.0.1,192.168.0.1' diff --git a/spec/quke/configuration_spec.rb b/spec/quke/configuration_spec.rb index 48a3b77..e1178ec 100644 --- a/spec/quke/configuration_spec.rb +++ b/spec/quke/configuration_spec.rb @@ -97,18 +97,19 @@ describe '#proxy' do context 'when NOT specified in the config file' do - it 'defaults to a blank host and port' do + it 'defaults to a blank values' do Quke::Configuration.file_location = data_path('.no_file.yml') - expect(subject.proxy).to eq('host' => '', 'port' => 0) + expect(subject.proxy).to eq('host' => '', 'port' => 0, 'no_proxy' => '') end end context 'when specified in the config file' do it 'matches the config file' do - Quke::Configuration.file_location = data_path('.simple.yml') + Quke::Configuration.file_location = data_path('.proxy.yml') expect(subject.proxy).to eq( 'host' => '10.10.2.70', - 'port' => 8080 + 'port' => 8080, + 'no_proxy' => '127.0.0.1,192.168.0.1' ) end end @@ -117,8 +118,9 @@ it 'matches the config file' do Quke::Configuration.file_location = data_path('.as_string.yml') expect(subject.proxy).to eq( - 'host' => '10.10.2.70', - 'port' => 8080 + 'host' => '', + 'port' => 8080, + 'no_proxy' => '' ) end end diff --git a/spec/quke/driver_configuration_spec.rb b/spec/quke/driver_configuration_spec.rb index 9b813a3..eeef821 100644 --- a/spec/quke/driver_configuration_spec.rb +++ b/spec/quke/driver_configuration_spec.rb @@ -86,17 +86,30 @@ end end - context 'proxy details have been set in the .config.yml' do - it 'returns an array containing proxy settings' do + context 'basic proxy details have been set in the .config.yml' do + it 'returns an array containing basic proxy settings' do Quke::Configuration.file_location = data_path('.simple.yml') config = Quke::Configuration.new expect(Quke::DriverConfiguration.new(config).chrome).to eq(["--proxy-server=#{config.proxy['host']}:#{config.proxy['port']}"]) end end + context 'proxy details including addresses not to connect via the proxy server have been set in the .config.yml' do + it 'returns an array containing proxy settings including no-proxy details' do + Quke::Configuration.file_location = data_path('.proxy.yml') + config = Quke::Configuration.new + expect(Quke::DriverConfiguration.new(config).chrome).to eq( + [ + "--proxy-server=#{config.proxy['host']}:#{config.proxy['port']}", + '--proxy-bypass-list=127.0.0.1;192.168.0.1' + ] + ) + end + end + end - describe '#firefox' do + describe '#firefox', focus: true do context 'proxy details have NOT been set in the .config.yml' do it 'returns a profile where the proxy details are NOT set' do @@ -113,8 +126,8 @@ end end - context 'proxy details have been set in the .config.yml' do - it 'returns a profile where the proxy details are set' do + context 'basic proxy details have been set in the .config.yml' do + it 'returns a profile where the basic proxy details are set' do Quke::Configuration.file_location = data_path('.simple.yml') config = Quke::Configuration.new profile = Quke::DriverConfiguration.new(config).firefox @@ -128,6 +141,22 @@ end end + context 'proxy details including addresses not to connect via the proxy server have been set in the .config.yml' do + it 'returns a profile where the proxy details are set including no-proxy details' do + Quke::Configuration.file_location = data_path('.proxy.yml') + config = Quke::Configuration.new + profile = Quke::DriverConfiguration.new(config).firefox + + # See spec/helpers.rb#read_profile_preferences for details of why we + # need to test the profile's properties in this way + preferences = read_profile_preferences(profile) + + expect(preferences).to include('user_pref("network.proxy.http", "10.10.2.70")') + expect(preferences).to include('user_pref("network.proxy.http_port", 8080)') + expect(preferences).to include('user_pref("network.proxy.no_proxies_on", "127.0.0.1,192.168.0.1")') + end + end + end describe '#browserstack_url' do