Skip to content

Instantly share code, notes, and snippets.

@tobiashm
Created September 16, 2009 09:00
Show Gist options
  • Save tobiashm/187941 to your computer and use it in GitHub Desktop.
Save tobiashm/187941 to your computer and use it in GitHub Desktop.
useful extensions to FireWatir
# 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