lib/watir/ie-class.rb in watir-3.0.0.rc2 vs lib/watir/ie-class.rb in watir-3.0.0.rc3
- old
+ new
@@ -66,15 +66,10 @@
READYSTATES = {:complete => 4}
# The default color for highlighting objects as they are accessed.
HIGHLIGHT_COLOR = 'yellow'
- # IE inserts some element whose tagName is empty and just acts as block level element
- # Probably some IE method of cleaning things
- # To pass the same to the xml parser we need to give some name to empty tagName
- EMPTY_TAG_NAME = "DUMMY"
-
# The time, in seconds, it took for the new page to load after executing the
# the last command
attr_reader :down_load_time
# the OLE Internet Explorer object
@@ -359,17 +354,10 @@
# Return the title of the document
def title
@ie.document.title
end
- # The document standards mode used by IE
- # can be overridden in the html with: <meta http-equiv="x-ua-compatible" content="IE=8">
- def document_mode
- @ie.document.documentMode.to_i
- end
-
-
# Return the status of the window, typically from the status bar at the bottom.
def status
return @ie.statusText
end
@@ -409,21 +397,10 @@
def inspect
'#<%s:0x%x url=%s title=%s>' % [self.class, hash*2, url.inspect, title.inspect]
end
- # Execute the given JavaScript string
- def execute_script(source)
- document.parentWindow.eval(source.to_s)
- rescue WIN32OLERuntimeError, NoMethodError #if eval fails we need to use execScript(source.to_s) which does not return a value, hence the workaround
- escaped_src = source.to_s.gsub(/[\r\n']/) {|m| "\\#{m}"}
- wrapper = "_watir_helper_div_#{rand(100000)}"
- cmd = "var e = document.createElement('DIV'); e.style.display='none'; e.id='#{wrapper}'; e.innerHTML = eval('#{escaped_src}'); document.body.appendChild(e);"
- document.parentWindow.execScript(cmd)
- document.getElementById(wrapper).innerHTML
- end
-
# clear the list of urls that we have visited
def clear_url_list
@url_list.clear
end
@@ -432,15 +409,15 @@
return unless exists?
@ie.stop
wait rescue nil
chwnd = @ie.hwnd.to_i
@ie.quit
- t = Time.now
+ t = ::Time.now
while exists?
# just in case to avoid possible endless loop if failing to close some
# window or tab
- break if Time.now - t > 10
+ break if ::Time.now - t > 10
sleep 0.3
end
end
# Maximize the window (expands to fill the screen)
@@ -490,12 +467,12 @@
# browser.send_keys("Hello World{enter}")
#
# Refer to RAutomation::Adapter::WinFfi::KeystrokeConverter.convert_special_characters for
# special characters conversion.
# @see RAutomation::Window#send_keys
- def send_keys(key_string)
- rautomation.send_keys key_string
+ def send_keys(*keys)
+ rautomation.send_keys *keys
end
def dir
return File.expand_path(File.dirname(__FILE__))
end
@@ -512,20 +489,24 @@
# returns the current url, as displayed in the address bar of the browser
def url
return @ie.LocationURL
end
- def window(how={}, &blk)
- win = Window.new(self, how, &blk)
+ def window(specifiers={}, &blk)
+ win = Window.new(self, specifiers, &blk)
win.use &blk if blk
win
end
- def windows(how={}, &blk)
- self.class._find_all(how.keys.first, how.values.first).map {|ie| Window.new(self, how, IE.bind(ie), &blk)}
+ def windows(specifiers={}, &blk)
+ self.class._find_all(specifiers.keys.first, specifiers.values.first).map {|ie| Window.new(self, specifiers, IE.bind(ie), &blk)}
end
+ def cookies
+ Cookies.new(self)
+ end
+
#
# Synchronization
#
# Block execution until the page has loaded.
@@ -536,11 +517,11 @@
# any moment!
def wait(no_sleep=false)
@xml_parser_doc = nil
@down_load_time = 0.0
interval = 0.05
- start_load_time = Time.now
+ start_load_time = ::Time.now
Timeout::timeout(5*60) do
begin
while @ie.busy
sleep interval
@@ -554,11 +535,11 @@
sleep interval
end
documents_to_wait_for = [@ie.document]
rescue WIN32OLERuntimeError # IE window must have been closed
- @down_load_time = Time.now - start_load_time
+ @down_load_time = ::Time.now - start_load_time
return @down_load_time
end
while doc = documents_to_wait_for.shift
begin
@@ -575,11 +556,11 @@
rescue WIN32OLERuntimeError
end
end
end
- @down_load_time = Time.now - start_load_time
+ @down_load_time = ::Time.now - start_load_time
run_error_checks
sleep @pause_after_wait unless no_sleep
@down_load_time
end
@@ -749,19 +730,15 @@
end
end
# Gives focus to the frame
def focus
- document.activeElement.blur
+ active_element = document.activeElement
+ active_element.blur unless active_element.tagName == "BODY"
document.focus
end
- # Functions written for using xpath for getting the elements.
- def xmlparser_document_object
- @xml_parser_doc ||= create_xml_parser_doc
- end
-
def attach_command
"Watir::IE.attach(:hwnd, #{hwnd})"
end
private
@@ -780,276 +757,9 @@
rescue Watir::Wait::TimeoutError
raise NoMatchingWindowFoundException,
"Unable to locate a window with #{how} of #{what}"
end
@ie = ieTemp
- end
-
- # Create the Nokogiri object if it is nil. This method is private so can be called only
- # from xmlparser_document_object method.
- def create_xml_parser_doc
- require 'nokogiri'
- if @xml_parser_doc == nil
- htmlSource ="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<HTML>\n"
- htmlSource = html_source(document.body,htmlSource," ")
- htmlSource += "\n</HTML>\n"
- # Angrez: Resolving Jira issue WTR-114
- htmlSource = htmlSource.gsub(/ /, ' ')
- begin
- @xml_parser_doc = Nokogiri.parse(htmlSource)
- rescue => e
- output_xml_parser_doc("error.xml", htmlSource)
- raise e
- end
- end
- end
-
- def output_xml_parser_doc(name, text)
- file = File.open(name,"w")
- file.print(text)
- file.close
- end
-
- #Function Tokenizes the tag line and returns array of tokens.
- #Token could be either tagName or "=" or attribute name or attribute value
- #Attribute value could be either quoted string or single word
- def tokenize_tagline(outerHtml)
- outerHtml = outerHtml.gsub(/\n|\r/," ")
- #removing "< symbol", opening of current tag
- outerHtml =~ /^\s*<(.*)$/
- outerHtml = $1
- tokens = Array.new
- i = startOffset = 0
- length = outerHtml.length
- #puts outerHtml
- parsingValue = false
- while i < length do
- i +=1 while (i < length && outerHtml[i,1] =~ /\s/)
- next if i == length
- currentToken = outerHtml[i,1]
-
- #Either current tag has been closed or user has not closed the tag >
- # and we have received the opening of next element
- break if currentToken =~ /<|>/
-
- #parse quoted value
- if(currentToken == "\"" || currentToken == "'")
- parsingValue = false
- quote = currentToken
- startOffset = i
- i += 1
- i += 1 while (i < length && (outerHtml[i,1] != quote || outerHtml[i-1,1] == "\\"))
- if i == length
- tokens.push quote + outerHtml[startOffset..i-1]
- else
- tokens.push outerHtml[startOffset..i]
- end
- elsif currentToken == "="
- tokens.push "="
- parsingValue = true
- else
- startOffset = i
- i += 1 while (i < length && !(outerHtml[i,1] =~ /\s|=|<|>/)) if !parsingValue
- i += 1 while (i < length && !(outerHtml[i,1] =~ /\s|<|>/)) if parsingValue
- parsingValue = false
- i -= 1
- tokens.push outerHtml[startOffset..i]
- end
- i += 1
- end
- return tokens
- end
-
- # This function get and clean all the attributes of the tag.
- def all_tag_attributes(outerHtml)
- tokens = tokenize_tagline(outerHtml)
- #puts tokens
- tagLine = ""
- count = 1
- tokensLength = tokens.length
- expectedEqualityOP= false
- while count < tokensLength do
- if expectedEqualityOP == false
- #print Attribute Name
- # If attribute name is valid. Refer: http://www.w3.org/TR/REC-xml/#NT-Name
- if tokens[count] =~ /^(\w|_|:)(.*)$/
- tagLine += " #{tokens[count]}"
- expectedEqualityOP = true
- end
- elsif tokens[count] == "="
- count += 1
- if count == tokensLength
- tagLine += "=\"\""
- elsif(tokens[count][0,1] == "\"" || tokens[count][0,1] == "'")
- tagLine += "=#{tokens[count]}"
- else
- tagLine += "=\"#{tokens[count]}\""
- end
- expectedEqualityOP = false
- else
- #Opps! equality was expected but its not there.
- #Set value same as the attribute name e.g. selected="selected"
- tagLine += "=\"#{tokens[count-1]}\""
- expectedEqualityOP = false
- next
- end
- count += 1
- end
- tagLine += "=\"#{tokens[count-1]}\" " if expectedEqualityOP == true
- #puts tagLine
- return tagLine
- end
-
- # This function is used to escape the characters that are not valid XML data.
- def xml_escape(str)
- str = str.gsub(/&/,'&')
- str = str.gsub(/</,'<')
- str = str.gsub(/>/,'>')
- str = str.gsub(/"/, '"')
- str
- end
-
- # Returns HTML Source
- # Traverse the DOM tree rooted at body element
- # and generate the HTML source.
- # element: Represent Current element
- # htmlString:HTML Source
- # spaces:(Used for debugging). Helps in indentation
- def html_source(element, htmlString, spaceString)
- begin
- tagLine = ""
- outerHtml = ""
- tagName = ""
- begin
- tagName = element.tagName.downcase
- tagName = EMPTY_TAG_NAME if tagName == ""
- # If tag is a mismatched tag.
- if !(tagName =~ /^(\w|_|:)(.*)$/)
- return htmlString
- end
- rescue
- #handling text nodes
- if element.toString(0) == '[object Text]' #IE9 has a different method for getting text
- element_text = element.wholeText
- else
- element_text = element.toString(0)
- end
- htmlString += xml_escape(element_text)
- return htmlString
- end
- #Skip comment and script tag
- if tagName =~ /^!/ || tagName== "script" || tagName =="style"
- return htmlString
- end
- #tagLine += spaceString
- outerHtml = all_tag_attributes(element.outerHtml) if tagName != EMPTY_TAG_NAME
- tagLine += "<#{tagName} #{outerHtml}"
-
- canHaveChildren = element.canHaveChildren
- if canHaveChildren
- tagLine += ">"
- else
- tagLine += "/>" #self closing tag
- end
- #spaceString += spaceString
- htmlString += tagLine
- childElements = element.childnodes
- childElements.each do |child|
- htmlString = html_source(child,htmlString,spaceString)
- end
- if canHaveChildren
- #tagLine += spaceString
- tagLine ="</" + tagName + ">"
- htmlString += tagLine
- end
- return htmlString
- rescue => e
- puts e.to_s
- end
- return htmlString
- end
-
- # Method that iterates over IE DOM object and get the elements for the given
- # xpath.
- def element_by_absolute_xpath(xpath)
- curElem = nil
- xpath = xpath.scan(/^.*\/body\[?\d*\]?\/(.*)/).flatten.first
- return unless xpath
-
- arr = xpath.split("/")
- return nil if arr.length == 0
-
- doc = document
- curElem = doc.getElementsByTagName("body").item(0)
- lastTagName = arr.last.to_s.upcase
-
- # lastTagName is like tagName[number] or just tagName. For the first case we need to
- # separate tagName and number.
- lastTagName = lastTagName.scan(/(\w*)\[?\d*\]?/).flatten.first
-
- arr.each do |element|
- element =~ /(\w*)\[?(\d*)\]?/
- tagname = $1
- tagname = tagname.upcase
-
- if $2 != nil && $2 != ""
- index = $2
- index = "#{index}".to_i - 1
- else
- index = 0
- end
-
- allElemns = tagname == "FRAME" ? [curElem] : curElem.childnodes
- next if allElemns == nil || allElemns.length == 0
-
- allElemns.each do |child|
- begin
- curTag = child.tagName
- curTag = EMPTY_TAG_NAME if curTag.empty?
- rescue
- next
- end
-
- if curTag == tagname
- index -= 1
- if index < 0
- curElem = child
- break
- end
- end
- end
- end
-
- curElem.tagName == lastTagName ? curElem : nil rescue nil
- end
-
- # execute css selector and return an array of (ole object) elements
- def elements_by_css(selector)
- xmlparser_document_object # Needed to ensure Nokogiri has been loaded
- xpath = Nokogiri::CSS.xpath_for(selector)[0]
- elements_by_xpath(xpath)
- end
-
- # return the first (ole object) element that matches the css selector
- def element_by_css(selector)
- elements_by_css(selector)[0]
- end
-
- # return the first element that matches the xpath
- def element_by_xpath(xpath)
- elements_by_xpath(xpath)[0]
- end
-
- # execute xpath and return an array of elements
- def elements_by_xpath(xpath)
- doc = xmlparser_document_object
-
- # strip any trailing slash from the xpath expression (as used in watir unit tests)
- xpath.chop! if xpath =~ /\/$/
-
- doc.xpath(xpath).reduce([]) do |memo, element|
- memo << element_by_absolute_xpath(element.path)
- end.compact
end
end # class IE
end