Watir-Classic 3.4.0 Released!

TauTropfenGerbera1

Hello everyone!

I’m happy to announce that Watir-Classic 3.4.0 has been released!

Put it into your Gemfile:

gem "watir-classic", "~> 3.4.0"

Or install it manually with:

gem install watir-classic

Biggest change is a complete documentation overhaul. Check it out at rubydoc.info/github/watir/watir-classic/frames

Other changes:

  • All deprecated methods will print out warnings.
  • Element#flash returns self instead of nil.
  • Fix frame locator in Frame#attach_command (issue #45).
  • Remove :zero_based_indexing option – from now on all index options are starting from zero.
  • Remove global variable $HIDE_IE – use IE.visible= method instead. Support for command line switch -b is also removed.
  • Remove global varialbe $FAST_SPEED – use IE.speed= method instead. Support for command line switch -f is also removed.
  • Remove IE#close_all – use browser.windows.each(&:close) instead.
  • Remove IE#close_modal – use browser.modal_dialog.close instead.
  • Remove IE#close_others – use browser.windows.reject(&:current?).each(&:close) instead.
  • Remove unused ie-new-process.rb.
  • Remove unused PageContainer module.
  • Remove unused PageContainer#check_for_http_error.
  • Remove unused PageContainer#enabled_popup – use browser.modal_dialog instead.

Watir-Classic 3.2.0 Released!

When Water Drops Collide

Hello everyone!

I’m happy to announce that Watir-Classic 3.2.0 has been released!

Changes:

  • Add Element#browser method as an alias for Element#page_container.
  • Fix SelectList#{select|clear} to fire onChange events for element.
  • Watir::Browser is now a class instead of a module – beware if you’re monkey-patching.

As usual:

Watir-Classic 3.1.0 Released!

Water Bomber

Hello everyone!

I’m happy to announce that another version of Watir-Classic has just been released – 3.1.0.

Changelog:

  • Add Browser#name, which returns :ie.
  • Add Dl#to_hash.
  • Add support for Alert API.
  • Add support for Browser#screenshot API.
  • Browser#execute_script returns now correct Ruby objects instead of String.
  • Browser#new accepts ignored parameter to make API more compatible with Watir-WebDriver.
  • Element#drag_and_drop methods work also with elements not in the viewport.
  • Fix TextField#set slow text entry.
  • Remove all show_* methods. Use element collection methods with #each instead. For example browser.links.each {|link| puts link.href}.
  • Remove already deprecated Watir::Waiter. Use Watir::Wait instead.
  • Remove already deprecated WinClicker.
  • Remove Browser#(javascript_)dialog. Use Browser#alert API instead.
  • Remove ScreenCapture module. Use Browser#screenshot API instead.
  • Remove Watir console. Use regular IRB or debugger instead.
  • Remove Watir.log method, WatirLogger and DefaultLogger classes. Use standard Ruby Logger instead.
  • Remove Watir.until_with_timeout. Use Watir::Wait.until instead.

Please try it out by executing:
gem install watir watir-classic

As usual:

Watir 3 Released!

Hello everyone!

I’m happy to announce that Watir 3 has been finally released!
Its biggest goal is to conform even better with WatirSpec making it more
compliant with Watir-WebDriver.

