From 23764ef1d67cb019656eea123cdd31a04cbaf8e6 Mon Sep 17 00:00:00 2001 From: Dmitry Vorotilin Date: Wed, 14 Oct 2026 05:08:37 +0300 Subject: [PATCH] fix(browser): list only page targets as window handles Ferrum 0.18 tracks worker, shared_worker and service_worker targets alongside pages, so window_handles reported a page's web workers as windows and window_opened_by raised "opened 2 windows instead of 1". switch_to_window and close_window now also reject non-page targets. Fixes #326 --- CHANGELOG.md | 2 ++ lib/capybara/cuprite/browser.rb | 17 ++++++++++------- spec/features/driver_spec.rb | 11 +++++++++++ spec/support/views/with_worker.erb | 14 ++++++++++++++ 4 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 spec/support/views/with_worker.erb diff --git a/CHANGELOG.md b/CHANGELOG.md index bdd2e15..5216a8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ `Session with given id not found` or `Browser is dead or given window is closed` instead of starting on a fresh page [#274], [rubycdp/ferrum#641] - `Node#visible?` reported an open popover or modal dialog as hidden when an ancestor had `opacity: 0` [#328] +- `Driver#window_handles` listed the web workers a page spawned as windows, so `window_opened_by` raised + `opened 2 windows instead of 1` [#326] ### Removed diff --git a/lib/capybara/cuprite/browser.rb b/lib/capybara/cuprite/browser.rb index d127b0c..e3cfe46 100644 --- a/lib/capybara/cuprite/browser.rb +++ b/lib/capybara/cuprite/browser.rb @@ -110,7 +110,7 @@ def window_handle end def window_handles - targets.keys + targets.values.select(&:page?).map(&:id) end def within_window(locator = nil) @@ -124,17 +124,13 @@ def within_window(locator = nil) end def switch_to_window(target_id) - target = targets[target_id] - raise Ferrum::NoSuchPageError unless target - + target = window_target(target_id) @page = attach_page(target.id) @page.activate end def close_window(target_id) - target = targets[target_id] - raise Ferrum::NoSuchPageError unless target - + target = window_target(target_id) @page = ClosedPage.new if @page.target_id == target.id target.page.close targets.delete(target_id) # page.close is async, delete target asap @@ -298,6 +294,13 @@ def prepare_wildcards(patterns) end end + def window_target(target_id) + target = targets[target_id] + raise Ferrum::NoSuchPageError unless target&.page? + + target + end + def attach_page(target_id = nil) target = targets[target_id] if target_id target ||= default_context.default_target diff --git a/spec/features/driver_spec.rb b/spec/features/driver_spec.rb index aad2929..8666ccf 100644 --- a/spec/features/driver_spec.rb +++ b/spec/features/driver_spec.rb @@ -989,6 +989,17 @@ def create_screenshot(file, *args) expect(@driver.window_handles.size).to eq(2) end + it "doesn't list web workers as windows" do + @session.visit "/cuprite/with_worker" + + expect(@driver.window_handles.size).to eq(1) + + new_window = @session.window_opened_by { @session.click_link "Open tab" } + + expect(@driver.window_handles).to contain_exactly(@session.current_window.handle, new_window.handle) + @session.within_window(new_window) { expect(@session).to have_link("Open tab") } + end + context "a new window inherits settings" do it "inherits size" do @session.visit "/" diff --git a/spec/support/views/with_worker.erb b/spec/support/views/with_worker.erb new file mode 100644 index 0000000..1efb02f --- /dev/null +++ b/spec/support/views/with_worker.erb @@ -0,0 +1,14 @@ + + + + Worker + + + + Open tab + + +