Automating Windows and Their Controls With Ruby

Update: added part about handling popups.

How would you automate windows and their controls like button and text fields if you had to? How would you do that in Ruby? I guess you wouldn’t. At least not in any user-friendly way.

Until now. I’ve created a Ruby library called RAutomation which allows you to control windows, retrieve different kind of information about them, fill text fields with desired jargon and click the buttons on them! That’s all via very user friendly API.

Let’s Start to RAutomate

For example, let’s fire up Internet Explorer so that it has File Save As dialog opened like seen on the picture below:

Internet Explorer's Save As Dialog

Now, let’s install RAutomation gem and start up an irb session so we can have our fun with that window:

If you’ve used browser automation tool called Watir before then the code above should seem awful lot similar. The thing is that RAutomation’s API is inspired by Watir’s clean and nice API. Awesome news, isn’t it?

You can also see that i’ve managed to find the window, made sure that it has a title, that it exists, is visible and has a window handle (hwnd). Nice.

Clicking the Button

Ok, let’s click the Save button because that’s what i want to do, right? I want to download RAutomation’s gem from the RubyGems website! That would sound just odd if i wouldn’t. Clickety, click…

Whoops. That was almost as easy as walking in the park. The following window appears to make sure that i really want to download the file and i really know where to put it:

Yet another Save As Dialog

Filling the Fields

If we’ve already come so far then what choice do we even have anymore? I guess we have to tell it where to save the file. Let’s do it!

Saving The File?

It’s also possible to search windows by regular expressions? Nice! Ok, let’s click now that final Save button. Oh, dang. I just realised that i already have this nice gem because i installed it with `gem install rautomation` early on. It would be just plain stupidity to download it again, especially like this. I guess i’ll just ditch the window instead and carry on with the knowledge of having this wonderful library already in my posession.

What About Popups?

Let’s pretend that after you closed the window above, the following threatening JavaScript popup appeared out of nowhere:

Threatening JavaScript popup

First of all, if you’re using Watir then make sure that you’re testing your page correctly. If that’s not the case, then by all means, take risks in your life once in a while and close that popup:

Where’s The Catch?

The catch is that not all kind of windows and platforms are supported. Yet. Currently only Windows operating system and windows using Windows’ native components are (fully) supported. But why did i emphasize on the “Yet”? That’s because RAutomation is built to allow cross-platform compatibility with easy extensibility by allowing to support all kind of different technologies. This is where the Adapter comes into the play.

What’s an Adapter?

RAutomation’s adapter is a technical component of the library being responsible for dealing with controlling windows and their controls on a specific operating system for specific technologies. As stated above then currently only Windows operating system is supported with two different adapters - :ffi and :autoit. By default :ffi adapter is used on Windows to execute Windows’ API functions directly. If there’s any need to change the adapter then it’s possible to specify another default one by using an environment variable called RAUTOMATION_ADAPTER or specifying different adapter for controlling specific window with the :adapter option:

Since i’ve set the environment variable to autoit then the first window is using adapter for AutoIt. The second one uses FFI instead since i specified it with an :adapter option. And of course they both point to the same physical Internet Explorer window.

How to Create New Adapters?

Since i’ve built RAutomation having all kinds of different platforms and technologies in mind, i’ve created a possibility to extend it relatively easily. If it’s possible to automate windows with Ruby directly or with the help of some external tools on the platform, then it should be possible to create a new Adapter for RAutomation. Just follow the steps below. I’d be happy to merge the results into the master.

  • Fork the project at GitHub
  • Create entry point file to lib/rautomation/adapter which should load all adapter specific files
  • Add `autoload` statement into lib/rautomation/adapter/helper.rb for that file
  • Create a directory for your adapter’s specific code into lib/rautomation/adapter
  • Copy button.rb, text_field.rb and window.rb from some of the existing adapter’s directory
  • Add spec data for your adapter into spec/spec_helper DATA constant
  • Use environment variable RAUTOMATION_ADAPTER to point to that adapter
  • Start coding and spec-ing until as much of possible of the public API is satisfied
  • Make me a pull request

Until then, have fun with the existing adapters!