Changelog is quite long, but reading it makes your life easier:
* Browser#status returns an empty string if status bar is disabled in IE9
* Browser#style fixed for IE9
* #execute_script evaluates JavaScript code inside of an anonymous function
- use “return” statement if value is needed by Ruby
* #execute_script returns nil instead of ‘undefined’
* drag and drop fixed for IE9
* Window#current? and Window#== are more robust
* all html elements are now supported (even html5 ones)
* CookieManager removed
* cookies API support added (

https://github.com/watir/watirspec/blob/master/cookies_spec.rb)

* drag and drop API support added (

https://github.com/watir/watirspec/blob/master/drag_and_drop_spec.rb)

* Element#(before|after)? removed
* Element#(before|after)_text removed
* Browser#cell(s) and Browser#row(s) removed
* Browser#Element camelCase methods removed, use under_score methods instead
* Browser#element(s) supports only general attributes like :id, :title,
:class_name, :text, :html and such
* Browser#modal_dialog improved
* Browser#send_keys and Element#send_keys have now same syntax as specified
in WatirSpec
* Element#style returns internal styles only for IE9, inline style will be
returned for IE8
* Table#each removed – use Table#(trs|rows).each instead
* Table#row(s) and Table#cell(s) added which ignore inner tables – use
#td/#tr for all.
* raise an Exception if more locators are specified with :xpath/:css
* searching by :xpath and :css code rewritten
* Browser#textarea(s) method for searching elements
* Element#focus works with IE9
* Element#focused? returns the state of focus on that element
* Element#to_subtype returns Element if non-supported tag found instead of
crashing
* searching by :class will match now partially like other tools behave
(e.g. jQuery)
* Button#text returns value if exists instead of text
* Browser#goto prepends url automatically with http:// if scheme is missing
* Browser#element(s)_by_(xpath/css) are now private methods – use
#element(:css => …) and #element(:xpath => …) instead
* Browser#label supports searching by :for attribute
* Browser#options method for searching elements
* Browser#body, #thead, #tfoot, #tbody, #frameset and #fieldset added
* Browser#window and Browser#windows added implementing window switching
API (https://github.com/jarib/watirspec/blob/master/window_switching_spec.rb
)
* Element#present? returns false if exception is thrown by #exists? or
#visible?
* Element#style returns CSS text instead of OLE object
* Element#text returns an empty string for non-visible elements
* Element#parent returns correct instance of Element class (e.g. Div
instead of Element)
* Element#focus focuses document before focusing on the element
* Element#right_click and Element#double_click added
* Element#to_subtype added which returns specific instance of
Watir::Element subclass
* Element#send_keys added
* Element#eql? as an alias for Element#== added
* Element#tag_name added
* ElementCollection#[] method supports negative indexes like regular Arrays
* ElementCollection#[] returns always an object, even if the index is out
of bounds
* FileField#set and Image#save uses correct Windows file path (e.g. convert
“\”-es into “/”-es)
* FileField#set raises Errno::ENOENT instead of WatirException if file
doesn’t exist
* FileField#value= as an alias for FileField#set added
* Font#color, #face and #size added
* Form#submit triggers onSubmit event and doesn’t submit the form if
event’s callback returns false
* Frame#execute_script added
* Image#file_size, #height and #width return integer instead of a string
* Image#save blocking fixed
* Meta#content and #http_equiv added
* Option code rewritten, causing changes in its API
* SelectList code rewritten, causing changes in its API
* SelectList#(selected_)options returns now Options collection instead of
an array of strings
* Table and its subelements code rewritten, causing changes in its API
* Table#strings and #hashes added
* TextField#label added
* searching elements will find only correct types – e.g. using Browser#div
returns only DIV element even if all other provided selectors match
* all selectors and tag of the element needs to match even if searching by
:id
* supporting html5 data-* attributes by using :data_* for locating and
#data_* for retrieving attribute values
* many other internal changes

Please try it out by executing:
gem install watir

Facebook, Watir And Testing

Originally posted at itreallymatters.net by Jarmo Pertman.


I’ve known some time now that Facebook has been using Watir as their integration testing tool. Hell, there’s even a Facebook logo on the main page of watir.com. But today was a special day because i had to read one article about Facebook moving away from Watir.

Confusions

Since i’m one of the few core developers of Watir then this article made me notice statements which are not true or are just misleading. It seems to me that the author of that post doesn’t know the insights of Watir and other tools he’s mentioning or just uses wrong terminology by accident.

Watir & JavaScript

First statement which forced me to questioning myself was the following: “Watir automates the browser with JavaScript…”.

It took me some time before i understood that the author had FireWatir in his mind and not the Watir itself. FireWatir was used to automate Firefox browser and it truly used JavaScript as it’s engine to perform all the automations. Watir on the other hand controls Internet Explorer and uses it’s OLE interface instead to control the browser. This means in effect that there’s almost no JavaScript used in Watir.

Watir != Watir-WebDriver != WebDriver

