diff --git a/.rubocop.yml b/.rubocop.yml index 51289a0a..7a4688b6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,5 @@ AllCops: - TargetRubyVersion: 2.6 + TargetRubyVersion: 2.7 NewCops: enable SuggestExtensions: false diff --git a/README.md b/README.md index e616baed..22a0320d 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,9 @@ Besides capybara screenshot method you can get image as Base64: ## Authorization * `page.driver.basic_authorize(user, password)` + +## Proxy + * `page.driver.set_proxy(ip, port, type, user, password)` @@ -192,14 +195,14 @@ Cuprite supports URL blacklisting, which allows you to prevent scripts from running on designated domains: ```ruby -page.driver.browser.url_blacklist = ["http://www.example.com"] +page.driver.browser.url_blacklist = %r{http://www.example.com} ``` and also URL whitelisting, which allows scripts to only run on designated domains: ```ruby -page.driver.browser.url_whitelist = ["http://www.example.com"] +page.driver.browser.url_whitelist = %r{http://www.example.com} ``` If you are experiencing slower run times, consider creating a URL whitelist of diff --git a/cuprite.gemspec b/cuprite.gemspec index d06b4553..4888654d 100644 --- a/cuprite.gemspec +++ b/cuprite.gemspec @@ -22,7 +22,7 @@ Gem::Specification.new do |s| "rubygems_mfa_required" => "true" } - s.required_ruby_version = ">= 2.6.0" + s.required_ruby_version = ">= 2.7.0" s.add_runtime_dependency "capybara", "~> 3.0" s.add_runtime_dependency "ferrum", "~> 0.13.0" diff --git a/lib/capybara/cuprite/browser.rb b/lib/capybara/cuprite/browser.rb index 8d539f1d..d9d754d1 100644 --- a/lib/capybara/cuprite/browser.rb +++ b/lib/capybara/cuprite/browser.rb @@ -46,13 +46,15 @@ def quit def url_whitelist=(patterns) @url_whitelist = prepare_wildcards(patterns) - page.network.intercept if @client && !@url_whitelist.empty? + page.network.whitelist = @url_whitelist if @client && @url_whitelist.any? end + alias url_allowlist= url_whitelist= def url_blacklist=(patterns) @url_blacklist = prepare_wildcards(patterns) - page.network.intercept if @client && !@url_blacklist.empty? + page.network.blacklist = @url_blacklist if @client && @url_blacklist.any? end + alias url_blocklist= url_blacklist= def visit(*args) goto(*args) @@ -199,15 +201,22 @@ def find_all(method, selector, within = nil) raise end - def prepare_wildcards(wc) - Array(wc).map do |wildcard| - if wildcard.is_a?(Regexp) - wildcard + def prepare_wildcards(patterns) + string_passed = false + + Array(patterns).map do |pattern| + if pattern.is_a?(Regexp) + pattern else - wildcard = wildcard.gsub("*", ".*") - Regexp.new(wildcard, Regexp::IGNORECASE) + string_passed = true + pattern = pattern.gsub("*", ".*") + Regexp.new(pattern, Regexp::IGNORECASE) end end + ensure + if string_passed + warn "Passing strings to blacklist/whitelist is deprecated, pass regexp at #{caller(4..4).first}" + end end def attach_page(target_id = nil) diff --git a/lib/capybara/cuprite/driver.rb b/lib/capybara/cuprite/driver.rb index 83d90e21..4a5cfe41 100644 --- a/lib/capybara/cuprite/driver.rb +++ b/lib/capybara/cuprite/driver.rb @@ -3,9 +3,9 @@ require "uri" require "forwardable" +# rubocop:disable Metrics/ClassLength module Capybara module Cuprite - # rubocop:disable Metrics/ClassLength class Driver < Capybara::Driver::Base DEFAULT_MAXIMIZE_SCREEN_SIZE = [1366, 768].freeze EXTENSION = File.expand_path("javascripts/index.js", __dir__) @@ -205,16 +205,7 @@ def clear_network_traffic end def set_proxy(host, port, user = nil, password = nil, bypass = nil) - browser_options = @options.fetch(:browser_options, {}) - browser_options = browser_options.merge("proxy-server" => "#{host}:#{port}") - browser_options = browser_options.merge("proxy-bypass-list" => bypass) if bypass - @options[:browser_options] = browser_options - - return unless user && password - - browser.network.authorize(user: user, password: password, type: :proxy) do |request, _index, _total| - request.continue - end + @options.merge!(proxy: { host: host, port: port, user: user, password: password, bypass: bypass }) end def headers @@ -422,6 +413,6 @@ def pdf?(path, options) options[:format].to_s == "pdf" end end - # rubocop:enable Metrics/ClassLength end end +# rubocop:enable Metrics/ClassLength diff --git a/lib/capybara/cuprite/page.rb b/lib/capybara/cuprite/page.rb index 106c74f5..3a4ce094 100644 --- a/lib/capybara/cuprite/page.rb +++ b/lib/capybara/cuprite/page.rb @@ -17,6 +17,7 @@ def initialize(*args) @frame_stack = [] @accept_modal = [] @modal_messages = [] + @modal_response = nil super end @@ -130,35 +131,13 @@ def title private - # rubocop:disable Metrics/CyclomaticComplexity - # rubocop:disable Metrics/PerceivedComplexity - # rubocop:disable Style/GuardClause def prepare_page super - network.intercept if !Array(@browser.url_whitelist).empty? || - !Array(@browser.url_blacklist).empty? - - on(:request) do |request, index, total| - if @browser.url_blacklist && !@browser.url_blacklist.empty? - if @browser.url_blacklist.any? { |r| request.match?(r) } - request.abort and next - else - request.continue and next - end - elsif @browser.url_whitelist && !@browser.url_whitelist.empty? - if @browser.url_whitelist.any? { |r| request.match?(r) } - request.continue and next - else - request.abort and next - end - elsif index + 1 < total - # There are other callbacks that may handle this request - next - else - # If there are no callbacks then just continue - request.continue - end + if @browser.url_blacklist.any? + network.blacklist = @browser.url_blacklist + elsif @browser.url_whitelist.any? + network.whitelist = @browser.url_whitelist end on("Page.javascriptDialogOpening") do |params| @@ -181,9 +160,6 @@ def prepare_page command("Page.handleJavaScriptDialog", **options) end end - # rubocop:enable Metrics/CyclomaticComplexity - # rubocop:enable Metrics/PerceivedComplexity - # rubocop:enable Style/GuardClause def find_position(node, **options) node.find_position(**options) diff --git a/spec/features/driver_spec.rb b/spec/features/driver_spec.rb index 30646ba8..5387f011 100644 --- a/spec/features/driver_spec.rb +++ b/spec/features/driver_spec.rb @@ -177,11 +177,11 @@ def session_url(path) File.open(file, "rb") do |f| size = @driver.evaluate_script <<-JS - function() { - var ele = document.getElementById("penultimate"); - var rect = ele.getBoundingClientRect(); - return [rect.width, rect.height]; - }(); + function() { + var ele = document.getElementById("penultimate"); + var rect = ele.getBoundingClientRect(); + return [rect.width, rect.height]; + }(); JS expect(ImageSize.new(f.read).size).to eq(size) end @@ -377,13 +377,13 @@ def create_screenshot(file, *args) @driver.headers = { "X-Omg" => "wat" } @session.visit "/" @driver.execute_script <<-JS - var request = new XMLHttpRequest(); - request.open("GET", "/cuprite/headers", false); - request.send(); + var request = new XMLHttpRequest(); + request.open("GET", "/cuprite/headers", false); + request.send(); - if (request.status === 200) { - document.body.innerHTML = request.responseText; - } + if (request.status === 200) { + document.body.innerHTML = request.responseText; + } JS expect(@driver.body).to include("X_OMG: wat") end @@ -511,9 +511,9 @@ def create_screenshot(file, *args) it "supports executing multiple lines of javascript" do @driver.execute_script <<-JS - var a = 1 - var b = 2 - window.result = a + b + var a = 1 + var b = 2 + window.result = a + b JS expect(@driver.evaluate_script("window.result")).to eq(3) end @@ -694,7 +694,7 @@ def create_screenshot(file, *args) end it "keeps track of blocked network traffic" do - @driver.browser.url_blacklist = ["unwanted"] + @driver.browser.url_blacklist = /unwanted/ @session.visit "/cuprite/url_blacklist" @@ -746,7 +746,7 @@ def create_screenshot(file, *args) end it "blocked requests get cleared along with network traffic" do - @driver.browser.url_blacklist = ["unwanted"] + @driver.browser.url_blacklist = /unwanted/ @session.visit "/cuprite/url_blacklist" @@ -772,24 +772,25 @@ def create_screenshot(file, *args) end end - it "can clear memory cache", skip: "Fixed in ferrum master" do + it "can clear memory cache" do @driver.clear_memory_cache @session.visit("/cuprite/cacheable") - first_request = @driver.network_traffic.last expect(@driver.network_traffic.length).to eq(1) - expect(first_request.response.status).to eq(200) + expect(@driver.network_traffic.last.response.status).to eq(200) + expect(@driver.network_traffic.last.response.params.dig("response", "fromDiskCache")).to be_falsey - @session.refresh + @session.click_link "click me" expect(@driver.network_traffic.length).to eq(2) - expect(@driver.network_traffic.last.response.status).to eq(304) + expect(@driver.network_traffic.last.response.status).to eq(200) + expect(@driver.network_traffic.last.response.params.dig("response", "fromDiskCache")).to be_truthy @driver.clear_memory_cache - @session.refresh - another_request = @driver.network_traffic.last + @session.click_link "click me" expect(@driver.network_traffic.length).to eq(3) - expect(another_request.response.status).to eq(200) + expect(@driver.network_traffic.last.response.status).to eq(200) + expect(@driver.network_traffic.last.response.params.dig("response", "fromDiskCache")).to be_falsey end context "status code support" do @@ -942,7 +943,7 @@ def create_screenshot(file, *args) @session.visit "/" @session.execute_script <<-JS - window.open("/cuprite/simple", "popup") + window.open("/cuprite/simple", "popup") JS sleep 0.1 @@ -951,7 +952,7 @@ def create_screenshot(file, *args) popup2 = @session.window_opened_by do @session.execute_script <<-JS - window.open("/cuprite/simple", "popup2") + window.open("/cuprite/simple", "popup2") JS end @@ -985,7 +986,7 @@ def create_screenshot(file, *args) end it "inherits url_blacklist" do - @driver.browser.url_blacklist = ["unwanted"] + @driver.browser.url_blacklist = /unwanted/ @session.visit "/" new_tab = @session.open_new_window @session.within_window(new_tab) do @@ -999,7 +1000,7 @@ def create_screenshot(file, *args) it "inherits url_whitelist" do @session.visit "/" - @driver.browser.url_whitelist = ["url_whitelist", "/cuprite/wanted"] + @driver.browser.url_whitelist = [/url_whitelist/, %r{/cuprite/wanted}] new_tab = @session.open_new_window @session.within_window(new_tab) do @session.visit "/cuprite/url_whitelist" @@ -1021,13 +1022,13 @@ def create_screenshot(file, *args) popup1 = @session.window_opened_by do @session.execute_script <<-JS - window.open("/cuprite/simple", "popup1") + window.open("/cuprite/simple", "popup1") JS end popup2 = @session.window_opened_by do @session.execute_script <<-JS - window.open("/cuprite/simple", "popup2") + window.open("/cuprite/simple", "popup2") JS end @@ -1041,10 +1042,10 @@ def create_screenshot(file, *args) it "clears local storage between tests" do @session.visit "/" @session.execute_script <<-JS - localStorage.setItem("key", "value"); + localStorage.setItem("key", "value"); JS value = @session.evaluate_script <<-JS - localStorage.getItem("key"); + localStorage.getItem("key"); JS expect(value).to eq("value") @@ -1053,7 +1054,7 @@ def create_screenshot(file, *args) @session.visit "/" value = @session.evaluate_script <<-JS - localStorage.getItem("key"); + localStorage.getItem("key"); JS expect(value).to be_nil end @@ -1107,7 +1108,7 @@ def create_screenshot(file, *args) context "blacklisting urls for resource requests" do it "blocks unwanted urls" do - @driver.browser.url_blacklist = ["unwanted"] + @driver.browser.url_blacklist = /unwanted/ @session.visit "/cuprite/url_blacklist" @@ -1119,7 +1120,7 @@ def create_screenshot(file, *args) end it "supports wildcards" do - @driver.browser.url_blacklist = ["*wanted"] + @driver.browser.url_blacklist = /.*wanted/ @session.visit "/cuprite/url_whitelist" @@ -1135,7 +1136,7 @@ def create_screenshot(file, *args) it "can be configured in the driver and survive reset" do Capybara.register_driver :cuprite_blacklist do |app| - Capybara::Cuprite::Driver.new(app, @driver.options.merge(url_blacklist: ["unwanted"])) + Capybara::Cuprite::Driver.new(app, @driver.options.merge(url_blacklist: /unwanted/)) end session = Capybara::Session.new(:cuprite_blacklist, @session.app) @@ -1158,7 +1159,7 @@ def create_screenshot(file, *args) context "whitelisting urls for resource requests" do it "allows whitelisted urls" do - @driver.browser.url_whitelist = ["url_whitelist", "/wanted"] + @driver.browser.url_whitelist = [/url_whitelist/, %r{/wanted}] @session.visit "/cuprite/url_whitelist" @@ -1173,7 +1174,7 @@ def create_screenshot(file, *args) end it "supports wildcards" do - @driver.browser.url_whitelist = ["url_whitelist", "/*wanted"] + @driver.browser.url_whitelist = [/url_whitelist/, %r{/.*wanted}] @session.visit "/cuprite/url_whitelist" @@ -1188,13 +1189,9 @@ def create_screenshot(file, *args) end it "blocks overruled urls" do - @driver.browser.url_whitelist = ["url_whitelist"] - @driver.browser.url_blacklist = ["url_whitelist"] - - @session.visit "/cuprite/url_whitelist" - - expect(@session.status_code).to eq(nil) - expect(@session).not_to have_content("We are loading some wanted action here") + @driver.browser.url_whitelist = /url_whitelist/ + expect { @driver.browser.url_blacklist = /url_whitelist/ } + .to raise_error(ArgumentError, "You can't use blacklist along with whitelist") end it "allows urls when the whitelist is empty" do @@ -1212,7 +1209,7 @@ def create_screenshot(file, *args) it "can be configured in the driver and survive reset" do Capybara.register_driver :cuprite_whitelist do |app| Capybara::Cuprite::Driver.new(app, - @driver.options.merge(url_whitelist: ["url_whitelist", "/cuprite/wanted"])) + @driver.options.merge(url_whitelist: [/url_whitelist/, %r{/cuprite/wanted}])) end session = Capybara::Session.new(:cuprite_whitelist, @session.app) @@ -1555,6 +1552,7 @@ def create_screenshot(file, *args) end it "waits for network idle" do + @session.driver.set_proxy("123", "123") @session.visit "/cuprite/show_cookies" expect(@session).not_to have_content("test_cookie") diff --git a/spec/support/test_app.rb b/spec/support/test_app.rb index ee5ecccf..353bd0b3 100644 --- a/spec/support/test_app.rb +++ b/spec/support/test_app.rb @@ -93,7 +93,7 @@ def authorized?(login, password) get "/cuprite/cacheable" do cache_control :public, max_age: 60 etag "deadbeef" - "Cacheable request" + "Cacheable request click me" end get "/cuprite/:view" do |view|