Class: Capybara::Apparition::Page
- Inherits:
-
Object
- Object
- Capybara::Apparition::Page
- Defined in:
- lib/capybara/apparition/page.rb
Instance Attribute Summary collapse
-
#keyboard ⇒ Object
readonly
Returns the value of attribute keyboard.
-
#modal_messages ⇒ Object
readonly
Returns the value of attribute modal_messages.
-
#mouse ⇒ Object
readonly
Returns the value of attribute mouse.
-
#network_traffic ⇒ Object
readonly
Returns the value of attribute network_traffic.
-
#perm_headers ⇒ Object
Returns the value of attribute perm_headers.
-
#response_headers ⇒ Object
readonly
Returns the value of attribute response_headers.
-
#status_code ⇒ Object
readonly
Returns the value of attribute status_code.
-
#temp_headers ⇒ Object
Returns the value of attribute temp_headers.
-
#temp_no_redirect_headers ⇒ Object
Returns the value of attribute temp_no_redirect_headers.
- #url_blacklist ⇒ Object writeonly
- #url_whitelist ⇒ Object writeonly
-
#viewport_size ⇒ Object
readonly
Returns the value of attribute viewport_size.
Class Method Summary collapse
Instance Method Summary collapse
- #add_modal(modal_response) ⇒ Object
- #async_command(name, **params) ⇒ Object
- #clear_network_traffic ⇒ Object
- #click_at(x, y) ⇒ Object
- #command(name, **params) ⇒ Object
- #content ⇒ Object
- #credentials=(creds) ⇒ Object
- #current_frame_offset ⇒ Object
- #current_state ⇒ Object
- #current_url ⇒ Object
- #element_from_point(x:, y:) ⇒ Object
- #evaluate(script, *args) ⇒ Object
- #evaluate_async(script, _wait_time, *args) ⇒ Object
- #execute(script, *args) ⇒ Object
- #extra_headers ⇒ Object
- #find(method, selector) ⇒ Object
- #frame_title ⇒ Object
- #frame_url ⇒ Object
- #fullscreen ⇒ Object
- #go_back ⇒ Object
- #go_forward ⇒ Object
- #inherit(page) ⇒ Object
-
#initialize(browser, session, id, _ignore_https_errors, _screenshot_task_queue, js_errors) ⇒ Page
constructor
A new instance of Page.
- #js_error ⇒ Object
- #maximize ⇒ Object
- #pop_frame(top: false) ⇒ Object
- #proxy_credentials=(creds) ⇒ Object
- #push_frame(frame_el) ⇒ Object
- #refresh ⇒ Object
- #render(options) ⇒ Object
- #reset ⇒ Object
- #scroll_to(left, top) ⇒ Object
- #set_viewport(width:, height:, screen: nil) ⇒ Object
- #title ⇒ Object
- #update_headers(async: false) ⇒ Object
- #usable? ⇒ Boolean
- #visit(url) ⇒ Object
- #wait_for_loaded(allow_obsolete: false) ⇒ Object
Constructor Details
#initialize(browser, session, id, _ignore_https_errors, _screenshot_task_queue, js_errors) ⇒ Page
Returns a new instance of Page.
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 |
# File 'lib/capybara/apparition/page.rb', line 38 def initialize(browser, session, id, _ignore_https_errors, _screenshot_task_queue, js_errors) @target_id = id @browser = browser @session = session @keyboard = Keyboard.new(self) @mouse = Mouse.new(self, @keyboard) @modals = [] @modal_messages = [] @frames = Capybara::Apparition::FrameManager.new(id) @response_headers = {} @status_code = 0 @url_blacklist = [] @url_whitelist = [] @credentials = nil @auth_attempts = [] @proxy_credentials = nil @proxy_auth_attempts = [] @perm_headers = {} @temp_headers = {} @temp_no_redirect_headers = {} @viewport_size = nil @network_traffic = [] @open_resource_requests = {} @raise_js_errors = js_errors @js_error = nil @modal_mutex = Mutex.new @modal_closed = ConditionVariable.new register_event_handlers register_js_error_handler # if js_errors setup_network_interception if browser.proxy_auth end |
Instance Attribute Details
#keyboard ⇒ Object (readonly)
Returns the value of attribute keyboard.
11 12 13 |
# File 'lib/capybara/apparition/page.rb', line 11 def keyboard @keyboard end |
#modal_messages ⇒ Object (readonly)
Returns the value of attribute modal_messages.
10 11 12 |
# File 'lib/capybara/apparition/page.rb', line 10 def @modal_messages end |
#mouse ⇒ Object (readonly)
Returns the value of attribute mouse.
11 12 13 |
# File 'lib/capybara/apparition/page.rb', line 11 def mouse @mouse end |
#network_traffic ⇒ Object (readonly)
Returns the value of attribute network_traffic.
14 15 16 |
# File 'lib/capybara/apparition/page.rb', line 14 def network_traffic @network_traffic end |
#perm_headers ⇒ Object
Returns the value of attribute perm_headers.
13 14 15 |
# File 'lib/capybara/apparition/page.rb', line 13 def perm_headers @perm_headers end |
#response_headers ⇒ Object (readonly)
Returns the value of attribute response_headers.
228 229 230 |
# File 'lib/capybara/apparition/page.rb', line 228 def response_headers @response_headers end |
#status_code ⇒ Object (readonly)
Returns the value of attribute status_code.
230 231 232 |
# File 'lib/capybara/apparition/page.rb', line 230 def status_code @status_code end |
#temp_headers ⇒ Object
Returns the value of attribute temp_headers.
13 14 15 |
# File 'lib/capybara/apparition/page.rb', line 13 def temp_headers @temp_headers end |
#temp_no_redirect_headers ⇒ Object
Returns the value of attribute temp_no_redirect_headers.
13 14 15 |
# File 'lib/capybara/apparition/page.rb', line 13 def temp_no_redirect_headers @temp_no_redirect_headers end |
#url_blacklist=(blacklist) ⇒ Object
102 103 104 105 |
# File 'lib/capybara/apparition/page.rb', line 102 def url_blacklist=(blacklist) @url_blacklist = blacklist setup_network_blocking end |
#url_whitelist=(whitelist) ⇒ Object
107 108 109 110 |
# File 'lib/capybara/apparition/page.rb', line 107 def url_whitelist=(whitelist) @url_whitelist = whitelist setup_network_blocking end |
#viewport_size ⇒ Object (readonly)
Returns the value of attribute viewport_size.
12 13 14 |
# File 'lib/capybara/apparition/page.rb', line 12 def @viewport_size end |
Class Method Details
.create(browser, session, id, ignore_https_errors: false, screenshot_task_queue: nil, js_errors: false) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/capybara/apparition/page.rb', line 16 def self.create(browser, session, id, ignore_https_errors: false, screenshot_task_queue: nil, js_errors: false) session.command 'Page.enable' # Provides a lot of info - but huge overhead # session.command 'Page.setLifecycleEventsEnabled', enabled: true page = Page.new(browser, session, id, ignore_https_errors, screenshot_task_queue, js_errors) session.async_commands 'Network.enable', 'Runtime.enable', 'Security.enable', 'DOM.enable' # session.command 'Network.enable' # session.command 'Runtime.enable' # session.command 'Security.enable' # session.command 'Security.setOverrideCertificateErrors', override: true if ignore_https_errors session.command 'Security.setIgnoreCertificateErrors', ignore: !!ignore_https_errors # session.command 'DOM.enable' # session.command 'Log.enable' if Capybara.save_path session.command 'Page.setDownloadBehavior', behavior: 'allow', downloadPath: Capybara.save_path end page end |
Instance Method Details
#add_modal(modal_response) ⇒ Object
87 88 89 90 |
# File 'lib/capybara/apparition/page.rb', line 87 def add_modal(modal_response) @last_modal_message = nil @modals.push(modal_response) end |
#async_command(name, **params) ⇒ Object
344 345 346 |
# File 'lib/capybara/apparition/page.rb', line 344 def async_command(name, **params) @browser.command_for_session(@session.session_id, name, params).discard_result end |
#clear_network_traffic ⇒ Object
112 113 114 |
# File 'lib/capybara/apparition/page.rb', line 112 def clear_network_traffic @network_traffic = [] end |
#click_at(x, y) ⇒ Object
121 122 123 124 |
# File 'lib/capybara/apparition/page.rb', line 121 def click_at(x, y) wait_for_loaded @mouse.click_at(x: x, y: y) end |
#command(name, **params) ⇒ Object
340 341 342 |
# File 'lib/capybara/apparition/page.rb', line 340 def command(name, **params) @browser.command_for_session(@session.session_id, name, params).result end |
#content ⇒ Object
245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/capybara/apparition/page.rb', line 245 def content wait_for_loaded _raw_evaluate("(function(){ let val = ''; if (document.doctype) val = new XMLSerializer().serializeToString(document.doctype); if (document.documentElement) val += document.documentElement.outerHTML; return val; })()") end |
#credentials=(creds) ⇒ Object
97 98 99 100 |
# File 'lib/capybara/apparition/page.rb', line 97 def credentials=(creds) @credentials = creds setup_network_interception end |
#current_frame_offset ⇒ Object
130 131 132 |
# File 'lib/capybara/apparition/page.rb', line 130 def current_frame_offset frame_offset(current_frame) end |
#current_state ⇒ Object
126 127 128 |
# File 'lib/capybara/apparition/page.rb', line 126 def current_state main_frame.state end |
#current_url ⇒ Object
272 273 274 275 |
# File 'lib/capybara/apparition/page.rb', line 272 def current_url wait_for_loaded _raw_evaluate('window.location.href', context_id: main_frame.context_id) end |
#element_from_point(x:, y:) ⇒ Object
277 278 279 280 281 282 283 284 285 286 |
# File 'lib/capybara/apparition/page.rb', line 277 def element_from_point(x:, y:) r_o = _raw_evaluate("document.elementFromPoint(#{x}, #{y})", context_id: main_frame.context_id) while r_o && (r_o['description'] =~ /^iframe/) frame_node = command('DOM.describeNode', objectId: r_o['objectId']) frame = @frames.get(frame_node.dig('node', 'frameId')) fo = frame_offset(frame) r_o = _raw_evaluate("document.elementFromPoint(#{x - fo[:x]}, #{y - fo[:y]})", context_id: frame.context_id) end r_o end |
#evaluate(script, *args) ⇒ Object
203 204 205 |
# File 'lib/capybara/apparition/page.rb', line 203 def evaluate(script, *args) eval_wrapped_script(EVALUATE_WITH_ID_JS, script, args) end |
#evaluate_async(script, _wait_time, *args) ⇒ Object
207 208 209 |
# File 'lib/capybara/apparition/page.rb', line 207 def evaluate_async(script, _wait_time, *args) eval_wrapped_script(EVALUATE_ASYNC_JS, script, args) end |
#execute(script, *args) ⇒ Object
198 199 200 201 |
# File 'lib/capybara/apparition/page.rb', line 198 def execute(script, *args) eval_wrapped_script(EXECUTE_JS, script, args) nil end |
#extra_headers ⇒ Object
348 349 350 |
# File 'lib/capybara/apparition/page.rb', line 348 def extra_headers temp_headers.merge(perm_headers).merge(temp_no_redirect_headers) end |
#find(method, selector) ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/capybara/apparition/page.rb', line 186 def find(method, selector) wait_for_loaded js_escaped_selector = selector.gsub('\\', '\\\\\\').gsub('"', '\"') query = method == :css ? CSS_FIND_JS : XPATH_FIND_JS result = _raw_evaluate(query % js_escaped_selector) (result || []).map { |r_o| [self, r_o['objectId']] } rescue ::Capybara::Apparition::BrowserError => e raise unless e.name =~ /is not a valid (XPath expression|selector)/ raise Capybara::Apparition::InvalidSelector, [method, selector] end |
#frame_title ⇒ Object
335 336 337 338 |
# File 'lib/capybara/apparition/page.rb', line 335 def frame_title wait_for_loaded _raw_evaluate('document.title') end |
#frame_url ⇒ Object
288 289 290 291 |
# File 'lib/capybara/apparition/page.rb', line 288 def frame_url wait_for_loaded _raw_evaluate('window.location.href') end |
#fullscreen ⇒ Object
317 318 319 320 |
# File 'lib/capybara/apparition/page.rb', line 317 def fullscreen result = @browser.command('Browser.getWindowForTarget', targetId: @target_id) @browser.command('Browser.setWindowBounds', windowId: result['windowId'], bounds: { windowState: 'fullscreen' }) end |
#go_back ⇒ Object
218 219 220 221 |
# File 'lib/capybara/apparition/page.rb', line 218 def go_back wait_for_loaded go_history(-1) end |
#go_forward ⇒ Object
223 224 225 226 |
# File 'lib/capybara/apparition/page.rb', line 223 def go_forward wait_for_loaded go_history(+1) end |
#inherit(page) ⇒ Object
361 362 363 364 365 366 367 368 |
# File 'lib/capybara/apparition/page.rb', line 361 def inherit(page) if page self.url_whitelist = page.url_whitelist.dup self.url_blacklist = page.url_blacklist.dup (page.) if page. end self end |
#js_error ⇒ Object
370 371 372 373 374 |
# File 'lib/capybara/apparition/page.rb', line 370 def js_error res = @js_error @js_error = nil res end |
#maximize ⇒ Object
322 323 324 325 326 327 328 |
# File 'lib/capybara/apparition/page.rb', line 322 def maximize screen_width, screen_height = *evaluate('[window.screen.width, window.screen.height]') (width: screen_width, height: screen_height) result = @browser.command('Browser.getWindowForTarget', targetId: @target_id) @browser.command('Browser.setWindowBounds', windowId: result['windowId'], bounds: { windowState: 'maximized' }) end |
#pop_frame(top: false) ⇒ Object
182 183 184 |
# File 'lib/capybara/apparition/page.rb', line 182 def pop_frame(top: false) @frames.pop_frame(top: top) end |
#proxy_credentials=(creds) ⇒ Object
92 93 94 95 |
# File 'lib/capybara/apparition/page.rb', line 92 def proxy_credentials=(creds) @proxy_credentials = creds setup_network_interception end |
#push_frame(frame_el) ⇒ Object
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/capybara/apparition/page.rb', line 162 def push_frame(frame_el) node = command('DOM.describeNode', objectId: frame_el.base.id) frame_id = node['node']['frameId'] timer = Capybara::Helpers.timer(expire_in: 10) while (frame = @frames.get(frame_id)).nil? || frame.loading? # Wait for the frame creation messages to be processed if timer.expired? puts 'Timed out waiting from frame to be ready' raise TimeoutError.new('push_frame') end sleep 0.1 end return unless frame frame.element_id = frame_el.base.id @frames.push_frame(frame.id) frame end |
#refresh ⇒ Object
211 212 213 214 215 216 |
# File 'lib/capybara/apparition/page.rb', line 211 def refresh wait_for_loaded main_frame.reloading! command('Page.reload', ignoreCache: true) wait_for_loaded end |
#render(options) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/capybara/apparition/page.rb', line 134 def render() wait_for_loaded pixel_ratio = evaluate('window.devicePixelRatio') scale = (@browser.zoom_factor || 1).to_f / pixel_ratio if [:format].to_s == 'pdf' params = {} params[:paperWidth] = @browser.paper_size[:width].to_f if @browser.paper_size params[:paperHeight] = @browser.paper_size[:height].to_f if @browser.paper_size params[:scale] = scale command('Page.printToPDF', params) else = if [:selector] pos = evaluate("document.querySelector('#{.delete(:selector)}').getBoundingClientRect().toJSON();") %w[x y width height].each_with_object({}) { |key, hash| hash[key] = pos[key] } elsif [:full] evaluate <<~JS { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight} JS else evaluate <<~JS { width: window.innerWidth, height: window.innerHeight } JS end [:clip] = { x: 0, y: 0, scale: scale }.merge() command('Page.captureScreenshot', ) end['data'] end |
#reset ⇒ Object
77 78 79 80 81 82 83 84 85 |
# File 'lib/capybara/apparition/page.rb', line 77 def reset @modals.clear @modal_messages.clear @response_headers = {} @status_code = 0 @auth_attempts = [] @proxy_auth_attempts = [] @perm_headers = {} end |
#scroll_to(left, top) ⇒ Object
116 117 118 119 |
# File 'lib/capybara/apparition/page.rb', line 116 def scroll_to(left, top) wait_for_loaded execute('window.scrollTo(arguments[0], arguments[1])', left, top) end |
#set_viewport(width:, height:, screen: nil) ⇒ Object
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/capybara/apparition/page.rb', line 293 def (width:, height:, screen: nil) wait_for_loaded @viewport_size = { width: width, height: height } result = @browser.command('Browser.getWindowForTarget', targetId: @target_id) begin @browser.command('Browser.setWindowBounds', windowId: result['windowId'], bounds: { width: width, height: height }) rescue WrongWorld # TODO: Fix Error naming here @browser.command('Browser.setWindowBounds', windowId: result['windowId'], bounds: { windowState: 'normal' }) retry end metrics = { mobile: false, width: width, height: height, deviceScaleFactor: 1 } metrics[:screenWidth], metrics[:screenHeight] = *screen if screen command('Emulation.setDeviceMetricsOverride', metrics) end |
#title ⇒ Object
330 331 332 333 |
# File 'lib/capybara/apparition/page.rb', line 330 def title wait_for_loaded _raw_evaluate('document.title', context_id: main_frame.context_id) end |
#update_headers(async: false) ⇒ Object
352 353 354 355 356 357 358 359 |
# File 'lib/capybara/apparition/page.rb', line 352 def update_headers(async: false) method = async ? :async_command : :command if (ua = extra_headers.find { |k, _v| k =~ /^User-Agent$/i }) send(method, 'Network.setUserAgentOverride', userAgent: ua[1]) end send(method, 'Network.setExtraHTTPHeaders', headers: extra_headers) setup_network_interception end |
#usable? ⇒ Boolean
73 74 75 |
# File 'lib/capybara/apparition/page.rb', line 73 def usable? !!current_frame&.context_id end |
#visit(url) ⇒ Object
257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/capybara/apparition/page.rb', line 257 def visit(url) wait_for_loaded @status_code = 0 navigate_opts = { url: url, transitionType: 'reload' } navigate_opts[:referrer] = extra_headers['Referer'] if extra_headers['Referer'] response = command('Page.navigate', navigate_opts) raise StatusFailError, 'args' => [url, response['errorText']] if response['errorText'] main_frame.loading(response['loaderId']) wait_for_loaded rescue TimeoutError raise StatusFailError.new('args' => [url]) end |
#wait_for_loaded(allow_obsolete: false) ⇒ Object
232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/capybara/apparition/page.rb', line 232 def wait_for_loaded(allow_obsolete: false) timer = Capybara::Helpers.timer(expire_in: 10) cf = current_frame until cf.usable? || (allow_obsolete && cf.obsolete?) || @js_error if timer.expired? puts 'Timedout waiting for page to be loaded' raise TimeoutError.new('wait_for_loaded') end sleep 0.05 end raise JavascriptError.new(js_error) if @js_error end |