The next statement causing confusion is: “The Watir we adopted in 2009 has since been improved, integrating a new protocol called WebDriver which allows you to automate the browser more accurately and with more power than could previously be done with straight JavaScript.”

First – Watir has been improved indeed when compared to year 2009 :) This is a good thing and a true statement. Second – Watir doesn’t integrate with the new protocol called WebDriver – it does still use OLE. I’m not exactly sure what the author means by the end of his statement about more accuracy and power. And of course – third – as mentioned already, Watir itself doesn’t use JavaScript and didn’t even do that in the year of 2009.

I think that you can call the WebDriver as a protocol, but the most famous implementation of that protocol is for sure Selenium-WebDriver aka Selenium 2. Watir-WebDriver is a library written on top of Selenium-WebDriver’s Ruby bindings. In other words it is an improved API over Selenium’s API. At least this is the way, we, Watir-loving people like to think. It does even have some API improvements which vanilla Watir doesn’t have yet. There is a project called WatirSpec, which is the specification for Watir’s API. Even Watir itself doesn’t conform to that yet. But the ultimate goal is to make Watir-WebDriver and Watir 100% compatible with each other. Latest releases of Watir have been moving towards that goal.

Abandoning Watir

And then i have to read the saddest statement of that article: “Once I understood all these factors, my course of action seemed clear: Abandon Watir, create a WebDriver client in PHP, and reuse our mature PHP unit test system for our browser tests. The WebDriver protocol was straightforward enough that I had a fully featured client in PHP by the end of a weekend’s work.”

On the one hand i’m happy that the engineers in the Facebook try to make things better – having the same technologies used between different projects is always a good thing. On the other hand i’m not sure i understand as to why they had to create a new PHP WebDriver bindings. Looking from the main page of Selenium 2 i can see that there’s already two seemingly active projects doing just that – php-webdriver-bindings and WebDriver-PHP. Maybe engineers at Facebook had good reasons why not to use something already existing. Maybe they just like to feel more challenged and want to invent few bicycles in a while. I don’t know.

Conclusion

After all it was an interesting read. Since i’ve used Watir about 4 years now then it’s nice to read that someone else had similar or completely different solutions to the same problems. I like the thing about Facebook that it tries to be more open to the world when it comes to the topics of the tools and processes used to make, maintain and release such a widely used product.

On the other hand, posts having false information in them tend to have a strong effect on people using the tools under fire. Especially if this kind of information is originating from a trustworthy source. From that post it seems that it is time to abandon Watir since it is too old and not developed anymore. That’s just plain wrong. Watir is still actively developed and one of the biggest reasons why not to abandon Watir at this moment is that it is still the best automation tool for Internet Explorer. Watir-WebDriver’s IE driver is just not mature enough. Sorry, WebDriver guys. I would be happy to run all my tests with Watir-WebDriver since that would give me an opportunity to test with different browsers, but as long as IE is not working properly, then i just can’t do that. Since IE is the brittlest and still most used browser, then testing with that browser just seems to be mandatory.

I have to agree that if the person is not tied with all or some of these projects on a daily basis then it is hard to understand the difference between Watir, Watir-WebDriver and WebDriver. Maybe the biggest problem is just that the topics aren’t documented enough?

Watir 2.0

number 2

Watir 2.0

Recently, Watir 2.0 got released! This post will try to explain all the important changes what this version brought to the automated testing world.

About FireWatir

Old Hand Made Whiskey Bottle

There is no FireWatir 2.0 and there won’t be any new releases of FireWatir anymore due to the fact that JSSH extension, which is used to control Firefox by FireWatir, is not available for Firefox versions 4 and newer. This means that we’ve decided that it’s time for the FireWatir to retire. We’ve released a version 1.9.3 which doesn’t have any new functionality, but has a less strict dependency requirement for common-watir gem so you could use Watir 2.0 and FireWatir 1.9.3 together in your Bundler’s Gemfile if really needed. We recommend you to start using Watir-WebDriver Firefox driver instead if you want to test your application on Firefox.

Zero based indexing

10

