Created
September 16, 2009 09:00
-
-
Save tobiashm/187941 to your computer and use it in GitHub Desktop.
useful extensions to FireWatir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
require 'firewatir' | |
require 'iconv' | |
$KCODE = 'u' | |
# useful extension to FireWatir | |
class Element | |
# http://docs.jquery.com/Release:jQuery_1.3.2#:visible.2F:hidden_Overhauled | |
def visible? | |
assert_exists | |
real_width = js_eval_method("offsetWidth").to_i | |
real_height = js_eval_method("offsetHeight").to_i | |
real_width > 0 and real_height > 0 | |
end | |
# This will return true if any part - but not necessary all - of the element is within the viewport. | |
# Also checks thet the element is not hidden behind another element. | |
def in_viewport? | |
return false unless visible? | |
in_viewport = "(function() { | |
var h = #{DOCUMENT_VAR}.documentElement.clientHeight; | |
var w = #{DOCUMENT_VAR}.documentElement.clientWidth; | |
var rects = #{element_object}.getClientRects(); | |
var on_top = function(r) { | |
for (var x = Math.floor(r.left), x_max = Math.ceil(r.right); x <= x_max; x++) | |
for (var y = Math.floor(r.top), y_max = Math.ceil(r.bottom); y <= y_max; y++) { | |
if (document.elementFromPoint(x, y) == #{element_object}) return true; | |
} | |
return false; | |
}; | |
return Array.prototype.some.call(rects, function(r) { | |
var within = (r.top > 0 ? r.top <= h : r.bottom > 0) && (r.left > 0 ? r.left <= w : r.right > 0); | |
return within && on_top(r); | |
}); | |
})()" | |
js_eval(in_viewport) == "true" | |
end | |
# modified to allow xpath to be relaitve to the container element | |
def element_by_xpath(container, xpath) | |
element_id = "element_xpath_#{rand(1000)}" # WTF: This can not be expected to be unique! | |
context_node = (@container.class == FireWatir::Firefox || @container.class == Frame) ? DOCUMENT_VAR : @container.element_name | |
jssh_command = "var #{element_id} = null; #{element_id} = #{DOCUMENT_VAR}.evaluate(\"#{xpath}\", #{context_node}, null, #{FIRST_ORDERED_NODE_TYPE}, null).singleNodeValue; #{element_id};" | |
jssh_socket.send("#{jssh_command}\n", 0) | |
result = read_socket() | |
if (result == "null" || result == "" || result.include?("exception")) | |
@@current_level = 0 | |
return nil | |
else | |
@@current_level += 1 | |
return element_id | |
end | |
end | |
end | |
class ElementCollections | |
def first | |
self[1] | |
end | |
def last | |
self[length] | |
end | |
def rand | |
self[rand(length) + 1] if length > 0 | |
end | |
end | |
module FireWatir | |
class Firefox | |
# | |
# Description: | |
# Resize the current browser window. | |
# | |
def resize(width=1024, height=738) | |
$jssh_socket.send("#{WINDOW_VAR}.resizeTo(#{width}, #{height});\n", 0) | |
read_socket() | |
end | |
# Wait for active Ajax (xml-http requests and jQuery animation/timers) operations | |
def wait_for_ajax | |
wait | |
wait_for_condition "(function($){return $.active == 0 && $.timers.length == 0;})(#{BROWSER_VAR}.contentWindow.jQuery)" | |
end | |
private | |
def wait_for_condition(condition, times = 20, seconds = 0.2) | |
result = lambda { js_eval(condition) == "true" } | |
until result.call or times == 0 do | |
puts "waiting for js condition (#{times})..." if $DEBUG | |
sleep(seconds) | |
times -= 1 | |
end | |
result.call | |
end | |
end | |
class InputElement | |
def submit_form | |
assert_exists | |
js_eval_method("form.submit()") | |
@o.wait | |
end | |
end | |
class TextField | |
private | |
# Override doKeyPress to handle UTF-8 (multibyte) strings | |
alias_method :doKeyPress_without_mb, :doKeyPress | |
def doKeyPress(value) | |
value = value.mb_chars | |
doKeyPress_without_mb(value) | |
end | |
end | |
# Defining missing element types that we are using in some documents | |
class B < NonControlElement; TAG = 'B'; end | |
class Bs < ElementCollections; end | |
end | |
# While our featur files are UTF-8 encoded, the internal js representation in | |
# Firefox seems to be in Latin-1. So we need to convert the byte stream before | |
# sending it through jssh. For some reason, the response seems to have been | |
# converet to UTF-8, so that's fine. | |
class TCPSocket | |
def send(what, flags) | |
what = Iconv.conv("L1", "UTF-8", what) | |
super # in Socket | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment