Watir 7.0 Beta 2

Written by: Titus Fortner on March 26, 2021

Watir 7.0.0.beta2 is now available on RubyGems. This is all the additions and optimizations that were dependent on removing the deprecated code in Beta 1. Watir Repo now has zero outstanding bugs! The Issues list contains 2 optimizations and 2 feature requests which we may or may not get to before Watir 7.0 is released. Expect production release of Watir 7.0 as soon as Selenium 4.0 is released.

To install:

gem install watir --pre

or in your Gemfile:

gem "watir", ">= 7.0.0.beta2"

Setting Values on a Page

One of the coolest features implemented by Page Object gems is the ability to use Watir to automatically fill out a form based on Element type. This is an example of what it looks like with Watir 6
in WatirDrops:

  case watir_element
  when Watir::Radio
    watir_element.set if val
  when Watir::CheckBox
    val ? watir_element.set : watir_element.clear
  when Watir::Select
    watir_element.select val
  when Watir::Button
    watir_element.click
  when Watir::TextField, Watir::TextArea
    watir_element.set val if val
  else
    watir_element.click if val
  end

Some take true or false, some take String or Regexp or even Array.

It makes more sense for Watir to create a standard interface for this interaction than to require Page Object gems to implement it. The #set method was originally intended for this role, but determining how the arguments would be used was never fully implemented.

This release simplifies all of that by baking it into #set. The above code can now be implemented with:

  watir_element.set val

Even more interesting, there is a generic Element#set method. You don’t even have to specify the element subclass any more. If you have a generic Watir::Element that matches <input type="checkbox" id="checky" />, calling #set on it with true value, will now automatically determine that it is actually a CheckBox element and will ensure that it is selected (based on the true input). Obviously, it is better and more efficient for the user to set it, but it is no longer required.

More Select Lists

Watir 6 had two methods for selecting options. Select#select would select options based on text or label and Select#select_value would select options based on value. The code was also a little messy because we assumed everything might be a multiple select list, which impacted performance a bit.

The first fix was to combine selecting by text, label and value into the #select method. This allows us to have the single common interface aliased to #set (as described in previous section), and the likelihood of the value of one option matching the text of another option is relatively small, but more on this below.

To deal with multiple select lists, we first decided to have people use the short-lived Select#select_all method. Except this moved us away from the single common interface for all inputs that we want. Independently, we decided to support passing in an Array instance to #select as a way to indicate that multiple values should be selected, and it just made sense to remove #select_all in favor of toggling multiple select list behavior based on whether the argument received is an Array. So if you have a multiple select list and want to match multiple options with one command, put it in an Array.

browser.goto 'watir.com/examples/simple_form.html'

country_dropdown = browser.select(id: 'languages')
country_dropdown.select [/an/] # An Array, so only first matching selected
country_dropdown.selected?('1') # => true
country_dropdown.selected?('3') # => true

If there is an issue with the value being passed in matching on a value or a text item that you did not intend, you can now be explicit about what gets matched.

browser.goto 'watir.com/examples/simple_form.html'

country_dropdown = browser.select(id: 'country')
country_dropdown.select(text: 'Denmark')
country_dropdown.selected?('1') # => true
country_dropdown.select(value: '2')
country_dropdown.selected?('Norway') # => true
country_dropdown.select(label: 'Sverige')
country_dropdown.selected?('Sweden') # => true

Finally, we added the ability to check if an option is selected in the same manner that we are selecting it, so now :value is supported in addition to :text and :label

For everything about working with Select Lists, read our Dropdown Elements Guide

Selenium Support Classes

Alex implemented two non-automation-specific features for Selenium (Logger and Guards) that are being used by Watir. Maybe these will eventually be put into their own gems.

In Watir 6.6 we pretty much just copy/pasted the Logger implementation from Selenium and then added things to it. The Selenium Logger was updated in v4 to include all of the Watir functionality, and allows other projects to extend it.

WatirSpec::Guards has been a part of the WatirSpec project from the beginning (when Jari created them in 2009), and was based on code in rubyspec. They are very powerful and allow executing or not executing pretty much any block of code in the specs. Unfortunately, it was extremely challenging to keep the watirspecs updated as bugs were fixed and w3c capabilities were implemented by different browsers. Selenium Guards are tied into RSpec metadata. Rather than running or not running blocks of code, each spec has a single set of guards. The killer feature is that guarded code will execute as pending, so if the bug has been fixed the test will fail and we can update everything accordingly.

See the Changelog for the complete history of updates.

Tags:

Thoughts about this article? Let us know!