The next big change is zero based indexing. As you might know then Watir has used one based indexing so far. For example, if you are using Watir 1.x and you’d like to access first div element on the page, you’d write code like this:

browser.div(:index => 1)

In Watir 2.0 and newer, you have to write code like this instead:

browser.div(:index => 0)

That change is done to be more compatible with Watir-WebDriver and the Ruby (and many other) programming language itself. For example, the first element in the array has an index of 0. That’s it, no more remembering if the indexing started from 0 or 1 in Watir. It’s consistently 0. This also applies to tables, rows and cells:

table = browser.table(:class => "sometable")
# will get the first row
first_row = table[0]
# will get the first cell
first_cell = first_row[0]

You can revert to one-based-indexing to make the integration from Watir 1.x to Watir 2.0 easier and faster for your existing tests by using a special option:

require "watir"
Watir.options[:zero_based_indexing] = false

Remember that this option will be probably removed in the not-too-soon-future, so you’d better edit your tests to start working with zero-based-indexing. I’m pretty sure you want to do that since starting from now Watir will become more and more compatible with Watir-WebDriver.

Multiple locators

Starting from Watir 2.0 ALL elements support multiple locators for searching. Even browser#element. In case you don’t know what this feature is, then here is an example for searching for the span element with a specific name AND class:

# only span with name "something" AND class "else" will be found
browser.span(:name => "something", :class => "else")

You can also search all elements by :xpath and :css locators now, but please remember that these are considerably slower than any other locators.

Locators for collections

When you were dealing with element collections in Watir 1.x then you had to use Ruby’s Enumerable methods for filtering out elements with specific criteria. Let’s say that we’re interested only in the images, which have a name of "logo":

browser.images.find_all {|image| image.name == "logo"}.each do |image|
# only images with the name of "logo" will print out their html
puts image.html
end

In Watir 2.0 you can also specify locators for the collections methods so it’s a lot easier to filter out the elements in interest. The above example in Watir 2.0 would be:

browser.images(:name => "logo").each do |image|
puts image.html
end

Of course you can use multiple locators for the collection methods too!

Default locator

Have you done something like this in your tests:

browser.span(:class => "something").div(:index => 1).span(:class => "else")

Notice the usage of :index => 1 to specify that the span with class "else" should be inside of the first div. In Watir 2.0 you can use the syntax below instead:

browser.span(:class => "something").div.span(:class => "else")

In other words – if no other locators are specified, then :index => 0 will be used as a default. Convenient, eh?

Aliased methods

Have you typed browser.tr instead of browser.row? What about browser.td instead of browser.cell? Since most of the html elements are accessible by the same method name as their tag then it just makes sense to have methods for these elements too. In Watir 2.0 you can use #tr, #trs, #td, #tds, #a, #as, #img and #imgs! Consistency is good!

Conclusion

Watir 2.0 tries to be the best “driver” for IE browser by adding all these missing features and incompatibilities between Watir-WebDriver. Our goal is to minimize that gap even further. Stay tuned for future releases!

Testing webpages with JavaScript popups correctly

Originally posted at itreallymatters.net by Jarmo Pertman.


JavaScript Pop Up

Usually when a JavaScript dialog pops up at some webpage then there is a highly possibility that it shouldn’t be there in the first place. It adds just more inconvenience to any user when needing to perform an additional click to get rid of some pointless message. If possible then solve the problem by removing those pointless usability mishaps altogether!

If there indeed exists some actual need of having a dialog window – perhaps the user is confirmed about starting a nuclear war and there’s no sufficient possibility to undo that action – then it’s needed to deal with those popups during automated testing. If the testing tool doesn’t support this types of obstacles then I’m recommending to ditch that tool and choosing something else. For Watir there are a number of possibilities to handle these dialogs, one more complex than another.

But there exists a very easy and elegant way to handle the JavaScript dialogs also. For some reason this technique hasn’t been recommended much before in Watir’s community until Alister Scott wrote about it in his blog. The main idea is to override the JavaScript dialog functions.

