Implementation:Teamcapybara Capybara Window
Overview
Capybara::Window represents a browser window within a Capybara session. It provides methods for querying window existence, checking whether a window is current, and performing window operations such as resizing, maximizing, fullscreening, and closing. The class wraps a driver-level window handle and delegates operations through the session's driver, with awareness of whether the target window is the currently active one.
Source File
| Property | Value |
|---|---|
| File | lib/capybara/window.rb
|
| Lines | 142 |
| Language | Ruby |
| Module | Capybara
|
| Class | Capybara::Window
|
Class Definition
class Capybara::Window attr_reader :handle attr_reader :session end
Attributes
| Attribute | Type | Description |
|---|---|---|
handle |
String |
A string that uniquely identifies this window within the session |
session |
Capybara::Session |
The session that this window belongs to |
Obtaining Window Instances
Window instances are not created directly by users. They are obtained through session methods:
Capybara::Session#windows-- returns all open windowsCapybara::Session#current_window-- returns the currently active windowCapybara::Session#window_opened_by-- returns a window opened during a blockCapybara::Session#switch_to_window-- switches to and returns a window
Driver Invocation Behavior
Operations on windows that support targeting (size, resize, close) have different performance characteristics depending on whether the window is current:
- Current window -- 2 Selenium method invocations (get current handle + perform operation)
- Non-current window -- 4 Selenium method invocations (get current handle + switch to target + perform operation + switch back to original)
Public Methods
initialize(session, handle)
Creates a new window instance associated with the given session and driver handle.
def initialize(session, handle) @session = session @driver = session.driver @handle = handle end
exists?
Returns true if the window is still open by checking whether the handle is present in the driver's list of window handles.
def exists? @driver.window_handles.include?(@handle) end
closed?
Returns true if the window has been closed. This is the logical inverse of exists?.
def closed? !exists? end
current?
Returns true if this window is the currently active window in the session. Handles the case where the current window has been closed by rescuing the driver's no_such_window_error and returning false.
def current? @driver.current_window_handle == @handle rescue @driver.no_such_window_error false end
close
Closes the window via the driver. If this method is called on the current window, subsequent Capybara method invocations will raise the driver's no_such_window_error until another window is switched to. If called on a non-current window, the current window remains unchanged.
def close @driver.close_window(handle) end
size
Returns the window size as an [width, height] array of integers.
def size @driver.window_size(handle) end
resize_to(width, height)
Resizes the window to the specified dimensions in pixels. Waits for the size to stabilize after the resize operation using wait_for_stable_size.
def resize_to(width, height)
wait_for_stable_size { @driver.resize_window_to(handle, width, height) }
end
maximize
Maximizes the window. Waits for the size to stabilize after maximizing. Not all drivers support this operation (e.g., headless drivers may lack the concept of maximization).
def maximize
wait_for_stable_size { @driver.maximize_window(handle) }
end
fullscreen
Puts the window into fullscreen mode. Unlike resize_to and maximize, this does not wait for stable size. Not all drivers support this operation.
def fullscreen @driver.fullscreen_window(handle) end
eql?(other) / ==
Two windows are considered equal if they are of the same class, belong to the same session, and have the same handle. The == operator is aliased to eql?.
def eql?(other) other.is_a?(self.class) && @session == other.session && @handle == other.handle end alias_method :==, :eql?
hash
Returns a hash value computed from the session and handle, ensuring consistent behavior when windows are used as hash keys or in sets.
def hash [@session, @handle].hash end
inspect
Returns a human-readable string representation of the window.
def inspect
"#<Window @handle=#{@handle.inspect}>"
end
Private Methods
wait_for_stable_size(seconds)
Waits for the window size to stabilize after a resize or maximize operation. Accepts an optional timeout in seconds (defaults to session.config.default_max_wait_time). Yields to the block containing the resize/maximize operation, then polls the window size at 25ms intervals until two consecutive readings match. Raises Capybara::WindowError if the size does not stabilize within the timeout.
def wait_for_stable_size(seconds = session.config.default_max_wait_time)
res = yield if block_given?
timer = Capybara::Helpers.timer(expire_in: seconds)
loop do
prev_size = size
sleep 0.025
return res if prev_size == size
break if timer.expired?
end
raise Capybara::WindowError, "Window size not stable within #{seconds} seconds."
end
Key Design Decisions
- Handle-based identity -- Windows are identified by opaque driver handles rather than indices or names, ensuring reliable identity even as windows open and close.
- Equality semantics -- Window equality is defined by session and handle, with both
eql?andhashimplemented to support use in collections and as hash keys. - Stable size waiting -- The
resize_toandmaximizemethods wait for the window size to stabilize, accounting for the asynchronous nature of window manager operations. Thefullscreenmethod does not wait, suggesting that fullscreen transitions are treated as immediate. - Graceful current? handling -- The
current?method rescuesno_such_window_errorto handle the edge case where the current window has been closed, returningfalserather than raising. - Driver delegation -- All operations are delegated to the driver through stored references, keeping the Window class as a thin, driver-agnostic wrapper.
See Also
Capybara::Session-- The session class that manages windows and provides window-related methodsCapybara::WindowError-- Exception raised when window size does not stabilizeCapybara::Helpers.timer-- Timer utility used for polling with timeouts