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(/&nbsp;/, '&#160;') - 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(/&/,'&amp;') - str = str.gsub(/</,'&lt;') - str = str.gsub(/>/,'&gt;') - str = str.gsub(/"/, '&quot;') - 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