File: window.rb

package info (click to toggle)
ruby-capybara 3.40.0%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,368 kB
  • sloc: ruby: 23,988; javascript: 752; makefile: 11
file content (142 lines) | stat: -rw-r--r-- 3,978 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# frozen_string_literal: true

module Capybara
  ##
  # The {Window} class represents a browser window.
  #
  # You can get an instance of the class by calling any of:
  #
  # * {Capybara::Session#windows}
  # * {Capybara::Session#current_window}
  # * {Capybara::Session#window_opened_by}
  # * {Capybara::Session#switch_to_window}
  #
  # Note that some drivers (e.g. Selenium) support getting size of/resizing/closing only
  # current window. So if you invoke such method for:
  #
  # * window that is current, Capybara will make 2 Selenium method invocations
  #   (get handle of current window + get size/resize/close).
  # * window that is not current, Capybara will make 4 Selenium method invocations
  #   (get handle of current window + switch to given handle + get size/resize/close + switch to original handle)
  #
  class Window
    # @return [String]   a string that uniquely identifies window within session
    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.
    #
    # If this method was called for window that is current, then after calling this method
    # future invocations of other Capybara methods should raise
    # {Capybara::Driver::Base#no_such_window_error session.driver.no_such_window_error} until another window will be switched to.
    #
    # @!macro about_current
    #   If this method was called for window that is not current, then after calling this method
    #   current window should remain the same as it was before calling this method.
    #
    def close
      @driver.close_window(handle)
    end

    ##
    # Get window size.
    #
    # @macro about_current
    # @return [Array<(Integer, Integer)>] an array with width and height
    #
    def size
      @driver.window_size(handle)
    end

    ##
    # Resize window.
    #
    # @macro about_current
    # @param width [Integer]  the new window width in pixels
    # @param height [Integer]  the new window height in pixels
    #
    def resize_to(width, height)
      wait_for_stable_size { @driver.resize_window_to(handle, width, height) }
    end

    ##
    # Maximize window.
    #
    # If a particular driver (e.g. headless driver) doesn't have concept of maximizing it
    # may not support this method.
    #
    # @macro about_current
    #
    def maximize
      wait_for_stable_size { @driver.maximize_window(handle) }
    end

    ##
    # Fullscreen window.
    #
    # If a particular driver doesn't have concept of fullscreen it may not support this method.
    #
    # @macro about_current
    #
    def fullscreen
      @driver.fullscreen_window(handle)
    end

    def eql?(other)
      other.is_a?(self.class) && @session == other.session && @handle == other.handle
    end
    alias_method :==, :eql?

    def hash
      [@session, @handle].hash
    end

    def inspect
      "#<Window @handle=#{@handle.inspect}>"
    end

  private

    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
  end
end