I’m writing my own blog post on that topic because I don’t agree with everything Alister has written. He’s recommending to override the functions to return true, but i don’t think that this is a correct way to do. Main reason for my thoughts is that it’s just not simulating the real functions properly. In real scenario, alert returns true in Firefox and undefined in IE. It doesn’t matter though since no-one is using return value of an alert for any functionality, right? At least i hope so. But it’s different altogether for prompt and confirm! Check out the following output from JavaScript console:

>>prompt("enter!")
"info"
>>prompt("cancel!")
null
>>confirm("yes!")
true
>>confirm("no!")
false

gist.github.com/663313#file_console.js

As you can see then if user enters anything into the prompt’s text field then that value is returned from the function and if he decides to click on a Cancel instead then null is returned. For the confirm, true was returned when “OK” was clicked and false otherwise.

Since both of the confirm and prompt might return different values then these values might be used in web pages for different functionality. This means that they should be simulated to work in both ways also in tests. Instead of returning true all the time, a different values should be returned as needed:

# don't return anything for alert
browser.execute_script("window.alert = function() {}")

# return some string for prompt to simulate user entering it
browser.execute_script("window.prompt = function() {return 'my name'}")

# return null for prompt to simulate clicking Cancel
browser.execute_script("window.prompt = function() {return null}")

# return true for confirm to simulate clicking OK
browser.execute_script("window.confirm = function() {return true}")

# return false for confirm to simulate clicking Cancel
browser.execute_script("window.confirm = function() {return false}")

gist.github.com/663313#file_dialogs.rb

This code works with Watir, but not for FireWatir for some reason. I’m suspecting that FireWatir’s JavaScript execution doesn’t happen in the same scope as the page under test. This same technique might work with any testing tool that allows to execute JavaScript on the page. You’d just have to perform execute_script right before interacting with an element which triggers the dialog.

Since Watir-Webdriver returns the executed JavaScript back to the Ruby then it allows for even cooler solutions where you can verify that an alert was shown indeed. For the prompt and confirm, the actual behavior of the web page itself should be enough for verification.

Hopefully next time if you happen to see any JavaScript dialog, you remember that it’s possible to get rid of them very easily.

Debugging and Improving Watir’s click_no_wait Method

Originally posted at itreallymatters.net by Jarmo Pertman.


I’ve written about debugging Watir’s click_no_wait method problems before. This time i’m gonna do it again because starting from Watir 1.6.6 the #click_no_wait method itself has changed along with the way to debug it’s problems.

In this post i’m gonna also write more about the inner-workings of #click_no_wait and the changes made to it in Watir 1.6.6.

There was mainly 3 motivations to change #click_no_wait:

  • Make it faster!
  • Make it easier to debug!
  • Make the code itself cleaner and better!

Making it Faster

Before going into the dirty details how it became faster i’m gonna give a short overview how it was working before the changes. The main parts of the #click_no_wait were the following methods:

# watir/element.rb
def click_no_wait
  assert_enabled

  highlight(:set)
  object = "#{self.class}.new(self, :unique_number, #{self.unique_number})"
  @page_container.eval_in_spawned_process(object + ".click!")
  highlight(:clear)
end

# watir/page-container.rb
def eval_in_spawned_process(command)
  command.strip!
  load_path_code = _code_that_copies_readonly_array($LOAD_PATH, '$LOAD_PATH')
  ruby_code = "require 'watir/ie'; "
  ruby_code << "pc = #{attach_command}; " # pc = page container
  ruby_code << "pc.instance_eval(#{command.inspect})"
  exec_string = "start rubyw -e #{(load_path_code + '; ' + ruby_code).inspect}"
  system(exec_string)
end

# watir/ie.rb
def _code_that_copies_readonly_array(array, name)
  "temp = Array.new(#{array.inspect}); #{name}.clear; temp.each {|element| #{name} << element}"
end

gist.github.com/634798#file_click_no_wait.rb

The main entrypoint is of course the #click_no_wait method itself which executes #eval_in_spawned_process in page-container. That in turn runs start rubyw with a system execution in a separate Ruby process where all the dirty work is done. The job consists of the following components:

  • Loading Watir;
  • Attaching to the browser window;
  • Locating the element with an unique identifier and performing clicking on it.

