From c1c2e424fe213f5eecda6aacf9c026f23ad80f8b Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Fri, 1 Mar 2024 02:32:39 -0500 Subject: [PATCH] Support `Node#active_element` and `:focused` filter (#261) As of [teamcapybara/capybara#2489][] (April 14, 2021), Capybara supports calling `#send_keys` on the page (instead of a particular element). Similarly, there is a global `:focused` filter that compares the node to the [Document.activeElement][]. These are both powered by a [Driver#active_element][] method in drivers that support JavaScript. This commit integrates `Capybara::Cuprite::Driver` to support both. [teamcapybara/capybara#2489]: https://github.com/teamcapybara/capybara/pull/2489 [Driver#active_element]: https://github.com/teamcapybara/capybara/blob/c0cbf4024c1abd48b0c22c2930e7b05af58ab284/lib/capybara/driver/base.rb#L62-L68 [Document.activeElement]: https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement --- CHANGELOG.md | 2 ++ lib/capybara/cuprite/browser.rb | 4 ++++ lib/capybara/cuprite/driver.rb | 5 +++++ spec/features/driver_spec.rb | 24 ++++++++++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b50e8..8b29d62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Added +- Support for `Driver#send_keys`, the `:focused` filter, and `Driver#active_element` [#261] + ### Changed - `@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] diff --git a/lib/capybara/cuprite/browser.rb b/lib/capybara/cuprite/browser.rb index a893b07..3d5045b 100644 --- a/lib/capybara/cuprite/browser.rb +++ b/lib/capybara/cuprite/browser.rb @@ -127,6 +127,10 @@ def close_window(target_id) targets.delete(target_id) # page.close is async, delete target asap end + def active_element + evaluate("document.activeElement") + end + def browser_error evaluate("_cuprite.browserError()") end diff --git a/lib/capybara/cuprite/driver.rb b/lib/capybara/cuprite/driver.rb index eff7689..2dfa59f 100644 --- a/lib/capybara/cuprite/driver.rb +++ b/lib/capybara/cuprite/driver.rb @@ -15,6 +15,7 @@ class Driver < Capybara::Driver::Base delegate %i[restart quit status_code timeout timeout= current_url title body window_handles close_window switch_to_window within_window window_handle back forward refresh wait_for_reload viewport_size device_pixel_ratio] => :browser + delegate %i[send_keys] => :active_element alias html body alias current_window_handle window_handle alias go_back back @@ -70,6 +71,10 @@ def frame_title evaluate_script("document.title") end + def active_element + Node.new(self, browser.active_element) + end + def find_xpath(selector) find(:xpath, selector) end diff --git a/spec/features/driver_spec.rb b/spec/features/driver_spec.rb index dce0c42..a4c6685 100644 --- a/spec/features/driver_spec.rb +++ b/spec/features/driver_spec.rb @@ -1303,6 +1303,30 @@ def create_screenshot(file, *args) expect(input.text).to eq("hello") end + it "supports the :focused filter" do + @session.find_field("empty_input").execute_script("this.focus()") + + expect(@session).to have_field("empty_input", focused: true) + end + + it "accessed the document.activeElement" do + input = @session.find_field("empty_input") + input.execute_script("this.focus()") + + expect(@session.active_element).to eq(input) + end + + it "sends keys to the active_element" do + @session.find_field("empty_input").execute_script("this.focus()") + + expect(@session).to have_field("empty_input", focused: true) + + @session.send_keys(:tab) + + expect(@session).to have_field("empty_input", focused: false) + .and(have_field("filled_input", focused: true)) + end + it "sends keys to filled contenteditable div" do input = @session.find(:css, "#filled_div")