diff --git a/.github/gemfiles/websocket-driver-0.6.x.gemfile b/.github/gemfiles/websocket-driver-0.6.x.gemfile deleted file mode 100644 index 5ddc6303..00000000 --- a/.github/gemfiles/websocket-driver-0.6.x.gemfile +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -source "https://rubygems.org" - -gem "websocket-driver", ">= 0.6", "< 0.7" -gem "capybara", "~> 3.0" -gem "matrix" - -eval_gemfile "../../Gemfile" - -gemspec path: "../../" diff --git a/.github/gemfiles/websocket-driver-0.7.x.gemfile b/.github/gemfiles/websocket-driver-0.7.x.gemfile deleted file mode 100644 index 0da8211d..00000000 --- a/.github/gemfiles/websocket-driver-0.7.x.gemfile +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -source "https://rubygems.org" - -gem "websocket-driver", ">= 0.7", "< 0.8" -gem "capybara", "~> 3.0" -gem "matrix" - -eval_gemfile "../../Gemfile" - -gemspec path: "../../" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d97467ea..d3141659 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,13 +11,11 @@ jobs: strategy: fail-fast: false matrix: - gemfile: [websocket-driver-0.6.x, websocket-driver-0.7.x] ruby: [2.7, "3.0", 3.1, 3.2, 3.3] runs-on: ubuntu-latest env: FERRUM_PROCESS_TIMEOUT: 25 FERRUM_DEFAULT_TIMEOUT: 15 - BUNDLE_GEMFILE: .github/gemfiles/${{ matrix.gemfile }}.gemfile steps: - name: Checkout code uses: actions/checkout@v4 @@ -42,5 +40,5 @@ jobs: uses: actions/upload-artifact@v4 if: ${{ failure() }} with: - name: footprints + name: artifacts-ruby-v${{ matrix.ruby }} path: /tmp/cuprite/ diff --git a/.rspec b/.rspec index 221fc808..311a4e79 100644 --- a/.rspec +++ b/.rspec @@ -1,3 +1,3 @@ --color ---format=doc +--format=progress --require spec_helper diff --git a/CHANGELOG.md b/CHANGELOG.md index 972a6029..a9b50e89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,17 @@ ### Added ### Changed -- `@window_size` attribute is moved from Ferrum viewport size is still inherited [#253] +- `@window_size` attribute is moved from Ferrum, viewport size is still inherited [#253] +- Compatibility with latest Ferrum. Browser instance is not passed everywhere now [#254] + - `Cuprite::Browser` methods are located in `Options`. + - `#window_size` + - `#url_blacklist` + - `#url_whitelist` + - `#timeout` + - `Page#new` arguments are changed to `client, context_id:, target_id:` + - `Target#attached?` renamed to `Target#connected?` + - Ferrum doesn't restart browser automatically, Cuprite does + - `Browser#close_window` removes target id asap from the target list ### Fixed - Detect whether element is in the viewport and clickable before click [#251] diff --git a/Gemfile b/Gemfile index 0a6a692f..b936ae2f 100644 --- a/Gemfile +++ b/Gemfile @@ -6,12 +6,12 @@ gem "byebug", "~> 11.1", platforms: %i[mri mingw x64_mingw] gem "chunky_png", "~> 1.4" gem "image_size", "~> 3.0" gem "launchy", "~> 2.5" -gem "pdf-reader", "~> 2.5" +gem "pdf-reader", "~> 2.12" gem "puma", ">= 5.6.7" gem "rake", "~> 13.0" gem "rspec", "~> 3.10" gem "rubocop", "~> 1.22" gem "rubocop-rake", require: false -gem "sinatra", "~> 2.1" +gem "sinatra", "~> 3.2" gemspec diff --git a/cuprite.gemspec b/cuprite.gemspec index 5aaf6171..235d0b69 100644 --- a/cuprite.gemspec +++ b/cuprite.gemspec @@ -25,5 +25,5 @@ Gem::Specification.new do |s| s.required_ruby_version = ">= 2.7.0" s.add_runtime_dependency "capybara", "~> 3.0" - s.add_runtime_dependency "ferrum", "~> 0.14.0" + s.add_runtime_dependency "ferrum", "~> 0.15.0" end diff --git a/lib/capybara/cuprite.rb b/lib/capybara/cuprite.rb index 15469f5b..aa1f23dc 100644 --- a/lib/capybara/cuprite.rb +++ b/lib/capybara/cuprite.rb @@ -5,6 +5,7 @@ require "capybara/cuprite/driver" require "capybara/cuprite/browser" require "capybara/cuprite/page" +require "capybara/cuprite/options" require "capybara/cuprite/node" require "capybara/cuprite/errors" diff --git a/lib/capybara/cuprite/browser.rb b/lib/capybara/cuprite/browser.rb index d817a204..1b6da63e 100644 --- a/lib/capybara/cuprite/browser.rb +++ b/lib/capybara/cuprite/browser.rb @@ -11,24 +11,20 @@ class Browser < Ferrum::Browser find_modal accept_confirm dismiss_confirm accept_prompt dismiss_prompt reset_modals] => :page - attr_reader :url_blacklist, :url_whitelist, :window_size - alias url_blocklist url_blacklist - alias url_allowlist url_whitelist - def initialize(options = nil) - options ||= {} - @client = nil - self.url_blacklist = options[:url_blacklist] - self.url_whitelist = options[:url_whitelist] - super - @window_size = @options.window_size + + @options.url_blacklist = prepare_wildcards(options&.dig(:url_blacklist)) + @options.url_whitelist = prepare_wildcards(options&.dig(:url_whitelist)) + @page = false end - def timeout=(value) + def command(...) super - @page.timeout = value unless @page.nil? + rescue Ferrum::DeadBrowserError + restart + raise end def page @@ -39,7 +35,7 @@ def page def reset super - @window_size = options.window_size + @options.reset_window_size @page = attach_page end @@ -49,19 +45,29 @@ def quit end def resize(**options) - @window_size = [options[:width], options[:height]] + @options.window_size = [options[:width], options[:height]] super end + def url_whitelist + @options.url_whitelist + end + alias url_allowlist url_whitelist + def url_whitelist=(patterns) - @url_whitelist = prepare_wildcards(patterns) - page.network.whitelist = @url_whitelist if @client && @url_whitelist.any? + @options.url_whitelist = prepare_wildcards(patterns) + page.network.whitelist = @options.url_whitelist if @client && @options.url_whitelist.any? end alias url_allowlist= url_whitelist= + def url_blacklist + @options.url_blacklist + end + alias url_blocklist url_blacklist + def url_blacklist=(patterns) - @url_blacklist = prepare_wildcards(patterns) - page.network.blacklist = @url_blacklist if @client && @url_blacklist.any? + @options.url_blacklist = prepare_wildcards(patterns) + page.network.blacklist = @options.url_blacklist if @client && @options.url_blacklist.any? end alias url_blocklist= url_blacklist= @@ -118,6 +124,7 @@ def close_window(target_id) @page = nil if @page.target_id == target.id target.page.close + targets.delete(target_id) # page.close is async, delete target asap end def browser_error @@ -231,10 +238,10 @@ def prepare_wildcards(patterns) def attach_page(target_id = nil) target = targets[target_id] if target_id target ||= default_context.default_target - return target.page if target.attached? + return target.page if target.connected? target.maybe_sleep_if_new_window - target.page = Page.new(target.id, self) + target.page = Page.new(target.client, context_id: target.context_id, target_id: target.id) target.page end end diff --git a/lib/capybara/cuprite/driver.rb b/lib/capybara/cuprite/driver.rb index be253547..eff76899 100644 --- a/lib/capybara/cuprite/driver.rb +++ b/lib/capybara/cuprite/driver.rb @@ -115,7 +115,7 @@ def switch_to_frame(locator) def open_new_window target = browser.default_context.create_target target.maybe_sleep_if_new_window - target.page = Page.new(target.id, browser) + target.page = Page.new(target.client, context_id: target.context_id, target_id: target.id) target.page end diff --git a/lib/capybara/cuprite/options.rb b/lib/capybara/cuprite/options.rb new file mode 100644 index 00000000..1f863dee --- /dev/null +++ b/lib/capybara/cuprite/options.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Ferrum + class Browser + class Options + attr_writer :window_size + attr_accessor :url_blacklist, :url_whitelist + + def reset_window_size + @window_size = @options[:window_size] + end + end + end +end diff --git a/lib/capybara/cuprite/page.rb b/lib/capybara/cuprite/page.rb index 8f2977ee..7d5b1f71 100644 --- a/lib/capybara/cuprite/page.rb +++ b/lib/capybara/cuprite/page.rb @@ -13,7 +13,7 @@ class Page < Ferrum::Page current_url current_title body execution_id execution_id! evaluate evaluate_on evaluate_async execute] => :active_frame - def initialize(*args) + def initialize(...) @frame_stack = [] @accept_modal = [] @modal_messages = [] @@ -70,17 +70,17 @@ def dismiss_prompt def find_modal(options) start = Ferrum::Utils::ElapsedTime.monotonic_time - timeout = options.fetch(:wait, browser.timeout) expect_text = options[:text] expect_regexp = expect_text.is_a?(Regexp) ? expect_text : Regexp.escape(expect_text.to_s) not_found_msg = "Unable to find modal dialog" not_found_msg += " with #{expect_text}" if expect_text + wait = options.fetch(:wait, timeout) begin modal_text = @modal_messages.shift raise Capybara::ModalNotFound if modal_text.nil? || (expect_text && !modal_text.match(expect_regexp)) rescue Capybara::ModalNotFound => e - raise e, not_found_msg if Ferrum::Utils::ElapsedTime.timeout?(start, timeout) + raise e, not_found_msg if Ferrum::Utils::ElapsedTime.timeout?(start, wait) sleep(MODAL_WAIT) retry @@ -134,13 +134,13 @@ def title def prepare_page super - width, height = @browser.window_size + width, height = @options.window_size resize(width: width, height: height) - if @browser.url_blacklist.any? - network.blacklist = @browser.url_blacklist - elsif @browser.url_whitelist.any? - network.whitelist = @browser.url_whitelist + if @options.url_blacklist.any? + network.blacklist = @options.url_blacklist + elsif @options.url_whitelist.any? + network.whitelist = @options.url_whitelist end on("Page.javascriptDialogOpening") do |params| diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 91e4577f..c8f8246f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -84,6 +84,7 @@ module TestSessions #has_css? with spatial requirements accepts spatial options #has_css? with spatial requirements supports spatial sugar #fill_in should fill in a textarea in a reasonable time by default + #has_element? should be true if the given element is on the page REGEXP metadata[:skip] = true if metadata[:full_description].match(/#{regexes}/)