The most time consuming part is not directly visible from the code above, but it was a require statement for watir/ie. This require statement triggered loading of everything in Watir. Even the things which are never needed in the “limited sandbox” of #click_no_wait. If you think of it then only core of Watir’s features are needed there to attach to the browser, locate the element and perform click on it. Every other advanced feature is not possible to use by #click_no_wait! Attaching to the browser, locating the element and performing click on it is pretty fast.

I inspected watir/ie.rb file and started to pick out all the require statements which might be needed in that sandbox. I ended up creating a separate file called watir/core.rb where only necessary files would be loaded. The file itself is loaded also by watir/ie.rb so everything would be available if using Watir normally. In other words, core.rb is a subset of files needed by Watir. This change itself made #click_no_wait to perform 2-3 times faster on my machine! That was enough for the time.

Making it Easier to Debug

As also written in the previous post then the fact that everything is done in a separate Ruby process is giving the feature of not blocking, but taking away the advantage of seeing any errors on the console window as you’d normally expect. This means that usually nothing is clicked and nothing is shown on the console in case of some problem. Using debugger would not help much either since the problem itself was happening on a spawned Ruby process with no visible output on the screen (yes, you could have set a breakpoint to Element#click!, but that wouldn’t have helped much if the error occurred before getting to that point). Also, for trying to change anything to happen differently in that spawned process with monkey-patching would have involved of overriding the whole contents of #eval_in_spawned_process_method. Not a nice way to solve problems, i’d say.

I wanted to achieve some possibility to debug these problems easily without any need of using debugger or monkey-patches. I wanted to use regular Ruby’s $DEBUG variable. To achieve that i extracted the command, which is given to the system method into separate method which would return a little bit different command depending of the value of $DEBUG:

def click_no_wait
  # ...
  system(spawned_click_no_wait_command(ruby_code))
end

def spawned_click_no_wait_command(command)
  command = "-e #{command.inspect}"
  unless $DEBUG
    "start rubyw #{command}"
  else
    puts "#click_no_wait command:"
    command = "ruby #{command}"
    puts command
    command
  end
end

gist.github.com/634798#file_click_no_wait_debug.rb

If $DEBUG is set to false (which is the default case) then #click_no_wait works as usual, but if it’s set to true then it will output the executed command itself and will wait for the spawned Ruby process to exit so it’s possible to see all the error messages if any.

This approach also gives the opportunity to monkey-patch the executed command, which in turn allows to write some tests for the method itself.

To make it plain and clear then this is the way to turn on debugging for #click_no_wait:

$DEBUG = true
browser.button(:id => "something").click_no_wait

gist.github.com/634798#file_click_no_wait_debug_on.rb

Making the Code Itself Cleaner and Better

The original code had some commented out code and over-generalisation. There were instance_eval’s and all other neat tricks which were not needed at all. The most cumbersome was the method called _code_that_copies_readonly_array defined in the global scope with a slightly funny comment – “why won’t this work when placed in the module (where it properly belongs)” – i even tried to move that method into the module where it actually worked. A valid case of comments getting out of sync? The change allowed to delete that method entirely and not use instance_eval and friends to make whole code more understandable. The resulting code is like this:

def click_no_wait
  assert_exists
  assert_enabled
  highlight(:set)
  element = "#{self.class}.new(#{@page_container.attach_command}, :unique_number, #{self.unique_number})"
  ruby_code = "require 'rubygems';" <<
          "require '#{File.expand_path(File.dirname(__FILE__))}/core';" <<
          "#{element}.click!"
  system(spawned_click_no_wait_command(ruby_code))
  highlight(:clear)
end

gist.github.com/634798#file_click_no_wait_refactored.rb

Of course in the end it is all just a matter of taste. There is only one small problem with this code – usage of Rubygems. It is in my pipeline to remove it’s usage without making code look much uglier (there’s no way i’m gonna add back that _code_that_copies… method!) and making #click_no_wait even faster.

Taking into the consideration the fact that these changes involved changing core code then i’m quite happy that they got released into the wild with only one (known) bug!