Class: Vapir::Firefox
- Includes:
- Firefox::Window, ModalDialogContainer, PageContainer
- Defined in:
- lib/vapir-firefox/firefox.rb,
lib/vapir-firefox/version.rb
Defined Under Namespace
Modules: Container, ModalDialogContainer, PageContainer, RadioCheckboxCommon Classes: Area, Button, CheckBox, Dd, Div, Dl, Dt, Em, FileField, Form, Frame, H1, H2, H3, H4, H5, H6, Hidden, Image, InputElement, Label, Li, Link, Map, ModalDialog, ModalDialogDocument, Ol, Option, P, Pre, Radio, SelectList, Span, Strong, TBody, Table, TableCell, TableRow, TextField, Ul
Constant Summary collapse
- VERSION =
'1.7.1'
Instance Attribute Summary collapse
-
#body_object ⇒ Object
readonly
Returns the value of attribute body_object.
-
#browser_object ⇒ Object
readonly
Returns the value of attribute browser_object.
-
#browser_window_object ⇒ Object
readonly
Returns the value of attribute browser_window_object.
-
#content_window_object ⇒ Object
readonly
Returns the value of attribute content_window_object.
-
#document_object ⇒ Object
readonly
Returns the value of attribute document_object.
Class Method Summary collapse
-
.attach(how, what) ⇒ Object
Class method to return a browser object if a window matches for how and what.
- .browser_window_objects ⇒ Object
- .each ⇒ Object
- .each_browser_window_object ⇒ Object
- .each_window_object ⇒ Object
- .initialize_jssh_socket ⇒ Object
- .jssh_socket(options = {}) ⇒ Object
-
.start(url) ⇒ Object
Creates a new instance of Firefox.
- .window_objects ⇒ Object
Instance Method Summary collapse
-
#add_checker(checker) ⇒ Object
Add an error checker that gets called on every page load.
-
#attach(how, what) ⇒ Object
Used for attaching pop up window to an existing Firefox window, either by url or title.
-
#back ⇒ Object
Loads the previous page (if there is any) in the browser.
- #browser ⇒ Object
-
#close ⇒ Object
Closes the window.
-
#close_all ⇒ Object
Closes all firefox windows by quitting the browser.
-
#disable_checker(checker) ⇒ Object
Disable an error checker * checker - a Proc object that is to be disabled.
- #exists? ⇒ Boolean
-
#forward ⇒ Object
Loads the next page (if there is any) in the browser.
-
#goto(url) ⇒ Object
Loads the given url in the browser.
-
#initialize(options = {}) ⇒ Firefox
constructor
Description: Starts the firefox browser.
- #jssh_socket(options = nil) ⇒ Object
-
#maximize ⇒ Object
Maximize the current browser window.
-
#minimize ⇒ Object
Minimize the current browser window.
-
#mozilla_window_class_name ⇒ Object
true end def firefox_is_running? self.class.firefox_is_running? end.
-
#quit_browser(options = {}) ⇒ Object
quits the browser.
-
#refresh ⇒ Object
Reloads the current page in the browser.
-
#run_error_checks ⇒ Object
Run the predefined error checks.
- #startClicker(*args) ⇒ Object
-
#status ⇒ Object
Returns the Status of the page currently loaded in the browser from statusbar.
-
#text ⇒ Object
Returns the text of the page currently loaded in the browser.
- #updated_at ⇒ Object
-
#wait(options = {}) ⇒ Object
Waits for the page to get loaded.
Methods included from ModalDialogContainer
Methods included from PageContainer
Methods included from Container
#element_by_xpath, #element_object_by_xpath, #element_objects_by_xpath, #elements_by_xpath, #extra_for_contained
Constructor Details
#initialize(options = {}) ⇒ Firefox
Description:
Starts the firefox browser.
On windows this starts the first version listed in the registry.
Input:
options - Hash of any of the following options:
:wait_time - Time to wait for Firefox to start. By default it waits for 2 seconds.
This is done because if Firefox is not started and we try to connect
to jssh on port 9997 an exception is thrown.
:profile - The Firefox profile to use. If none is specified, Firefox will use
the last used profile.
:suppress_launch_process - do not create a new firefox process. Connect to an existing one.
TODO: Start the firefox version given by user.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/vapir-firefox/firefox.rb', line 139 def initialize( = {}) if(.kind_of?(Integer)) = {:wait_time => } Kernel.warn "DEPRECATION WARNING: #{self.class.name}.new takes an options hash - passing a number is deprecated. Please use #{self.class.name}.new(:wait_time => #{[:wait_time]})\n(called from #{caller.map{|c|"\n"+c}})" end =(, {:wait_time => 20}, [:attach, :goto, :binary_path]) if [:binary_path] @binary_path=[:binary_path] end # check for jssh not running, firefox may be open but not with -jssh # if its not open at all, regardless of the :suppress_launch_process option start it # error if running without jssh, we don't want to kill their current window (mac only) begin jssh_socket(:reset_if_dead => true).assert_socket rescue JsshError # here we're going to assume that since it's not connecting, we need to launch firefox. if [:attach] raise Vapir::Exception::NoBrowserException, "cannot attach using #{[:attach].inspect} - could not connect to Firefox with JSSH" else launch_browser # if we just launched a the browser process, attach to the window # that opened when we did that. # but if options[:attach] is explicitly given as false (not nil), # take that to mean we don't want to attach to the window launched # when the process starts. unless [:attach]==false [:attach]=[:title, //] end end ::Waiter.try_for([:wait_time], :exception => Vapir::Exception::NoBrowserException.new("Could not connect to the JSSH socket on the browser after #{[:wait_time]} seconds. Either Firefox did not start or JSSH is not installed and listening.")) do begin jssh_socket(:reset_if_dead => true).assert_socket true rescue JsshUnableToStart false end end end @browser_jssh_objects = jssh_socket.object('{}').store_rand_object_key(@@firewatir_jssh_objects) # this is an object that holds stuff for this browser if [:attach] attach(*[:attach]) else open_window end set_browser_document set_defaults if [:goto] goto([:goto]) end end |
Instance Attribute Details
#body_object ⇒ Object (readonly)
Returns the value of attribute body_object.
359 360 361 |
# File 'lib/vapir-firefox/firefox.rb', line 359 def body_object @body_object end |
#browser_object ⇒ Object (readonly)
Returns the value of attribute browser_object.
357 358 359 |
# File 'lib/vapir-firefox/firefox.rb', line 357 def browser_object @browser_object end |
#browser_window_object ⇒ Object (readonly)
Returns the value of attribute browser_window_object.
355 356 357 |
# File 'lib/vapir-firefox/firefox.rb', line 355 def browser_window_object @browser_window_object end |
#content_window_object ⇒ Object (readonly)
Returns the value of attribute content_window_object.
356 357 358 |
# File 'lib/vapir-firefox/firefox.rb', line 356 def content_window_object @content_window_object end |
#document_object ⇒ Object (readonly)
Returns the value of attribute document_object.
358 359 360 |
# File 'lib/vapir-firefox/firefox.rb', line 358 def document_object @document_object end |
Class Method Details
.attach(how, what) ⇒ Object
Class method to return a browser object if a window matches for how and what. Window can be referenced by url or title. The second argument can be either a string or a regular expression. Vapir::Browser.attach(:url, ‘www.google.com’) Vapir::Browser.attach(:title, ‘Google’)
446 447 448 |
# File 'lib/vapir-firefox/firefox.rb', line 446 def self.attach how, what new(:attach => [how, what]) end |
.browser_window_objects ⇒ Object
481 482 483 484 485 486 487 |
# File 'lib/vapir-firefox/firefox.rb', line 481 def self.browser_window_objects window_objects=[] each_browser_window_object do |window_object| window_objects << window_object end window_objects end |
.each ⇒ Object
466 467 468 469 470 |
# File 'lib/vapir-firefox/firefox.rb', line 466 def self.each each_browser_window_object do |win| yield self.attach(:jssh_object, win) end end |
.each_browser_window_object ⇒ Object
472 473 474 475 476 477 478 479 480 |
# File 'lib/vapir-firefox/firefox.rb', line 472 def self.each_browser_window_object mediator=jssh_socket.Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(jssh_socket.Components.interfaces.nsIWindowMediator) enumerator=mediator.getEnumerator("navigator:browser") while enumerator.hasMoreElements win=enumerator.getNext yield win end nil end |
.each_window_object ⇒ Object
488 489 490 491 492 493 494 495 496 |
# File 'lib/vapir-firefox/firefox.rb', line 488 def self.each_window_object mediator=jssh_socket.Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(jssh_socket.Components.interfaces.nsIWindowMediator) enumerator=mediator.getEnumerator(nil) while enumerator.hasMoreElements win=enumerator.getNext yield win end nil end |
.initialize_jssh_socket ⇒ Object
100 101 102 103 104 105 106 107 108 |
# File 'lib/vapir-firefox/firefox.rb', line 100 def self.initialize_jssh_socket # if it already exists and is not nil, then we are clobbering an existing one, presumably dead. but a new socket will not have any objects of the old one, so warn if class_variable_defined?('@@jssh_socket') && @@jssh_socket Kernel.warn "WARNING: JSSH_SOCKET RESET: resetting jssh socket. Any active javascript references will not exist on the new socket!" end @@jssh_socket=JsshSocket.new @@firewatir_jssh_objects=@@jssh_socket.object("Vapir").assign({}) @@jssh_socket end |
.jssh_socket(options = {}) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/vapir-firefox/firefox.rb', line 109 def self.jssh_socket(={}) if [:reset] || !(class_variable_defined?('@@jssh_socket') && @@jssh_socket) initialize_jssh_socket end if [:reset_if_dead] begin @@jssh_socket.assert_socket rescue JsshConnectionError initialize_jssh_socket end end @@jssh_socket end |
.start(url) ⇒ Object
Creates a new instance of Firefox. Loads the URL and return the instance. Input:
url - url of the page to be loaded.
230 231 232 |
# File 'lib/vapir-firefox/firefox.rb', line 230 def self.start(url) new(:goto => url) end |
.window_objects ⇒ Object
497 498 499 500 501 502 503 |
# File 'lib/vapir-firefox/firefox.rb', line 497 def self.window_objects window_objects=[] each_window_object do |window_object| window_objects << window_object end window_objects end |
Instance Method Details
#add_checker(checker) ⇒ Object
Add an error checker that gets called on every page load.
-
checker - a Proc object
606 607 608 |
# File 'lib/vapir-firefox/firefox.rb', line 606 def add_checker(checker) @error_checkers << checker end |
#attach(how, what) ⇒ Object
Used for attaching pop up window to an existing Firefox window, either by url or title.
ff.attach(:url, 'http://www.google.com')
ff.attach(:title, 'Google')
Output:
Instance of newly attached window.
426 427 428 429 430 431 432 433 434 435 436 437 438 439 |
# File 'lib/vapir-firefox/firefox.rb', line 426 def attach(how, what) @browser_window_object = case how when :jssh_object what else find_window(how, what) end unless @browser_window_object raise Exception::NoMatchingWindowFoundException.new("Unable to locate window, using #{how} and #{what}") end set_browser_document self end |
#back ⇒ Object
Loads the previous page (if there is any) in the browser. Waits for the page to get loaded.
243 244 245 246 247 248 249 250 |
# File 'lib/vapir-firefox/firefox.rb', line 243 def back if browser_object.canGoBack browser_object.goBack else raise Vapir::Exception::NavigationException, "Cannot go back!" end wait end |
#browser ⇒ Object
204 205 206 |
# File 'lib/vapir-firefox/firefox.rb', line 204 def browser self end |
#close ⇒ Object
Closes the window.
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/vapir-firefox/firefox.rb', line 367 def close assert_exists begin browser_window_object.close # TODO/fix timeout; this shouldn't be a hard-coded magic number. ::Waiter.try_for(32, :exception => Exception::WindowFailedToCloseException.new("The browser window did not close")) do !exists? end @@jssh_socket.assert_socket rescue JsshConnectionError # the socket may disconnect when we close the browser, causing the JsshSocket to complain @@jssh_socket=nil end @browser_window_object=@browser_object=@document_object=@content_window_object=@body_object=nil @launched_browser_process=false #TODO/FIX: check here if we originally launched the browser process if @launched_browser_process && @@jssh_socket quit_browser(:force => false) end end |
#close_all ⇒ Object
Closes all firefox windows by quitting the browser
387 388 389 |
# File 'lib/vapir-firefox/firefox.rb', line 387 def close_all quit_browser(:force => false) end |
#disable_checker(checker) ⇒ Object
Disable an error checker
-
checker - a Proc object that is to be disabled
612 613 614 |
# File 'lib/vapir-firefox/firefox.rb', line 612 def disable_checker(checker) @error_checkers.delete(checker) end |
#exists? ⇒ Boolean
208 209 210 211 |
# File 'lib/vapir-firefox/firefox.rb', line 208 def exists? # jssh_socket may be nil if the window has closed jssh_socket && browser_window_object && jssh_socket.object('getWindows()').to_js_array.include(browser_window_object) end |
#forward ⇒ Object
Loads the next page (if there is any) in the browser. Waits for the page to get loaded.
253 254 255 256 257 258 259 260 |
# File 'lib/vapir-firefox/firefox.rb', line 253 def forward if browser_object.canGoForward browser_object.goForward else raise Vapir::Exception::NavigationException, "Cannot go forward!" end wait end |
#goto(url) ⇒ Object
Loads the given url in the browser. Waits for the page to get loaded.
236 237 238 239 240 |
# File 'lib/vapir-firefox/firefox.rb', line 236 def goto(url) assert_exists browser_object.loadURI url wait end |
#jssh_socket(options = nil) ⇒ Object
122 123 124 |
# File 'lib/vapir-firefox/firefox.rb', line 122 def jssh_socket(=nil) ? self.class.jssh_socket() : @@jssh_socket end |
#maximize ⇒ Object
Maximize the current browser window.
542 543 544 |
# File 'lib/vapir-firefox/firefox.rb', line 542 def maximize() browser_window_object.maximize end |
#minimize ⇒ Object
Minimize the current browser window.
547 548 549 |
# File 'lib/vapir-firefox/firefox.rb', line 547 def minimize() browser_window_object.minimize end |
#mozilla_window_class_name ⇒ Object
true
end
def firefox_is_running?
self.class.firefox_is_running?
end
200 201 202 |
# File 'lib/vapir-firefox/firefox.rb', line 200 def mozilla_window_class_name 'MozillaUIWindowClass' end |
#quit_browser(options = {}) ⇒ Object
quits the browser. quit_browser(:force => true) will force the browser to quit.
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 |
# File 'lib/vapir-firefox/firefox.rb', line 393 def quit_browser(={}) =(, :force => false) # from https://developer.mozilla.org/en/How_to_Quit_a_XUL_Application appStartup= jssh_socket.Components.classes['@mozilla.org/toolkit/app-startup;1'].getService(jssh_socket.Components.interfaces.nsIAppStartup) quitSeverity = [:force] ? jssh_socket.Components.interfaces.nsIAppStartup.eForceQuit : jssh_socket.Components.interfaces.nsIAppStartup.eAttemptQuit begin appStartup.quit(quitSeverity) ::Waiter.try_for(8, :exception => Exception::WindowFailedToCloseException.new("The browser did not quit")) do @@jssh_socket.assert_socket # this should error, going up past the waiter to the rescue block above false end rescue JsshConnectionError @@jssh_socket=nil end # TODO/FIX: poll to wait for the process itself to finish? the socket closes (which we wait for # above) before the process itself has exited, so if Firefox.new is called between the socket # closing and the process exiting, Firefox pops up with: # Close Firefox # A copy of Firefox is already open. Only one copy of Firefox can be open at a time. # [OK] # until that's implemented, just wait for an arbitrary amount of time. (ick) sleep 2 @browser_window_object=@browser_object=@document_object=@content_window_object=@body_object=nil nil end |
#refresh ⇒ Object
Reloads the current page in the browser. Waits for the page to get loaded.
263 264 265 266 |
# File 'lib/vapir-firefox/firefox.rb', line 263 def refresh browser_object.reload wait end |
#run_error_checks ⇒ Object
Run the predefined error checks. This is automatically called on every page load.
617 618 619 |
# File 'lib/vapir-firefox/firefox.rb', line 617 def run_error_checks @error_checkers.each { |e| e.call(self) } end |
#startClicker(*args) ⇒ Object
622 623 624 |
# File 'lib/vapir-firefox/firefox.rb', line 622 def startClicker(*args) raise NotImplementedError, "startClicker is gone. Use Firefox#modal_dialog.click_button (generally preceded by a Element#click_no_wait)" end |
#status ⇒ Object
Returns the Status of the page currently loaded in the browser from statusbar.
Output:
Status of the page.
531 532 533 534 |
# File 'lib/vapir-firefox/firefox.rb', line 531 def status #content_window_object.status browser_window_object.XULBrowserWindow.statusText end |
#text ⇒ Object
Returns the text of the page currently loaded in the browser.
537 538 539 |
# File 'lib/vapir-firefox/firefox.rb', line 537 def text body_object.textContent end |
#updated_at ⇒ Object
361 362 363 |
# File 'lib/vapir-firefox/firefox.rb', line 361 def updated_at Time.at(@updated_at_epoch_ms.val/1000.0)+@updated_at_offset end |
#wait(options = {}) ⇒ Object
Waits for the page to get loaded.
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 |
# File 'lib/vapir-firefox/firefox.rb', line 552 def wait(={}) return unless exists? unless .is_a?(Hash) raise ArgumentError, "given options should be a Hash, not #{.inspect} (#{.class})\nold conflicting arguments of no_sleep or last_url are gone" end ={:sleep => false, :last_url => nil, :timeout => 120}.merge() started=Time.now while browser_object.webProgress.isLoadingDocument sleep 0.1 if Time.now - started > [:timeout] raise "Page Load Timeout" end end # If the redirect is to a download attachment that does not reload this page, this # method will loop forever. Therefore, we need to ensure that if this method is called # twice with the same URL, we simply accept that we're done. url= document_object.URL if(url != [:last_url]) # Check for Javascript redirect. As we are connected to Firefox via JSSh. JSSh # doesn't detect any javascript redirects so check it here. # If page redirects to itself that this code will enter in infinite loop. # So we currently don't wait for such a page. # wait variable in JSSh tells if we should wait more for the page to get loaded # or continue. -1 means page is not redirected. Anyother positive values means wait. =document_object.getElementsByTagName 'meta' wait_time=.to_array.map do || return_time=true return_time &&= .httpEquiv =~ /\Arefresh\z/i return_time &&= begin content_split=.content.split(';') content_split[1] && content_split[1] !~ /\A\s*url=#{Regexp.escape(url)}\s*\z/ # if there is no url, or if the url is the current url, it's just a reload, not a redirect; don't wait. end return_time ? content_split[0].to_i : nil end.compact.max if wait_time if wait_time > ([:timeout] - (Time.now - started)) # don't wait longer than what's left in the timeout would for any other timeout. raise "waiting for a meta refresh would take #{wait_time} seconds but remaining time before timeout is #{[:timeout] - (Time.now - started)} seconds - giving up" end sleep(wait_time) wait(:last_url => url, :timeout => [:timeout] - (Time.now - started)) end end ::Waiter.try_for([:timeout] - (Time.now - started), :exception => "Waiting for requests in progress to complete timed out.") do @requests_in_progress.length<=@browser_jssh_objects[:unmatched_stopped_requests_count] end run_error_checks return self end |