mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
Merge pull request #1722 from jnicklas/frame_api
new frame api for drivers
This commit is contained in:
commit
d690c8815e
5 changed files with 67 additions and 32 deletions
|
@ -11,6 +11,7 @@ Release date: Unreleased
|
||||||
* Raise error if Capybara.app_host/default_host are specified incorrectly [Thomas Walpole]
|
* Raise error if Capybara.app_host/default_host are specified incorrectly [Thomas Walpole]
|
||||||
* Capybara::Selector::FilterSet allows for sharing filter definitions between selectors [Thomas Walpole]
|
* Capybara::Selector::FilterSet allows for sharing filter definitions between selectors [Thomas Walpole]
|
||||||
* Remove need to pass nil locator in most node actions when locator is not needed [Thomas Walpole]
|
* Remove need to pass nil locator in most node actions when locator is not needed [Thomas Walpole]
|
||||||
|
* New frames API for drivers - Issue #1365 [Thomas Walpole]
|
||||||
|
|
||||||
#Version 2.7.1
|
#Version 2.7.1
|
||||||
Release date: 2016-05-01
|
Release date: 2016-05-01
|
||||||
|
|
|
@ -48,8 +48,12 @@ class Capybara::Driver::Base
|
||||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#status_code'
|
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#status_code'
|
||||||
end
|
end
|
||||||
|
|
||||||
def within_frame(frame_handle)
|
##
|
||||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#within_frame'
|
#
|
||||||
|
# @param frame [Capybara::Node::Element, :parent, :top] The iframe element to switch to
|
||||||
|
#
|
||||||
|
def switch_to_frame(frame)
|
||||||
|
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#switch_to_frame'
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_window_handle
|
def current_window_handle
|
||||||
|
|
|
@ -131,29 +131,22 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
def switch_to_frame(frame)
|
||||||
#
|
case frame
|
||||||
# Webdriver supports frame name, id, index(zero-based) or {Capybara::Node::Element} to find iframe
|
when :top
|
||||||
#
|
@frame_handles[browser.window_handle] = []
|
||||||
# @overload within_frame(index)
|
browser.switch_to.default_content
|
||||||
# @param [Integer] index index of a frame
|
when :parent
|
||||||
# @overload within_frame(name_or_id)
|
# would love to use browser.switch_to.parent_frame here
|
||||||
# @param [String] name_or_id name or id of a frame
|
# but it has an issue if the current frame is removed from within it
|
||||||
# @overload within_frame(element)
|
@frame_handles[browser.window_handle].pop
|
||||||
# @param [Capybara::Node::Base] a_node frame element
|
browser.switch_to.default_content
|
||||||
#
|
@frame_handles[browser.window_handle].each { |fh| browser.switch_to.frame(fh) }
|
||||||
def within_frame(frame_handle)
|
else
|
||||||
frame_handle = frame_handle.native if frame_handle.is_a?(Capybara::Node::Base)
|
@frame_handles[browser.window_handle] ||= []
|
||||||
@frame_handles[browser.window_handle] ||= []
|
@frame_handles[browser.window_handle] << frame.native
|
||||||
@frame_handles[browser.window_handle] << frame_handle
|
browser.switch_to.frame(frame.native)
|
||||||
browser.switch_to.frame(frame_handle)
|
end
|
||||||
yield
|
|
||||||
ensure
|
|
||||||
# would love to use browser.switch_to.parent_frame here
|
|
||||||
# but it has an issue if the current frame is removed from within it
|
|
||||||
@frame_handles[browser.window_handle].pop
|
|
||||||
browser.switch_to.default_content
|
|
||||||
@frame_handles[browser.window_handle].each { |fh| browser.switch_to.frame(fh) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_window_handle
|
def current_window_handle
|
||||||
|
|
|
@ -327,18 +327,48 @@ module Capybara
|
||||||
|
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
# Execute the given block within the given iframe using given frame name or index.
|
# Execute the given block within the given iframe using given frame, frame name/id or index.
|
||||||
# May be supported by not all drivers. Drivers that support it, may provide additional options.
|
# May not be supported by all drivers.
|
||||||
#
|
#
|
||||||
|
# @overload within_frame(element)
|
||||||
|
# @param [Capybara::Node::Element] frame element
|
||||||
|
# @overload within_frame(name)
|
||||||
|
# @param [String] name name/id of a frame
|
||||||
# @overload within_frame(index)
|
# @overload within_frame(index)
|
||||||
# @param [Integer] index index of a frame
|
# @param [Integer] index index of a frame
|
||||||
# @overload within_frame(name)
|
|
||||||
# @param [String] name name of a frame
|
|
||||||
#
|
#
|
||||||
def within_frame(frame_handle)
|
def within_frame(locator)
|
||||||
scopes.push(nil)
|
scopes.push(nil)
|
||||||
driver.within_frame(frame_handle) do
|
|
||||||
yield
|
#support older driver frame api for now
|
||||||
|
frame = case locator
|
||||||
|
when Capybara::Node::Element
|
||||||
|
locator
|
||||||
|
when String
|
||||||
|
find(:xpath, XPath.descendant(:iframe)[XPath.attr(:id).equals(locator) | XPath.attr(:name).equals(locator)].to_xpath(:exact))
|
||||||
|
when Integer
|
||||||
|
all(:css, 'iframe', minimum: locator+1)[locator]
|
||||||
|
else
|
||||||
|
raise ArgumentError
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
driver.switch_to_frame(frame)
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
driver.switch_to_frame(:parent)
|
||||||
|
end
|
||||||
|
rescue Capybara::NotSupportedByDriverError
|
||||||
|
# Support older driver frame API for now
|
||||||
|
if driver.respond_to?(:within_frame)
|
||||||
|
warn "Your driver (#{driver.class.name}) is using an older version of Capybara's frame API - please update your driver"
|
||||||
|
driver.within_frame(frame) do
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
else
|
||||||
|
raise
|
||||||
|
end
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
scopes.pop
|
scopes.pop
|
||||||
|
|
|
@ -9,32 +9,38 @@ Capybara::SpecHelper.spec '#within_frame', :requires => [:frames] do
|
||||||
expect(@session.find("//*[@id='divInFrameOne']").text).to eql 'This is the text of divInFrameOne'
|
expect(@session.find("//*[@id='divInFrameOne']").text).to eql 'This is the text of divInFrameOne'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should find the div in FrameTwo" do
|
it "should find the div in FrameTwo" do
|
||||||
@session.within_frame("frameTwo") do
|
@session.within_frame("frameTwo") do
|
||||||
expect(@session.find("//*[@id='divInFrameTwo']").text).to eql 'This is the text of divInFrameTwo'
|
expect(@session.find("//*[@id='divInFrameTwo']").text).to eql 'This is the text of divInFrameTwo'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should find the text div in the main window after finding text in frameOne" do
|
it "should find the text div in the main window after finding text in frameOne" do
|
||||||
@session.within_frame("frameOne") do
|
@session.within_frame("frameOne") do
|
||||||
expect(@session.find("//*[@id='divInFrameOne']").text).to eql 'This is the text of divInFrameOne'
|
expect(@session.find("//*[@id='divInFrameOne']").text).to eql 'This is the text of divInFrameOne'
|
||||||
end
|
end
|
||||||
expect(@session.find("//*[@id='divInMainWindow']").text).to eql 'This is the text for divInMainWindow'
|
expect(@session.find("//*[@id='divInMainWindow']").text).to eql 'This is the text for divInMainWindow'
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should find the text div in the main window after finding text in frameTwo" do
|
it "should find the text div in the main window after finding text in frameTwo" do
|
||||||
@session.within_frame("frameTwo") do
|
@session.within_frame("frameTwo") do
|
||||||
expect(@session.find("//*[@id='divInFrameTwo']").text).to eql 'This is the text of divInFrameTwo'
|
expect(@session.find("//*[@id='divInFrameTwo']").text).to eql 'This is the text of divInFrameTwo'
|
||||||
end
|
end
|
||||||
expect(@session.find("//*[@id='divInMainWindow']").text).to eql 'This is the text for divInMainWindow'
|
expect(@session.find("//*[@id='divInMainWindow']").text).to eql 'This is the text for divInMainWindow'
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return the result of executing the block" do
|
it "should return the result of executing the block" do
|
||||||
expect(@session.within_frame("frameOne") { "return value" }).to eql "return value"
|
expect(@session.within_frame("frameOne") { "return value" }).to eql "return value"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should find the div given Element" do
|
it "should find the div given Element" do
|
||||||
element = @session.find(:id, 'frameOne')
|
element = @session.find(:id, 'frameOne')
|
||||||
@session.within_frame element do
|
@session.within_frame element do
|
||||||
expect(@session.find("//*[@id='divInFrameOne']").text).to eql 'This is the text of divInFrameOne'
|
expect(@session.find("//*[@id='divInFrameOne']").text).to eql 'This is the text of divInFrameOne'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should find multiple nested frames" do
|
it "should find multiple nested frames" do
|
||||||
@session.within_frame 'parentFrame' do
|
@session.within_frame 'parentFrame' do
|
||||||
@session.within_frame 'childFrame' do
|
@session.within_frame 'childFrame' do
|
||||||
|
@ -43,6 +49,7 @@ Capybara::SpecHelper.spec '#within_frame', :requires => [:frames] do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should reset scope when changing frames" do
|
it "should reset scope when changing frames" do
|
||||||
@session.within(:css, '#divInMainWindow') do
|
@session.within(:css, '#divInMainWindow') do
|
||||||
@session.within_frame 'parentFrame' do
|
@session.within_frame 'parentFrame' do
|
||||||
|
|
Loading…
Reference in a new issue