mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
New API for working with windows (switching/finding/closing/opening/etc.)
This commit is contained in:
parent
3c5dd37a93
commit
adda9b0acd
23 changed files with 1046 additions and 99 deletions
15
README.md
15
README.md
|
@ -467,6 +467,21 @@ within_table('Employee') do
|
|||
end
|
||||
```
|
||||
|
||||
### Working with windows
|
||||
|
||||
Capybara provides some methods to ease finding and switching windows:
|
||||
|
||||
```ruby
|
||||
facebook_window = window_opened_by do
|
||||
click_button 'Like'
|
||||
end
|
||||
within_window facebook_window do
|
||||
find('#login_email').set('a@example.com')
|
||||
find('#login_password').set('qwerty')
|
||||
click_button 'Submit'
|
||||
end
|
||||
```
|
||||
|
||||
### Scripting
|
||||
|
||||
In drivers which support it, you can easily execute JavaScript:
|
||||
|
|
|
@ -37,13 +37,13 @@ Gem::Specification.new do |s|
|
|||
s.add_development_dependency("cucumber", [">= 0.10.5"])
|
||||
s.add_development_dependency("rake")
|
||||
s.add_development_dependency("pry")
|
||||
|
||||
|
||||
if RUBY_ENGINE == 'rbx' then
|
||||
s.add_development_dependency("racc")
|
||||
s.add_development_dependency("json")
|
||||
s.add_development_dependency("rubysl")
|
||||
end
|
||||
|
||||
|
||||
if File.exist?("gem-private_key.pem")
|
||||
s.signing_key = 'gem-private_key.pem'
|
||||
end
|
||||
|
|
|
@ -13,6 +13,8 @@ module Capybara
|
|||
class UnselectNotAllowed < CapybaraError; end
|
||||
class NotSupportedByDriverError < CapybaraError; end
|
||||
class InfiniteRedirectError < CapybaraError; end
|
||||
class ScopeError < CapybaraError; end
|
||||
class WindowError < CapybaraError; end
|
||||
|
||||
class << self
|
||||
attr_accessor :asset_host, :app_host, :run_server, :default_host, :always_include_port
|
||||
|
@ -316,6 +318,7 @@ module Capybara
|
|||
require 'capybara/helpers'
|
||||
require 'capybara/session'
|
||||
require 'capybara/dsl'
|
||||
require 'capybara/window'
|
||||
require 'capybara/server'
|
||||
require 'capybara/selector'
|
||||
require 'capybara/query'
|
||||
|
|
|
@ -51,10 +51,42 @@ class Capybara::Driver::Base
|
|||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#within_frame'
|
||||
end
|
||||
|
||||
def within_window(handle)
|
||||
def current_window_handle
|
||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#current_window_handle'
|
||||
end
|
||||
|
||||
def current_window_size
|
||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#window_size'
|
||||
end
|
||||
|
||||
def resize_current_window_to(width, height)
|
||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#resize_window_to'
|
||||
end
|
||||
|
||||
def close_current_window
|
||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#close_window'
|
||||
end
|
||||
|
||||
def window_handles
|
||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#window_handles'
|
||||
end
|
||||
|
||||
def open_new_window
|
||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#open_new_window'
|
||||
end
|
||||
|
||||
def switch_to_window(handle)
|
||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#switch_to_window'
|
||||
end
|
||||
|
||||
def within_window(locator)
|
||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#within_window'
|
||||
end
|
||||
|
||||
def no_such_window_error
|
||||
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#no_such_window_error'
|
||||
end
|
||||
|
||||
def invalid_element_errors
|
||||
[]
|
||||
end
|
||||
|
|
|
@ -67,10 +67,13 @@ module Capybara
|
|||
# Capybara will raise `Capybara::FrozenInTime`.
|
||||
#
|
||||
# @param [Integer] seconds Number of seconds to retry this block
|
||||
# @param options [Hash]
|
||||
# @option options [Array<Exception>] :errors (driver.invalid_element_errors +
|
||||
# [Capybara::ElementNotFound]) exception types that cause the block to be rerun
|
||||
# @return [Object] The result of the given block
|
||||
# @raise [Capybara::FrozenInTime] If the return value of `Time.now` appears stuck
|
||||
#
|
||||
def synchronize(seconds=Capybara.default_wait_time)
|
||||
def synchronize(seconds=Capybara.default_wait_time, options = {})
|
||||
start_time = Time.now
|
||||
|
||||
if session.synchronized
|
||||
|
@ -82,7 +85,7 @@ module Capybara
|
|||
rescue => e
|
||||
session.raise_server_error!
|
||||
raise e unless driver.wait?
|
||||
raise e unless catch_error?(e)
|
||||
raise e unless catch_error?(e, options[:errors])
|
||||
raise e if (Time.now - start_time) >= seconds
|
||||
sleep(0.05)
|
||||
raise Capybara::FrozenInTime, "time appears to be frozen, Capybara does not work with libraries which freeze time, consider using time travelling instead" if Time.now == start_time
|
||||
|
@ -96,8 +99,9 @@ module Capybara
|
|||
|
||||
protected
|
||||
|
||||
def catch_error?(error)
|
||||
(driver.invalid_element_errors + [Capybara::ElementNotFound]).any? do |type|
|
||||
def catch_error?(error, errors = nil)
|
||||
errors ||= (driver.invalid_element_errors + [Capybara::ElementNotFound])
|
||||
errors.any? do |type|
|
||||
error.is_a?(type)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -109,6 +109,33 @@ module Capybara
|
|||
end
|
||||
end
|
||||
|
||||
class BecomeClosed
|
||||
def initialize(options)
|
||||
@wait_time = Capybara::Query.new(options).wait
|
||||
end
|
||||
|
||||
def matches?(window)
|
||||
@window = window
|
||||
start_time = Time.now
|
||||
while window.exists? && (Time.now - start_time) < @wait_time
|
||||
sleep 0.05
|
||||
end
|
||||
window.closed?
|
||||
end
|
||||
|
||||
def failure_message
|
||||
"expected #{@window.inspect} to become closed after #{@wait_time} seconds"
|
||||
end
|
||||
|
||||
def failure_message_when_negated
|
||||
"expected #{@window.inspect} not to become closed after #{@wait_time} seconds"
|
||||
end
|
||||
|
||||
# RSpec 2 compatibility:
|
||||
alias_method :failure_message_for_should, :failure_message
|
||||
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
||||
end
|
||||
|
||||
def have_selector(*args)
|
||||
HaveSelector.new(*args)
|
||||
end
|
||||
|
@ -157,5 +184,15 @@ module Capybara
|
|||
def have_table(locator, options={})
|
||||
HaveSelector.new(:table, locator, options)
|
||||
end
|
||||
|
||||
##
|
||||
# Wait for window to become closed.
|
||||
# @example
|
||||
# expect(window).to become_closed(wait: 0.8)
|
||||
# @param options [Hash] optional param
|
||||
# @option options [Numeric] :wait (Capybara.default_wait_time) wait time
|
||||
def become_closed(options = {})
|
||||
BecomeClosed.new(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -126,24 +126,56 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|||
@frame_handles[browser.window_handle].each { |fh| browser.switch_to.frame(fh) }
|
||||
end
|
||||
|
||||
def find_window( selector )
|
||||
def current_window_handle
|
||||
browser.window_handle
|
||||
end
|
||||
|
||||
def current_window_size
|
||||
size = browser.manage.window.size
|
||||
[size.width, size.height]
|
||||
end
|
||||
|
||||
def resize_current_window_to(width, height)
|
||||
browser.manage.window.resize_to(width, height)
|
||||
end
|
||||
|
||||
def close_current_window
|
||||
browser.close
|
||||
end
|
||||
|
||||
def window_handles
|
||||
browser.window_handles
|
||||
end
|
||||
|
||||
def open_new_window
|
||||
browser.execute_script('window.open();')
|
||||
end
|
||||
|
||||
def switch_to_window(handle)
|
||||
browser.switch_to.window handle
|
||||
end
|
||||
|
||||
# @api private
|
||||
def find_window(locator)
|
||||
handles = browser.window_handles
|
||||
return locator if handles.include? locator
|
||||
|
||||
original_handle = browser.window_handle
|
||||
browser.window_handles.each do |handle|
|
||||
handles.each do |handle|
|
||||
browser.switch_to.window handle
|
||||
if( selector == browser.execute_script("return window.name") ||
|
||||
browser.title.include?(selector) ||
|
||||
browser.current_url.include?(selector) ||
|
||||
(selector == handle) )
|
||||
if (locator == browser.execute_script("return window.name") ||
|
||||
browser.title.include?(locator) ||
|
||||
browser.current_url.include?(locator))
|
||||
browser.switch_to.window original_handle
|
||||
return handle
|
||||
end
|
||||
end
|
||||
raise Capybara::ElementNotFound, "Could not find a window identified by #{selector}"
|
||||
raise Capybara::ElementNotFound, "Could not find a window identified by #{locator}"
|
||||
end
|
||||
|
||||
def within_window(selector, &blk)
|
||||
handle = find_window( selector )
|
||||
browser.switch_to.window(handle, &blk)
|
||||
def within_window(locator)
|
||||
handle = find_window(locator)
|
||||
browser.switch_to.window(handle) { yield }
|
||||
end
|
||||
|
||||
def quit
|
||||
|
@ -158,4 +190,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|||
[Selenium::WebDriver::Error::StaleElementReferenceError, Selenium::WebDriver::Error::UnhandledError, Selenium::WebDriver::Error::ElementNotVisibleError]
|
||||
end
|
||||
|
||||
def no_such_window_error
|
||||
Selenium::WebDriver::Error::NoSuchWindowError
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,7 +40,8 @@ module Capybara
|
|||
SESSION_METHODS = [
|
||||
:body, :html, :source, :current_url, :current_host, :current_path,
|
||||
:execute_script, :evaluate_script, :visit, :go_back, :go_forward,
|
||||
:within, :within_fieldset, :within_table, :within_frame, :within_window,
|
||||
:within, :within_fieldset, :within_table, :within_frame, :current_window,
|
||||
:windows, :open_new_window, :switch_to_window, :within_window, :window_opened_by,
|
||||
:save_page, :save_and_open_page, :save_screenshot,
|
||||
:save_and_open_screenshot, :reset_session!, :response_headers,
|
||||
:status_code, :title, :has_title?, :has_no_title?, :current_scope
|
||||
|
@ -327,17 +328,162 @@ module Capybara
|
|||
end
|
||||
|
||||
##
|
||||
# @return [Capybara::Window] current window
|
||||
#
|
||||
# Execute the given block within the given window. Only works on
|
||||
# some drivers (e.g. Selenium)
|
||||
def current_window
|
||||
Window.new(self, driver.current_window_handle)
|
||||
end
|
||||
|
||||
##
|
||||
# Get all opened windows.
|
||||
# The order of windows in returned array is not defined.
|
||||
# The driver may sort windows by their creation time but it's not required.
|
||||
#
|
||||
# @param [String] handle of the window
|
||||
# @return [Array<Capybara::Window>] an array of all windows
|
||||
#
|
||||
def within_window(handle, &blk)
|
||||
scopes.push(nil)
|
||||
driver.within_window(handle, &blk)
|
||||
ensure
|
||||
scopes.pop
|
||||
def windows
|
||||
driver.window_handles.map do |handle|
|
||||
Window.new(self, handle)
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Open new window.
|
||||
# Current window doesn't change as the result of this call.
|
||||
# It should be switched to explicitly.
|
||||
#
|
||||
# @return [Capybara::Window] window that has been opened
|
||||
#
|
||||
def open_new_window
|
||||
window_opened_by do
|
||||
driver.open_new_window
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# @overload switch_to_window(&block)
|
||||
# Switches to the first window for which given block returns a value other than false or nil.
|
||||
# @example
|
||||
# window = switch_to_window { title == 'Page title' }
|
||||
# @return [Capybara::Window] window that has been switched to
|
||||
# @raise [Capybara::WindowError] if no window matches given block
|
||||
# @overload switch_to_window(window)
|
||||
# @param window [Capybara::Window] window that should be switched to
|
||||
# @raise [Capybara::Driver::Base#no_such_window_error] if unexistent (e.g. closed) window was passed
|
||||
#
|
||||
# @raise [Capybara::ScopeError] if this method is invoked inside `within`,
|
||||
# `within_frame` or `within_window` methods
|
||||
# @raise [ArgumentError] if both or neither arguments were provided
|
||||
#
|
||||
def switch_to_window(window = nil)
|
||||
block_given = block_given?
|
||||
if window && block_given
|
||||
raise ArgumentError, "`switch_to_window` can take either a block or a window, not both"
|
||||
elsif !window && !block_given
|
||||
raise ArgumentError, "`switch_to_window`: either window or block should be provided"
|
||||
elsif scopes.size > 1
|
||||
raise Capybara::ScopeError, "`switch_to_window` is not supposed to be invoked from "\
|
||||
"`within`'s, `within_frame`'s' or `within_window`'s' block."
|
||||
end
|
||||
|
||||
if window
|
||||
driver.switch_to_window(window.handle)
|
||||
else
|
||||
driver.window_handles.each do |handle|
|
||||
driver.switch_to_window handle
|
||||
if yield
|
||||
return Window.new(self, handle)
|
||||
end
|
||||
end
|
||||
raise Capybara::WindowError, "Could not find a window matching block/lambda"
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# This method does the following:
|
||||
#
|
||||
# 1. Switches to the given window (it can be located by window instance/lambda/string).
|
||||
# 2. Executes the given block (within window located at previous step).
|
||||
# 3. Switches back (this step will be invoked even if exception will happen at second step)
|
||||
#
|
||||
# @overload within_window(window) { do_something }
|
||||
# @param [Capybara::Window] instance of Capybara::Window class
|
||||
# that will be switched to
|
||||
# @overload within_window(proc_or_lambda) { do_something }
|
||||
# @param lambda [Proc] lambda. First window for which lambda
|
||||
# returns a value other than false or nil will be switched to.
|
||||
# @example
|
||||
# within_window(->{ page.title == 'Page title' }) { click_button 'Submit' }
|
||||
# @raise [Capybara::WindowError] if no window matching lambda was found
|
||||
# @overload within_window(string) { do_something }
|
||||
# @deprecated Pass window or lambda instead
|
||||
# @param [String] handle, name, url or title of the window
|
||||
#
|
||||
# @raise [Capybara::ScopeError] if this method is invoked inside `within`,
|
||||
# `within_frame` or `within_window` methods
|
||||
# @raise [driver#no_such_window_error] if unexistent (e.g. closed) window was passed
|
||||
# @return value returned by the block
|
||||
#
|
||||
def within_window(window_or_handle)
|
||||
if window_or_handle.instance_of?(Capybara::Window)
|
||||
original = current_window
|
||||
begin
|
||||
switch_to_window(window_or_handle) unless original == window_or_handle
|
||||
scopes.push(nil)
|
||||
yield
|
||||
ensure
|
||||
scopes.pop if scopes.last.nil? # It will be not nil if closed window has been passed
|
||||
switch_to_window(original) unless original == window_or_handle
|
||||
end
|
||||
elsif window_or_handle.is_a?(Proc)
|
||||
original = current_window
|
||||
begin
|
||||
switch_to_window { window_or_handle.call }
|
||||
scopes.push(nil)
|
||||
yield
|
||||
ensure
|
||||
scopes.pop if scopes.last.nil?
|
||||
switch_to_window(original)
|
||||
end
|
||||
else
|
||||
offending_line = caller.first
|
||||
file_line = offending_line.match(/^(.+?):(\d+)/)[0]
|
||||
warn "DEPRECATION WARNING: Passing string argument to #within_window is deprecated. "\
|
||||
"Pass window object or lambda. (called from #{file_line})"
|
||||
begin
|
||||
scopes.push(nil)
|
||||
driver.within_window(window_or_handle) { yield }
|
||||
ensure
|
||||
scopes.pop
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Get the window that has been opened by the passed block.
|
||||
# It will wait for it to be opened (in the same way as other Capybara methods wait).
|
||||
# It's better to use this method than `windows.last`
|
||||
# {https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html#h_note_10 as order of windows isn't defined in some drivers}
|
||||
#
|
||||
# @param options [Hash]
|
||||
# @option options [Numeric] :wait (Capybara.default_wait_time) wait time
|
||||
# @return [Capybara::Window] the window that has been opened within a block
|
||||
# @raise [Capybara::WindowError] if block passed to window hasn't opened window
|
||||
# or opened more than one window
|
||||
#
|
||||
def window_opened_by(options = {}, &block)
|
||||
old_handles = driver.window_handles
|
||||
block.call
|
||||
|
||||
wait_time = Capybara::Query.new(options).wait
|
||||
document.synchronize(wait_time, errors: [Capybara::WindowError]) do
|
||||
opened_handles = (driver.window_handles - old_handles)
|
||||
if opened_handles.size != 1
|
||||
raise Capybara::WindowError, "block passed to #window_opened_by "\
|
||||
"opened #{opened_handles.size} windows instead of 1"
|
||||
end
|
||||
Window.new(self, opened_handles.first)
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
|
|
84
lib/capybara/spec/session/window/become_closed_spec.rb
Normal file
84
lib/capybara/spec/session/window/become_closed_spec.rb
Normal file
|
@ -0,0 +1,84 @@
|
|||
Capybara::SpecHelper.spec '#become_closed', requires: [:windows] do
|
||||
before(:each) do
|
||||
@window = @session.current_window
|
||||
@session.visit('/with_windows')
|
||||
@other_window = @session.window_opened_by do
|
||||
@session.find(:css, '#openWindow').click
|
||||
end
|
||||
end
|
||||
after(:each) do
|
||||
(@session.windows - [@window]).each do |w|
|
||||
@session.switch_to_window w
|
||||
w.close
|
||||
end
|
||||
@session.switch_to_window(@window)
|
||||
end
|
||||
|
||||
context 'with :wait option' do
|
||||
it 'should wait if value of :wait is more than timeout' do
|
||||
@session.within_window @other_window do
|
||||
@session.execute_script('setTimeout(function(){ window.close(); }, 500);')
|
||||
end
|
||||
Capybara.using_wait_time 0.1 do
|
||||
expect(@other_window).to become_closed(wait: 0.7)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should raise error if value of :wait is less than timeout' do
|
||||
@session.within_window @other_window do
|
||||
@session.execute_script('setTimeout(function(){ window.close(); }, 700);')
|
||||
end
|
||||
Capybara.using_wait_time 2 do
|
||||
expect do
|
||||
expect(@other_window).to become_closed(wait: 0.4)
|
||||
end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /\Aexpected #<Window @handle=".+"> to become closed after 0.4 seconds\Z/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without :wait option' do
|
||||
it 'should wait if value of default_wait_time is more than timeout' do
|
||||
@session.within_window @other_window do
|
||||
@session.execute_script('setTimeout(function(){ window.close(); }, 500);')
|
||||
end
|
||||
Capybara.using_wait_time 0.7 do
|
||||
expect(@other_window).to become_closed
|
||||
end
|
||||
end
|
||||
|
||||
it 'should raise error if value of default_wait_time is less than timeout' do
|
||||
@session.within_window @other_window do
|
||||
@session.execute_script('setTimeout(function(){ window.close(); }, 700);')
|
||||
end
|
||||
Capybara.using_wait_time 0.4 do
|
||||
expect do
|
||||
expect(@other_window).to become_closed
|
||||
end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /\Aexpected #<Window @handle=".+"> to become closed after 0.4 seconds\Z/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with not_to' do
|
||||
it 'should raise error if default_wait_time is more than timeout' do
|
||||
@session.within_window @other_window do
|
||||
@session.execute_script('setTimeout(function(){ window.close(); }, 700);')
|
||||
end
|
||||
Capybara.using_wait_time 0.4 do
|
||||
expect do
|
||||
expect(@other_window).not_to become_closed
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'should raise error if default_wait_time is more than timeout' do
|
||||
@session.within_window @other_window do
|
||||
@session.execute_script('setTimeout(function(){ window.close(); }, 700);')
|
||||
end
|
||||
Capybara.using_wait_time 1.1 do
|
||||
expect do
|
||||
expect(@other_window).not_to become_closed
|
||||
end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /\Aexpected #<Window @handle=".+"> not to become closed after 1.1 seconds\Z/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
24
lib/capybara/spec/session/window/current_window_spec.rb
Normal file
24
lib/capybara/spec/session/window/current_window_spec.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
Capybara::SpecHelper.spec '#current_window', requires: [:windows] do
|
||||
before(:each) do
|
||||
@window = @session.current_window
|
||||
@session.visit('/with_windows')
|
||||
end
|
||||
after(:each) do
|
||||
(@session.windows - [@window]).each do |w|
|
||||
@session.switch_to_window w
|
||||
w.close
|
||||
end
|
||||
@session.switch_to_window(@window)
|
||||
end
|
||||
|
||||
it 'should return window' do
|
||||
expect(@session.current_window).to be_instance_of(Capybara::Window)
|
||||
end
|
||||
|
||||
it "should be modified by switching to another window" do
|
||||
expect do
|
||||
window = @session.window_opened_by { @session.find(:css, '#openWindow').click }
|
||||
@session.switch_to_window(window)
|
||||
end.to change { @session.current_window }
|
||||
end
|
||||
end
|
28
lib/capybara/spec/session/window/open_new_window_spec.rb
Normal file
28
lib/capybara/spec/session/window/open_new_window_spec.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
Capybara::SpecHelper.spec '#open_new_window', requires: [:windows] do
|
||||
before(:each) do
|
||||
@window = @session.current_window
|
||||
@session.visit('/with_windows')
|
||||
end
|
||||
after(:each) do
|
||||
(@session.windows - [@window]).each do |w|
|
||||
@session.switch_to_window w
|
||||
w.close
|
||||
end
|
||||
@session.switch_to_window(@window)
|
||||
end
|
||||
|
||||
it 'should open new window with blank url and title' do
|
||||
window = @session.open_new_window
|
||||
@session.switch_to_window(window)
|
||||
expect(['', 'about:blank']).to include(@session.title)
|
||||
expect(@session.current_url).to eq('about:blank')
|
||||
end
|
||||
|
||||
it 'should open window with changable content' do
|
||||
window = @session.open_new_window
|
||||
@session.within_window window do
|
||||
@session.visit '/with_html'
|
||||
expect(@session).to have_css('#first')
|
||||
end
|
||||
end
|
||||
end
|
93
lib/capybara/spec/session/window/switch_to_window_spec.rb
Normal file
93
lib/capybara/spec/session/window/switch_to_window_spec.rb
Normal file
|
@ -0,0 +1,93 @@
|
|||
Capybara::SpecHelper.spec '#switch_to_window', requires: [:windows] do
|
||||
before(:each) do
|
||||
@window = @session.current_window
|
||||
@session.visit('/with_windows')
|
||||
end
|
||||
after(:each) do
|
||||
(@session.windows - [@window]).each do |w|
|
||||
@session.switch_to_window w
|
||||
w.close
|
||||
end
|
||||
@session.switch_to_window(@window)
|
||||
end
|
||||
|
||||
it "should raise error when invoked without args" do
|
||||
expect do
|
||||
@session.switch_to_window
|
||||
end.to raise_error(ArgumentError, "`switch_to_window`: either window or block should be provided")
|
||||
end
|
||||
|
||||
it "should raise error when invoked with window and block" do
|
||||
expect do
|
||||
@session.switch_to_window(@window) { @session.title == 'Title of the first popup' }
|
||||
end.to raise_error(ArgumentError, "`switch_to_window` can take either a block or a window, not both")
|
||||
end
|
||||
|
||||
context "with an instance of Capybara::Window" do
|
||||
it "should be able to switch to window" do
|
||||
window = @session.open_new_window
|
||||
expect(@session.title).to eq('With Windows')
|
||||
@session.switch_to_window(window)
|
||||
expect(['', 'about:blank']).to include(@session.title)
|
||||
end
|
||||
end
|
||||
|
||||
context "with block" do
|
||||
before(:each) do
|
||||
@session.find(:css, '#openTwoWindows').click
|
||||
end
|
||||
|
||||
it "should be able to switch to current window" do
|
||||
@session.switch_to_window { @session.title == 'With Windows' }
|
||||
expect(@session).to have_css('#openTwoWindows')
|
||||
end
|
||||
|
||||
it "should find the div in another window" do
|
||||
@session.switch_to_window { @session.title == 'Title of popup two' }
|
||||
expect(@session).to have_css('#divInPopupTwo')
|
||||
end
|
||||
|
||||
it "should be able to switch multiple times" do
|
||||
@session.switch_to_window { @session.title == 'Title of the first popup' }
|
||||
expect(@session).to have_css('#divInPopupOne')
|
||||
@session.switch_to_window { @session.title == 'Title of popup two' }
|
||||
expect(@session).to have_css('#divInPopupTwo')
|
||||
end
|
||||
|
||||
it "should return window" do
|
||||
window = @session.switch_to_window { @session.title == 'Title of popup two' }
|
||||
expect((@session.windows - [@window])).to include(window)
|
||||
end
|
||||
|
||||
it "should raise error when invoked inside `within` as it's nonsense" do
|
||||
expect do
|
||||
@session.within(:css, '#doesNotOpenWindows') do
|
||||
@session.switch_to_window { @session.title == 'With Windows' }
|
||||
end
|
||||
end.to raise_error(Capybara::ScopeError, "`switch_to_window` is not supposed to be invoked from `within`'s, `within_frame`'s' or `within_window`'s' block.")
|
||||
end
|
||||
|
||||
it "should raise error when invoked inside `within_frame` as it's nonsense" do
|
||||
expect do
|
||||
@session.within_frame('frameOne') do
|
||||
@session.switch_to_window { @session.title == 'With Windows' }
|
||||
end
|
||||
end.to raise_error(Capybara::ScopeError, "`switch_to_window` is not supposed to be invoked from `within`'s, `within_frame`'s' or `within_window`'s' block.")
|
||||
end
|
||||
|
||||
it "should raise error when invoked inside `within_window` as it's nonsense" do
|
||||
window = (@session.windows - [@window]).first
|
||||
expect do
|
||||
@session.within_window window do
|
||||
@session.switch_to_window { @session.title == 'With Windows' }
|
||||
end
|
||||
end.to raise_error(Capybara::ScopeError, "`switch_to_window` is not supposed to be invoked from `within`'s, `within_frame`'s' or `within_window`'s' block.")
|
||||
end
|
||||
end
|
||||
|
||||
it "should raise error if window matching block wasn't found" do
|
||||
expect do
|
||||
@session.switch_to_window { @session.title == 'A title' }
|
||||
end.to raise_error(Capybara::WindowError, "Could not find a window matching block/lambda")
|
||||
end
|
||||
end
|
74
lib/capybara/spec/session/window/window_opened_by_spec.rb
Normal file
74
lib/capybara/spec/session/window/window_opened_by_spec.rb
Normal file
|
@ -0,0 +1,74 @@
|
|||
Capybara::SpecHelper.spec '#window_opened_by', requires: [:windows] do
|
||||
before(:each) do
|
||||
@window = @session.current_window
|
||||
@session.visit('/with_windows')
|
||||
end
|
||||
after(:each) do
|
||||
(@session.windows - [@window]).each do |w|
|
||||
@session.switch_to_window w
|
||||
w.close
|
||||
end
|
||||
@session.switch_to_window(@window)
|
||||
end
|
||||
|
||||
let(:zero_windows_message) { "block passed to #window_opened_by opened 0 windows instead of 1" }
|
||||
let(:two_windows_message) { "block passed to #window_opened_by opened 2 windows instead of 1" }
|
||||
|
||||
context 'with :wait option' do
|
||||
it 'should raise error if value of :wait is less than timeout' do
|
||||
Capybara.using_wait_time 1 do
|
||||
expect do
|
||||
@session.window_opened_by(wait: 0.3) do
|
||||
@session.find(:css, '#openWindowWithTimeout').click
|
||||
end
|
||||
end.to raise_error(Capybara::WindowError, zero_windows_message)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should find window if value of :wait is more than timeout' do
|
||||
Capybara.using_wait_time 0.1 do
|
||||
window = @session.window_opened_by(wait: 0.9) do
|
||||
@session.find(:css, '#openWindowWithTimeout').click
|
||||
end
|
||||
expect(window).to be_instance_of(Capybara::Window)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without :wait option' do
|
||||
it 'should raise error if default_wait_time is less than timeout' do
|
||||
Capybara.using_wait_time 0.2 do
|
||||
expect do
|
||||
@session.window_opened_by do
|
||||
@session.find(:css, '#openWindowWithTimeout').click
|
||||
end
|
||||
end.to raise_error(Capybara::WindowError, zero_windows_message)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should find window if default_wait_time is more than timeout' do
|
||||
Capybara.using_wait_time 0.9 do
|
||||
window = @session.window_opened_by do
|
||||
@session.find(:css, '#openWindowWithTimeout').click
|
||||
end
|
||||
expect(window).to be_instance_of(Capybara::Window)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'should raise error when two windows have been opened by block' do
|
||||
expect do
|
||||
@session.window_opened_by do
|
||||
@session.find(:css, '#openTwoWindows').click
|
||||
end
|
||||
end.to raise_error(Capybara::WindowError, two_windows_message)
|
||||
end
|
||||
|
||||
it 'should raise error when no windows were opened by block' do
|
||||
expect do
|
||||
@session.window_opened_by do
|
||||
@session.find(:css, '#doesNotOpenWindows').click
|
||||
end
|
||||
end.to raise_error(Capybara::WindowError, zero_windows_message)
|
||||
end
|
||||
end
|
114
lib/capybara/spec/session/window/window_spec.rb
Normal file
114
lib/capybara/spec/session/window/window_spec.rb
Normal file
|
@ -0,0 +1,114 @@
|
|||
Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
|
||||
before(:each) do
|
||||
@window = @session.current_window
|
||||
@session.visit('/with_windows')
|
||||
end
|
||||
after(:each) do
|
||||
(@session.windows - [@window]).each do |w|
|
||||
@session.switch_to_window w
|
||||
w.close
|
||||
end
|
||||
@session.switch_to_window(@window)
|
||||
end
|
||||
|
||||
describe '#exists?' do
|
||||
before(:each) do
|
||||
@other_window = @session.window_opened_by do
|
||||
@session.find(:css, '#openWindow').click
|
||||
end
|
||||
end
|
||||
|
||||
it "should become false after window was closed" do
|
||||
expect do
|
||||
@session.switch_to_window @other_window
|
||||
@other_window.close
|
||||
end.to change { @other_window.exists? }.from(true).to(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#closed?' do
|
||||
it "should become true after window was closed" do
|
||||
@other_window = @session.window_opened_by do
|
||||
@session.find(:css, '#openWindow').click
|
||||
end
|
||||
expect do
|
||||
@session.switch_to_window @other_window
|
||||
@other_window.close
|
||||
end.to change { @other_window.closed? }.from(false).to(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#current?' do
|
||||
before(:each) do
|
||||
@other_window = @session.window_opened_by do
|
||||
@session.find(:css, '#openWindow').click
|
||||
end
|
||||
end
|
||||
|
||||
it 'should become true after switching to window' do
|
||||
expect do
|
||||
@session.switch_to_window(@other_window)
|
||||
end.to change { @other_window.current? }.from(false).to(true)
|
||||
end
|
||||
|
||||
it 'should return false if window is closed' do
|
||||
@session.switch_to_window(@other_window)
|
||||
@other_window.close
|
||||
expect(@other_window.current?).to be_false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#close' do
|
||||
before(:each) do
|
||||
@other_window = @session.window_opened_by do
|
||||
@session.find(:css, '#openWindow').click
|
||||
end
|
||||
end
|
||||
|
||||
it 'should change number of windows' do
|
||||
expect do
|
||||
@session.within_window(@other_window) do
|
||||
@other_window.close
|
||||
end
|
||||
end.to change { @session.windows.size }.from(2).to(1)
|
||||
end
|
||||
|
||||
it 'should raise error if invoked not for current window' do
|
||||
expect do
|
||||
@other_window.close
|
||||
end.to raise_error(Capybara::WindowError, "Closing not current window is not possible.")
|
||||
end
|
||||
end
|
||||
|
||||
describe '#size' do
|
||||
it 'should return size of whole window' do
|
||||
expect(@session.current_window.size).to eq @session.evaluate_script("[window.outerWidth, window.outerHeight];")
|
||||
end
|
||||
|
||||
it 'should raise error if invoked not for current window' do
|
||||
@other_window = @session.window_opened_by do
|
||||
@session.find(:css, '#openWindow').click
|
||||
end
|
||||
expect do
|
||||
@other_window.size
|
||||
end.to raise_error(Capybara::WindowError, "Getting size of not current window is not possible.")
|
||||
end
|
||||
end
|
||||
|
||||
describe '#resize_to' do
|
||||
it 'should be able to resize window' do
|
||||
width, height = @session.evaluate_script("[window.outerWidth, window.outerHeight];")
|
||||
@session.current_window.resize_to(width-10, height-10)
|
||||
expect(@session.evaluate_script("[window.outerWidth, window.outerHeight];")).to eq([width-10, height-10])
|
||||
end
|
||||
|
||||
it 'should raise error if invoked not for current window' do
|
||||
@other_window = @session.window_opened_by do
|
||||
@session.find(:css, '#openWindow').click
|
||||
end
|
||||
expect do
|
||||
@other_window.resize_to(1000, 700)
|
||||
end.to raise_error(Capybara::WindowError, "Resizing not current window is not possible.")
|
||||
end
|
||||
end
|
||||
end
|
27
lib/capybara/spec/session/window/windows_spec.rb
Normal file
27
lib/capybara/spec/session/window/windows_spec.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
Capybara::SpecHelper.spec '#windows', requires: [:windows] do
|
||||
before(:each) do
|
||||
@window = @session.current_window
|
||||
@session.visit('/with_windows')
|
||||
@session.find(:css, '#openTwoWindows').click
|
||||
end
|
||||
after(:each) do
|
||||
(@session.windows - [@window]).each do |w|
|
||||
@session.switch_to_window w
|
||||
w.close
|
||||
end
|
||||
@session.switch_to_window(@window)
|
||||
end
|
||||
|
||||
it 'should return objects of Capybara::Window class' do
|
||||
expect(@session.windows.map { |window| window.instance_of?(Capybara::Window) }).to eq([true] * 3)
|
||||
end
|
||||
|
||||
it 'should switchable windows' do
|
||||
titles = @session.windows.map do |window|
|
||||
@session.within_window(window) { @session.title }
|
||||
end
|
||||
expect(titles).to match_array([
|
||||
'With Windows', 'Title of the first popup', 'Title of popup two'
|
||||
])
|
||||
end
|
||||
end
|
164
lib/capybara/spec/session/window/within_window_spec.rb
Normal file
164
lib/capybara/spec/session/window/within_window_spec.rb
Normal file
|
@ -0,0 +1,164 @@
|
|||
Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
|
||||
before(:each) do
|
||||
@window = @session.current_window
|
||||
@session.visit('/with_windows')
|
||||
@session.find(:css, '#openTwoWindows').click
|
||||
end
|
||||
after(:each) do
|
||||
(@session.windows - [@window]).each do |w|
|
||||
@session.switch_to_window w
|
||||
w.close
|
||||
end
|
||||
@session.switch_to_window(@window)
|
||||
end
|
||||
|
||||
context "with an instance of Capybara::Window" do
|
||||
it "should not invoke driver#switch_to_window when given current window" do
|
||||
# switch_to_window is invoked in after hook
|
||||
expect(@session.driver).to receive(:switch_to_window).exactly(3).times.and_call_original
|
||||
@session.within_window @window do
|
||||
expect(@session.title).to eq('With Windows')
|
||||
end
|
||||
end
|
||||
|
||||
it "should be able to switch to another window" do
|
||||
window = (@session.windows - [@window]).first
|
||||
expect(@session.driver).to receive(:switch_to_window).exactly(5).times.and_call_original
|
||||
@session.within_window window do
|
||||
expect(['Title of the first popup', 'Title of popup two']).to include(@session.title)
|
||||
end
|
||||
expect(@session.title).to eq('With Windows')
|
||||
end
|
||||
|
||||
it "returns value from the block" do
|
||||
window = (@session.windows - [@window]).first
|
||||
value = @session.within_window window do
|
||||
43252003274489856000
|
||||
end
|
||||
expect(value).to eq(43252003274489856000)
|
||||
end
|
||||
|
||||
it "should switch back if exception was raised inside block" do
|
||||
window = (@session.windows - [@window]).first
|
||||
expect do
|
||||
@session.within_window(window) do
|
||||
raise 'some error'
|
||||
end
|
||||
end.to raise_error(StandardError, 'some error')
|
||||
expect(@session.current_window).to eq(@window)
|
||||
expect(@session).to have_css('#doesNotOpenWindows')
|
||||
end
|
||||
|
||||
it 'should raise error if closed window was passed' do
|
||||
other_window = (@session.windows - [@window]).first
|
||||
@session.within_window other_window do
|
||||
other_window.close
|
||||
end
|
||||
expect do
|
||||
@session.within_window(other_window) do
|
||||
raise 'should not be invoked'
|
||||
end
|
||||
end.to raise_error(@session.driver.no_such_window_error)
|
||||
expect(@session).to have_css('#doesNotOpenWindows')
|
||||
end
|
||||
end
|
||||
|
||||
context "with lambda" do
|
||||
it "should find the div in another window" do
|
||||
@session.within_window(->{ @session.title == 'Title of the first popup'}) do
|
||||
expect(@session).to have_css('#divInPopupOne')
|
||||
end
|
||||
end
|
||||
|
||||
it "should find divs in both windows" do
|
||||
@session.within_window(->{ @session.title == 'Title of popup two'}) do
|
||||
expect(@session).to have_css('#divInPopupTwo')
|
||||
end
|
||||
@session.within_window(->{ @session.title == 'Title of the first popup'}) do
|
||||
expect(@session).to have_css('#divInPopupOne')
|
||||
end
|
||||
expect(@session.title).to eq('With Windows')
|
||||
end
|
||||
|
||||
it "should raise error if window wasn't found" do
|
||||
expect do
|
||||
@session.within_window(->{ @session.title == 'Invalid title'}) do
|
||||
expect(@session).to have_css('#divInPopupOne')
|
||||
end
|
||||
end.to raise_error(Capybara::WindowError, "Could not find a window matching block/lambda")
|
||||
expect(@session).to have_css('#doesNotOpenWindows')
|
||||
end
|
||||
|
||||
it "returns value from the block" do
|
||||
value = @session.within_window(->{ @session.title == 'Title of popup two'}) do
|
||||
42
|
||||
end
|
||||
expect(value).to eq(42)
|
||||
end
|
||||
|
||||
it "should switch back if exception was raised inside block" do
|
||||
expect do
|
||||
@session.within_window(->{ @session.title == 'Title of popup two'}) do
|
||||
raise 'some error'
|
||||
end
|
||||
end.to raise_error(StandardError, 'some error')
|
||||
expect(@session.current_window).to eq(@window)
|
||||
end
|
||||
end
|
||||
|
||||
context "with string" do
|
||||
it "should warn" do
|
||||
expect(@session).to receive(:warn).with("DEPRECATION WARNING: Passing string argument "\
|
||||
"to #within_window is deprecated. Pass window object or lambda. "\
|
||||
"(called from #{__FILE__}:114)").and_call_original
|
||||
@session.within_window('firstPopup') {}
|
||||
end
|
||||
|
||||
it "should find window by handle" do
|
||||
window = (@session.windows - [@window]).first
|
||||
@session.within_window window.handle do
|
||||
expect(['Title of the first popup', 'Title of popup two']).to include(@session.title)
|
||||
end
|
||||
end
|
||||
|
||||
it "should find the div in firstPopup" do
|
||||
@session.within_window("firstPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupOne']").text).to eq 'This is the text of divInPopupOne'
|
||||
end
|
||||
end
|
||||
it "should find the div in secondPopup" do
|
||||
@session.within_window("secondPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupTwo']").text).to eq 'This is the text of divInPopupTwo'
|
||||
end
|
||||
end
|
||||
it "should find the divs in both popups" do
|
||||
@session.within_window("secondPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupTwo']").text).to eq 'This is the text of divInPopupTwo'
|
||||
end
|
||||
@session.within_window("firstPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupOne']").text).to eq 'This is the text of divInPopupOne'
|
||||
end
|
||||
end
|
||||
it "should find the div in the main window after finding a div in a popup" do
|
||||
@session.within_window("secondPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupTwo']").text).to eq 'This is the text of divInPopupTwo'
|
||||
end
|
||||
expect(@session.find("//*[@id='doesNotOpenWindows']").text).to eq 'Does not open windows'
|
||||
end
|
||||
it "should reset scope when switching windows" do
|
||||
@session.within(:css, '#doesNotOpenWindows') do
|
||||
@session.within_window("secondPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupTwo']").text).to eq 'This is the text of divInPopupTwo'
|
||||
end
|
||||
end
|
||||
end
|
||||
it "should switch back if exception was raised inside block" do
|
||||
expect do
|
||||
@session.within_window('secondPopup') do
|
||||
raise 'some error'
|
||||
end
|
||||
end.to raise_error(StandardError, 'some error')
|
||||
expect(@session.current_window).to eq(@window)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,45 +0,0 @@
|
|||
Capybara::SpecHelper.spec '#within_window', :requires => [:windows] do
|
||||
before(:each) do
|
||||
@session.visit('/within_popups')
|
||||
end
|
||||
after(:each) do
|
||||
@session.within_window("firstPopup") do
|
||||
@session.evaluate_script('window.close()')
|
||||
end
|
||||
@session.within_window("secondPopup") do
|
||||
@session.evaluate_script('window.close()')
|
||||
end
|
||||
end
|
||||
|
||||
it "should find the div in firstPopup" do
|
||||
@session.within_window("firstPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupOne']").text).to eql 'This is the text of divInPopupOne'
|
||||
end
|
||||
end
|
||||
it "should find the div in secondPopup" do
|
||||
@session.within_window("secondPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupTwo']").text).to eql 'This is the text of divInPopupTwo'
|
||||
end
|
||||
end
|
||||
it "should find the divs in both popups" do
|
||||
@session.within_window("secondPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupTwo']").text).to eql 'This is the text of divInPopupTwo'
|
||||
end
|
||||
@session.within_window("firstPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupOne']").text).to eql 'This is the text of divInPopupOne'
|
||||
end
|
||||
end
|
||||
it "should find the div in the main window after finding a div in a popup" do
|
||||
@session.within_window("secondPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupTwo']").text).to eql 'This is the text of divInPopupTwo'
|
||||
end
|
||||
expect(@session.find("//*[@id='divInMainWindow']").text).to eql 'This is the text for divInMainWindow'
|
||||
end
|
||||
it "should reset scope when switching windows" do
|
||||
@session.within(:css, '#divInMainWindow') do
|
||||
@session.within_window("secondPopup") do
|
||||
expect(@session.find("//*[@id='divInPopupTwo']").text).to eql 'This is the text of divInPopupTwo'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -54,6 +54,7 @@ module Capybara
|
|||
specs = @specs
|
||||
RSpec.describe Capybara::Session, name, options do
|
||||
include Capybara::SpecHelper
|
||||
include Capybara::RSpecMatchers
|
||||
before do
|
||||
@session = session
|
||||
end
|
||||
|
@ -92,4 +93,4 @@ module Capybara
|
|||
end
|
||||
end
|
||||
|
||||
Dir[File.dirname(__FILE__)+'/session/*'].each { |group| require group }
|
||||
Dir[File.dirname(__FILE__) + "/session/**/*.rb"].each { |file| require_relative file }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>This is the title of the first popup</title>
|
||||
<title>Title of the first popup</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="divInPopupOne">This is the text of divInPopupOne</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>This is the title of popup two</title>
|
||||
<title>Title of popup two</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="divInPopupTwo">This is the text of divInPopupTwo</div>
|
||||
|
|
38
lib/capybara/spec/views/with_windows.erb
Normal file
38
lib/capybara/spec/views/with_windows.erb
Normal file
|
@ -0,0 +1,38 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>With Windows</title>
|
||||
<script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script language="javascript" type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
$('#openWindow').click(function(){
|
||||
window.open('/popup_one', 'firstPopup');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#openWindowWithTimeout').click(function(){
|
||||
setTimeout(function(){
|
||||
window.open('/popup_one', 'firstPopup');
|
||||
}, 500);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#openTwoWindows').click(function() {
|
||||
window.open('/popup_one', 'firstPopup');
|
||||
window.open('/popup_two', 'secondPopup');
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="openWindow">Open new window</button>
|
||||
|
||||
<button id="openWindowWithTimeout">Open new window with timeout</button>
|
||||
|
||||
<button id="openTwoWindows">Open two windows</button>
|
||||
|
||||
<button id="doesNotOpenWindows">Does not open windows</button>
|
||||
|
||||
<iframe src="/frame_one" id="frameOne"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -1,25 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>With Popups</title>
|
||||
<script language="javascript" type="text/javascript">
|
||||
<!--
|
||||
|
||||
function popItUp(name, url) {
|
||||
newwindow=window.open(url,name,'height=200,width=150');
|
||||
if (window.focus) { newwindow.focus() }
|
||||
return false;
|
||||
}
|
||||
|
||||
function init() {
|
||||
popItUp('firstPopup', '/popup_one');
|
||||
popItUp('secondPopup', '/popup_two');
|
||||
}
|
||||
window.onload = init;
|
||||
|
||||
// -->
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="divInMainWindow">This is the text for divInMainWindow</div>
|
||||
</body>
|
||||
</html>
|
98
lib/capybara/window.rb
Normal file
98
lib/capybara/window.rb
Normal file
|
@ -0,0 +1,98 @@
|
|||
module Capybara
|
||||
##
|
||||
# The Window class represents a browser window.
|
||||
#
|
||||
# You can get an instance of the class by calling either of:
|
||||
#
|
||||
# * {Capybara::Session#windows}
|
||||
# * {Capybara::Session#current_window}
|
||||
# * {Capybara::Session#window_opened_by}
|
||||
# * {Capybara::Session#switch_to_window}
|
||||
#
|
||||
class Window
|
||||
# @return [String] a string that uniquely identifies window
|
||||
attr_reader :handle
|
||||
|
||||
# @return [Capybara::Session] session that this window belongs to
|
||||
attr_reader :session
|
||||
|
||||
# @api private
|
||||
def initialize(session, handle)
|
||||
@session = session
|
||||
@driver = session.driver
|
||||
@handle = handle
|
||||
end
|
||||
|
||||
##
|
||||
# @return [Boolean] whether the window is not closed
|
||||
def exists?
|
||||
@driver.window_handles.include?(@handle)
|
||||
end
|
||||
|
||||
##
|
||||
# @return [Boolean] whether the window is closed
|
||||
def closed?
|
||||
!exists?
|
||||
end
|
||||
|
||||
##
|
||||
# @return [Boolean] whether this window is the window in which commands are being executed
|
||||
def current?
|
||||
@driver.current_window_handle == @handle
|
||||
rescue @driver.no_such_window_error
|
||||
false
|
||||
end
|
||||
|
||||
##
|
||||
# Close window. Available only for current window.
|
||||
# After calling this method future invocations of other Capybara methods should raise `session.driver.no_such_window_error` until another window will be switched to.
|
||||
# @raise [Capybara::WindowError] if invoked not for current window
|
||||
#
|
||||
def close
|
||||
raise_unless_current('Closing')
|
||||
@driver.close_current_window
|
||||
end
|
||||
|
||||
##
|
||||
# Get window size. Available only for current window.
|
||||
# @return [Array<(Fixnum, Fixnum)>] an array with width and height
|
||||
# @raise [Capybara::WindowError] if invoked not for current window
|
||||
#
|
||||
def size
|
||||
raise_unless_current('Getting size of')
|
||||
@driver.current_window_size
|
||||
end
|
||||
|
||||
##
|
||||
# Resize window. Available only for current window.
|
||||
# @param width [String] the new window width in pixels
|
||||
# @param height [String] the new window height in pixels
|
||||
# @raise [Capybara::WindowError] if invoked not for current window
|
||||
#
|
||||
def resize_to(width, height)
|
||||
raise_unless_current('Resizing')
|
||||
@driver.resize_current_window_to(width, height)
|
||||
end
|
||||
|
||||
def eql?(other)
|
||||
other.kind_of?(self.class) && @session == other.session && @handle == other.handle
|
||||
end
|
||||
alias_method :==, :eql?
|
||||
|
||||
def hash
|
||||
@session.hash ^ @handle.hash
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<Window @handle=#{@handle.inspect}>"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def raise_unless_current(what)
|
||||
unless current?
|
||||
raise Capybara::WindowError, "#{what} not current window is not possible."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue