Coder Social home page Coder Social logo

rautomation's Introduction

RAutomation

Gem Version

RAutomation is a small and easy to use library for helping out to automate windows and their controls for automated testing.

RAutomation provides:

  • Easy to use and user-friendly API (inspired by Watir)
  • Cross-platform compatibility
  • Easy extensibility - with small scripting effort it's possible to add support for not yet supported platforms or technologies

USAGE

require "rautomation"

window = RAutomation::Window.new(:title => /part of the title/i)
window.exists? # => true

window.title # => "blah blah part Of the title blah"
window.text # => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies..."

window.text_field(:class => "Edit", :index => 0).set "hello, world!"
button = window.button(:value => "&Save")
button.exists? # => true
button.click

all_windows = RAutomation::Window.windows
all_windows.each {|window| puts window.hwnd}

window = RAutomation::Window.new(:title => /part of the title/i)
windows = window.windows
puts windows.size # => 2
windows.map &:title # => ["part of the title 1", "part of the title 2"]

window.windows(:title => /part of other title/i) # => all windows with matching specified title

window.buttons.each {|button| puts button.value}
window.buttons(:value => /some value/i).each {|button| puts button.value}

window2 = RAutomation::Window.new(:title => "Other Title", :adapter => :autoit) # use AutoIt adapter
# use adapter's (in this case AutoIt's) internal methods not part of the public API directly
window2.WinClose("[TITLE:Other Title]")

Check out the documentation for other possible usages!

INSTALL

Windows

gem install rautomation

Available adapters:

  • :win_32 - uses Windows API directly with FFI (default)
  • :ms_uia - an experimental adapter
  • :autoit - uses AutoIt for automation (DEPRECATED)

When using AutoIt adapter: You might need administrative privileges if running for the first time and you haven't installed AutoIt before!

Linux

Feel yourself at home on Linux and know how to automate windows and their controls? I would be happy if you'd contact me about that matter - or even better, follow the instructions at "How to create a new adapter?"

OS X

Feel yourself at home on OS X and know how to automate windows and their controls? I would be happy if you'd contact me about that matter - or even better, follow the instructions at "How to create a new adapter?"

Others

Feel yourself at home on some operating system not listed in here and know how to automate windows and their controls? Does Ruby also work on that operating system? I would be happy if you'd contact me about that matter - or even better, follow the instructions at "How to create a new adapter?"

Supported Ruby Platforms

64bit Ruby platform is only supported for Win32 adapter. Other adapters can be used only on a 32bit Ruby!

How to create a new adapter?

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

Don't forget to fix the documentation for that adapter also!

In case of any problems, feel free to contact me.

Contributors

Libraries Using RAutomation

Note on Patches/Pull Requests

  • Fork the project.

  • Make your feature addition or bug fix.

  • Add tests for it. This is important so I don't break it in a future version unintentionally.

  • Commit, do not mess with rakefile, version, or history.

    (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)

  • Send me a pull request. Bonus points for topic branches.

Copyright

Copyright (c) Jarmo Pertman. See LICENSE for details.

rautomation's People

Contributors

chrahunt avatar enkessler avatar jacob-ewald avatar jarmo avatar kylemartinez avatar leviwilson avatar moller2866 avatar myungs avatar rdp avatar snscaimito avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rautomation's Issues

MsUia: Internationalization

It would be very useful to have full support for non-ASCII (i.e. UTF-8) characters for locating controls and windows.

In particular, when you use the MsUia adapter and try to open a menu, only the :text locator is allowed, which means that if the text is in a language different of english, it will fail to get the control.

At least it would be fine to get a workaround to this by allowing to use another locator, like :id, this way it could be possible to define a list of values (or a hash) with the name of the menu and its AutomationID to get the right control.

Something like:

...

FILE_MENU = "123"
SUBMENU = "456"

RAutomation.window(title: /myapp/i, adapter: :ms_uia).menu(id: FILE_MENU).menu(id: SUBMENU).open

...

LoadError iaccessibleDll.dll on windows 7

Hi,

I get the following error when I want to start this simple example:
code:

    require "rautomation"
    window = RAutomation::Window.new(:title => 'File Download', :adapter => :win_32)
    put window.title

Error:

C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/ffi-1.9.0/lib/ffi/library.rb:123:in `block in ffi_lib': Could not open library 'C:/Ruby200-x64/lib/ruby/gems/2
.0.0/gems/rautomation-0.9.2/lib/rautomation/adapter/win_32/../../../../ext/IAccessibleDLL/Release/iaccessibleDll':  (LoadError)
        from C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/ffi-1.9.0/lib/ffi/library.rb:90:in `map'
        from C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/ffi-1.9.0/lib/ffi/library.rb:90:in `ffi_lib'
        from C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/rautomation-0.9.2/lib/rautomation/adapter/win_32/functions.rb:8:in `<module:Functions>'
        from C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/rautomation-0.9.2/lib/rautomation/adapter/win_32/functions.rb:5:in `<module:Win32>'
        from C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/rautomation-0.9.2/lib/rautomation/adapter/win_32/functions.rb:3:in `<module:Adapter>'
        from C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/rautomation-0.9.2/lib/rautomation/adapter/win_32/functions.rb:2:in `<module:RAutomation>'
        from C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/rautomation-0.9.2/lib/rautomation/adapter/win_32/functions.rb:1:in `<top (required)>'
        from C:/Ruby200-x64/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'
        from C:/Ruby200-x64/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'
        from C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/rautomation-0.9.2/lib/rautomation/adapter/win_32.rb:9:in `<top (required)>'
        from C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/rautomation-0.9.2/lib/rautomation/window.rb:67:in `const_get'
        from C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/rautomation-0.9.2/lib/rautomation/window.rb:67:in `initialize'
        from test.rb:3:in `new'
        from test.rb:3:in `<main>'

This iaccessibleDll.dll file exsists, the path to it is correct and is readable as far as I can see now, but nothing happens :(

I found somewere that it could be the problem, that the path is relative, but when I change the path to:
C:/Ruby200-x64/lib/ruby/gems/2.0.0/gems/rautomation-0.9.2/ext/IAccessibleDLL/Release/iaccessibleDll.dll
It still doen't work.

The other files that should be load are loaded fine, but this important one doesn't.
How can I fix this?

Window#new with valid :hwnd always succeeds, regardless of other locators

A call to method Window#new whose locators include a valid :hwnd always finds the window with the given hwnd, even if none of the other locators given match that window.

From the doc: "Use multiple locators, every locator will be matched (AND-ed) to the window."

Here's a test that produces the behavior by calling with a valid :hwnd, and with all other locators not matching the window. The assertion fails.

require 'test/unit'
require 'rubygems'
require 'rautomation'

class BugDemo < Test::Unit::TestCase

def setup
thread = Thread.new { calc.exe }
Thread.pass
sleep 1
@@calculator_window = RAutomation::Window.new(:title => 'Calculator')
end

def teardown
@@calculator_window.close
end

def test_bug_demo
# This window should not be found,
# because all locators are invalid except :hwnd.
locators = {
:class => 'NoSuch',
:hwnd => @@calculator_window.hwnd,
:index => 1000000,
:pid => 1 + @@calculator_window.pid,
:text => 'NoSuch',
:title => 'NoSuch'
}
window = RAutomation::Window.new(locators)
assert(!window.exists?, 'Window does not exist')
end

end

Public API

I am guessing that part of an adapter fulfilling the public API is passing all of the adapter non-specific specs regardless of which adapter is used? I was making some Autoit specs and when I switched the default adapter to :autoit any spec that located elements by :id failed. While :id is a valid locator that will work with the :autoit adapter, it's meaning is not the same as for the :win_ffi adapter and as such it cannot currently be used in the same way across adapters.

In particular, the TextField specs fail because they have "textField" listed as the :id which lines up with the AutomationID used by :win_ffi. The :id used by :autoit, however, is a number which changes every time the control is created and as such is problematic to practically use as an identifier.

File Download issue

I am using Win7, Ruby 1.8.7 and Watir 1.9.0

I click a download link and the dialog box appears. I want to click the Save button. When I am not using Autoit the code does not attach to the dialog box. When I use Autoit everything functions as expected. The Save As and the Download Complete dialogs work fine. I only have to use Autoit for the initial Save dialog box. The odd thing is when I'm not using Autoit if I click the Ruby command window the non Autoit RAutomation finds the dialog box and it clicks the Save button. If I just do an attach to the browser and click the link it seems to work. It just won't work when it is imbedded in the rest of my script. I know it doesn't make sense but that is what is happening.

This does not work:

window = RAutomation::Window.new(:title => 'File Download')
window.button(:value => '&Save').click()

This works:

window = RAutomation::Window.new(:title => 'File Download', :adapter => :autoit)
window.button(:value => '&Save').click()

Thanks for gem. When I get over this hump it will make my life a lot easier.

George

clicking buttons without a video input

HI Jarmo,

I'm seeing an issue when using rautomation where the automation fails to work properly when there is no monitor or video output (for example, remote desktop into a machine). I'm using automation to close javascript dialogs (via watir) and the script times out in Control#click, wait_until if there is no video output attached at the time. This is happening when it's trying to activate and set focus to the windows. If you are watching it by logging into the machine or you are not locked out of your screen then it runs fine. So it only fails when no-one is watching :). This is a problem, however when you're trying to run against a set of test machines using Jenkins, eg.

I didn't submit a pull request for this because the fix seems like a big change and I'm not sure of the implications or what else might be affected. Also I was not able to figure out how your unit tests needed to be set up - pointing to notepad didn't seem to work for me and I didn't want to install .net to run the bundled app :)....in any case, below is a working solution and steps to reproduce.

You can recreate using the following:

(1) Open IE with this HTML

(2) Run a script that continually opens/closes dialogs (eg from the rautomation/spec dir)

$LOAD_PATH.unshift(File.join(File.dirname(FILE), '..', 'lib'))
require 'rautomation'
require 'watir/ie'

ie = Watir::IE.attach :url, /test/
i = 0
loop do
ie.button(:index,1).click_no_wait
ie.javascript_dialog.button("OK").click
i += 1
puts i
end

(3) Ctrl+Alt+Del while the script is running and wait a bit. You'll notice the ding of the popup stops and if you get out of this screen, the script starts up again. If you wait long enough the script times out.

I was able to get things working by removing the activate and focus calls in Control#click. After this change the script doesn't stall when you disconnect the video. Seems like the activate/focus calls won't work without an active video out.

Work around Jenkins issue where dialogs not clicked

module RAutomation
module Adapter
module WinFfi
class Control
def click
assert_enabled
clicked = false
wait_until do
hwnd = Functions.control_hwnd(@window.hwnd, @locators)

        if hwnd
          Functions.control_click(hwnd) &&
          clicked = true # is clicked at least once
        end

        block_given? ? yield : clicked && !exist?
      end
    end
  end
end

end
end

add window_class method

Since I'm a bit lazy...

module RAutomation
  module Adapter
    module WinFfi
      class Window
        def class_name
          Functions.window_class(hwnd)
        end
      end
    end
  end
end

Window should have many elements

Currently Window has only #controls. I recommend of changing the line https://github.com/jarmo/RAutomation/blob/master/lib/rautomation/adapter/ms_uia/window.rb#L11 to something like:

has_many :controls, :tables, :radios # ... and so on

The problem is currently also with :win32 adapter in addition to :ms_uia, but i would ignore that since the big idea is to make :ms_uia as default adapter and remove :win32 adapter altogether.

So, for now - let's improve only :ms_uia in that regard.

Ability to enumerate all windows

feature request:

=> d = RAutomation.desktop

(a window that allows the user to then do d.windows and enumerate all)
or
RAutomation.desktop_windows
or the like.
Thanks!
-roger-

How to get an array of objects with same property

Hi all,

I have a Siebel app that runs in IE8 and I want to interact with some ActiveX controls that are basically some windows. These controls don't have any name or id, but I can get their hwnds with WinSpy++:

w = RAutomation::Window.new :hwnd=>'00090BB2'.to_i(16)

The problem is that the hwnds are changing every time I open the app so I was thinking getting their parent that is the Internet Explorer Server inside the IE browser, then get the children and reference each child by index. I want to get the parent cause it actually has a class name. Or can I get an array with all the children if I know their class name (#32770 in this case)?

So how can I interact with these elements if their hwnds change all the time?

I have attached a screenshot of the app taken with WinSpy++.

Thanks a lot!
Andrei
siebel

Show friendly error message when loading UiaDll fails.

First, let's find out what are all the requirements for loading UiaDll successfully. Even on older XP machines (#34) and then let's try to catch that error to show meaningful message to the user before exiting (#62).

At that point we could try to set MsUia as a default adapter after it has seen some polishing and retire AutoIt and Win32 adapters once and for all making more room for other-OS-adapters hopefully.

split text

Hello.
Since there's no mailing list, just posting this as an issue :)

I noticed with this code (using chrome browser, but probably doesn't matter):
window = RAutomation::Window.new(:title => /jarmo/)

window.text
=> "Commit 04e2297 to snscaimito/RAutomation - GitHubDummyWindowForActivationDummyWindowForActivationhttps://github.com/snscaimito/RAutomation/commit/04e229755ab942b7af6b8aec03e354c6745ac531"

It's like it's concatenating tons of strings. Maybe those should be split up?

ms_uia Automation ID locators

One of the best about the Windows automation library is being able to use the AutomationID of a given control/window. This would be really great to have in the library.

ButtonHelper.set? always returns false

I've pulled the latest sources and am running them on Windows 7. It looks like everything that uses ButtonHelper.set? is failing as BM_GETSTATE is always returning 0 (according to Spy). Here is my output from rake (only the fail information):

Failures:

  1) RAutomation::Window#activate & #active?
     Failure/Error: window.should be_active
       expected active? to return true, got false
     # ./spec/window_spec.rb:69:in `block (2 levels) in <top (required)>'

  2) Win32::Checkbox#set? & #set
     Failure/Error: checkbox.set
     RAutomation::WaitHelper::TimeoutError:
       timed out after 15 seconds
     # ./lib/rautomation/wait_helper.rb:20:in `wait_until'
     # ./lib/rautomation/adapter/win_32/control.rb:33:in `click'
     # ./lib/rautomation/adapter/win_32/button_helper.rb:18:in `set'
     # ./spec/adapter/win_32/checkbox_spec.rb:16:in `block (2 levels) in <top (required)>'

  3) Win32::Checkbox#clear
     Failure/Error: checkbox.set
     RAutomation::WaitHelper::TimeoutError:
       timed out after 15 seconds
     # ./lib/rautomation/wait_helper.rb:20:in `wait_until'
     # ./lib/rautomation/adapter/win_32/control.rb:33:in `click'
     # ./lib/rautomation/adapter/win_32/button_helper.rb:18:in `set'
     # ./spec/adapter/win_32/checkbox_spec.rb:27:in `block (2 levels) in <top (required)>'

  4) Win32::RadioButton#set? & #set
     Failure/Error: radio.set
     RAutomation::WaitHelper::TimeoutError:
       timed out after 15 seconds
     # ./lib/rautomation/wait_helper.rb:20:in `wait_until'
     # ./lib/rautomation/adapter/win_32/control.rb:33:in `click'
     # ./lib/rautomation/adapter/win_32/button_helper.rb:18:in `set'
     # ./spec/adapter/win_32/radio_spec.rb:17:in `block (2 levels) in <top (required)>'

Finished in 2 minutes 17.41 seconds
85 examples, 4 failures

Failed examples:

rspec ./spec/window_spec.rb:66 # RAutomation::Window#activate & #active?
rspec ./spec/adapter/win_32/checkbox_spec.rb:12 # Win32::Checkbox#set? & #set
rspec ./spec/adapter/win_32/checkbox_spec.rb:25 # Win32::Checkbox#clear
rspec ./spec/adapter/win_32/radio_spec.rb:13 # Win32::RadioButton#set? & #set

Can't find child window with same title text as parent window

An app has a main window and a child window (popup) with the exact same title text.

w = RAutomation::Window.new(:title => /BrowseTree Administration/i) finds the main window.

w.child(:title => /BrowseTree Administration/i) is unable to find the child window.

License missing from gemspec

Some companies will only use gems with a certain license.
The canonical and easy way to check is via the gemspec,

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Even for projects that already specify a license, including a license in your gemspec is a good practice, since it is easily
discoverable there without having to check the readme or for a license file. For example, it is the field that rubygems.org uses to display a gem's license.

For example, there is a License Finder gem to help companies ensure all gems they use
meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough
issue that even Bundler now generates gems with a default 'MIT' license.

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), github has created a license picker tool.

In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :).

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue and let me know. In either case, I'll follow up. Thanks!

p.s. I've written a blog post about this project

AutoItX3.dll registration error

I tried using the :autoit adapter for the first time the other day and was pleased with the results. When I tried using it on a different machine, however, I ran into a problem. In the #load_autoit method the call to regsvr32.exe kept failing. As it turns out this was because I was not running my applications as Administrator and thus did not have the permission to register the needed dll. Once I made the call to regsvr32.exe while an Admin everything worked fine.

It strikes me that this is an issue that should be handled at the time of gem installation and not require additional effort after the fact or blind luck that the dll has already been registered but simply installing the gem through a console that was opened as an Administrator did not seem to do the trick. Is there a good way to handle the registration at install time?

MsUia: Error Clicking Control

When clicking on a control using the :ms_uia adapter, sometimes the following exception is thrown:

RuntimeError: System.Runtime.InteropServices.COMException (0x80042002): Exception from HRESULT: 0x80042002
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   at MS.Internal.Automation.UiaCoreApi.CheckError(Int32 hr)
   at AutomationClicker.Click()
   at RA_Click(_FindInformation* findInformation, SByte* errorInfo, Int32 errorInfoSize)

The control exists and it seems like everything should click through properly.

Windows#size can hang and leak memory

The code below, placed in a file in spec/ and run by rspec, hangs and leaks memory rapidly.

The call to windows.class succeeds, but the call to windows.size does not return.

require 'spec_helper'

describe RAutomation::Windows do

it "" do
title = SpecHelper::DATA[:window1_title]
window1 = RAutomation::Window.new(:title => title)
hwnd = window1.windows.first.hwnd
windows = window1.windows(:hwnd => hwnd)
puts windows.class; $stdout.flush
puts windows.size
end

end

Changing select_list values do not fire Window's events

For example: let us say I have a combo box, and depending on the value selected in the combo box, the OnChange event will change a value in a text field dynamically.

 @window.select_list(:id => "select_list_1").options(:text => "Cheese")[0].select

If I use RAutomation, it will not trigger the OnChange event.

MsUia::Radio#set not working on WPF application

The tests are working on a WindowsForms application, and there the spec file succeeds. When I use RAutomation on a WPF application MsUia::Radio#set fails and claims it cannot file the control.

However most other methods works file such as #set?, #control_name #class_name, and so on.

jruby fails

RuntimeError: unsupported platform for RAutomation: java
Maybe needs a better check for "windows' (OS gem's OS.windows? is what I typically use).

MsUia ListBox: Not firing events if the item is out of the viewable area

Description

If you have a ListBox control that has many items in it, if you select an item that is outside of the viewable area, events do not get fired.

window = RAutomation::Window.new(title: 'Some Title', adapter: :ms_uia)
list_box = window.list_box(id: 'listBox1')
label = window.label(id: 'changedListItem') # => holds the value when the label changes

list_box.select(20) # => select an item that is outside of the view
label.value.should eq('Item 20 Text') # => fails

Segmentation Fault in functions.rb:317

I have a Windows Security box open and am trying to access it via rautomation. I can get the handle for the box, but when I run any rautomation feature, it gives me segmentation fault.
Here is my script:

require 'watir'
require 'rautomation'

ww = RAutomation::Window.new(:title=>"Windows Security")
ww.exists?

here is the error:
C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/adapter/win_32/functions.rb:317: [BUG] Segmentation fault
ruby 1.9.3p194 (2012-04-20) [i386-mingw32]

-- Control frame information -----------------------------------------------
c:0009 p:---- s:0034 b:0034 l:000033 d:000033 CFUNC :enum_windows
c:0008 p:0080 s:0029 b:0029 l:001a98 d:001a98 METHOD C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/adapter/win_32/functions.rb:317
c:0007 p:0013 s:0021 b:0021 l:000e80 d:000e80 METHOD C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/adapter/win_32/functions.rb:141
c:0006 p:0034 s:0017 b:0017 l:000016 d:000016 METHOD C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/adapter/win_32/window.rb:48
c:0005 p:0011 s:0014 b:0014 l:000013 d:000013 METHOD C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/adapter/win_32/window.rb:90
c:0004 p:0013 s:0010 b:0010 l:000009 d:000009 METHOD C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/window.rb:138
c:0003 p:0073 s:0007 b:0007 l:00044c d:001638 EVAL C:/Devkit/secondtest.rb:13
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
c:0001 p:0000 s:0002 b:0002 l:00044c d:00044c TOP

-- Ruby level backtrace information ----------------------------------------
C:/Devkit/secondtest.rb:13:in <main>' C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/window.rb:138:inexists?'
C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/adapter/win_32/window.rb:90:in exists?' C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/adapter/win_32/window.rb:48:inhwnd'
C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/adapter/win_32/functions.rb:141:in window_hwnd' C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/adapter/win_32/functions.rb:317:infind_hwnd'
C:/Ruby193/lib/ruby/gems/1.9.1/gems/rautomation-0.7.2/lib/rautomation/adapter/win_32/functions.rb:317:in `enum_windows'

Running it on Windows 7 with ffi (1.1.0), rautomation(0.7.2), ruby (0.9.9) and watir (3.0.0)

Rautomation windows dialog box not active from CLI(Jenkins)

Hi,

I have tried to kick off my test script from Jenkins for continuous integration. while doing file upload my script got failed because, that windows dialog box for upload file is not active when it is triggered from command line interface.

Could anybody help me on this issue?

Note: Whereas if I physically in the machine, then upload file get success. My problem is only on CLI interface call.

MsUia: Better Error Handling

This is kind of a generic request, but there are methods in the UiaDll.dll that output error information if an exception is thrown rather than relaying that information back to the caller. It would be nice to have some consistency in doing this and to allow the caller to decide what to do with the exception.

Upload File on multiple browser failed

Hi,

Actually I have tried to upload file on a multiple browsers(launching three Firefox browser instances) on each browser i am doing file upload one by one. For example:

  1. first upload file on browser # 1. - It got success)
  2. second upload file on browser # 2 - It got failed, because window has been triggered but Rautomation can't find that window, so it throws me a timeout error.

Please advice

Feature Request: Tab Order

It would be nice to be able to grab the tab order property inside an element on the screen.

Either that or be able to see what element is in focus, so while you tab you can check what element is in focus.

MsUia: Control#click fails if the window goes away

When a Control is clicked, causing the Window to go away, RAutomation will crash ruby as noted in #72 here. This only happens if the control is found by a UIA locator, not a Win32 locator.

window.button(:value => 'OK').click # this is fine
window.button(:id => 'buttonOK').click # this crashes

An Issue of Timing

Here's a little experiment:

  1. Open up an application window.
  2. Locate that window (by :title for the sake of argument) and store it in a handy variable.
  3. Check if it #exist?.
  4. Close the window.
  5. Reopen/relaunch the application window.
  6. Check if it #exists? again using the same variable.

According to RAutomation the window will not exist the second time. You won't be able to click buttons or grab values or anything else for that matter either because the instance of Window that the variable points to was fixed to a specific instance of a matching application window.

Here is the offending piece of code by the way:

    # Retrieves handle of the window.
    # @note Searches only for visible windows.
    # @see RAutomation::Window#hwnd
    def hwnd
      @hwnd ||= Functions.window_hwnd(@locators)
    end

Since most of the internal operations of a Window are handled via its @hwnd, as soon as you use it the first time you are tied to one exact application window.

Is this desired? Shouldn't a given RAutomation::Window object be able to interact with any application window as long as its locators match?

MsUia::TextField - ControlType.Edit or ControlType.Document?

I've been running into an issue where sometimes a multi-line System.Windows.Forms.TextBox will return UIA_DocumentControlTypeId (50030) vs UIA_EditControlTypeId (50004). In the MsUia::TextField class it has the following:

  def exist?
    super && matches_type?(Constants::UIA_EDIT_CONTROL_TYPE)
  end

I believe that this should also include Constants::UIA_DOCUMENT_CONTROL_TYPE (does not exist yet) as well. I would have added this, but I cannot for the life of me get the WindowsForms app that is used in the specs to return 50030 rather than 50004. I'm happy to add this to the test suite as long as you're cool with me not being able to reproduce a failing test. I am, however, seeing this in the app I'm working with. I cannot figure out the difference.

Identifiers only work with Hashes

RAutomation currently only seems to work with =>

@window.button(:value => "OK)

Will work, but the following will not:

@window.button(:value, "OK")

and give the error:
ArgumentError: wrong number of arguments (2 for 1)

Window#button sometimes (but consistently) fails to find a button.

Window#button sometimes (but consistently) fails to find a button.

Here's some code that I've isolated and adapted from the suites I've been building to test RAutomation. It should run if placed in a file in directory spec. It's worth noting that the button was found for each of the single-valued locators, so we can (safely?) assume that the locator values are correct (for my machine).

Though this test does not demonstrate it, I saw no difference when :id and :index were given as strings rather than as integers.

require 'rautomation'
require 'rspec'

RSpec.configure do |config|
  
  config.before(:all) do
    @pid = IO.popen('calc.exe').pid
    RAutomation::WaitHelper.wait_until {RAutomation::Window.new(:pid => @pid).present?}
  end

  config.after(:all) do
    Process.kill(9, @pid) rescue nil
  end

end

describe RAutomation::Button do
  
  # Calculator button '1'.
  # These values could conceivably vary among versions of Calculator.
  klass = 'Button'
  id = 125
  index = 6
  value = '1'
  
  locators = [
    {},
    {:class => klass},
    {:id => id},
    {:index => index},
    {:value => value},
    {:class => klass, :id => id},
    {:class => klass, :index => index},
    {:class => klass, :value => value},
    {:id => id, :index => index},
    {:id => id, :value => value},
    {:index => index, :value => value},
    {:class => klass, :id => id, :index => index},
    {:class => klass, :id => id, :value => value},
    {:class => klass, :index => index, :value => value},
    {:id => id, :index => index, :value => value},
    {:class => klass, :id => id, :index => index, :value => value},
  ]

  locators.each do |locator|
    it "#button for locator #{locator.inspect}" do
      window = RAutomation::Window.new(:title => 'Calculator')
      button = window.button(locator)
      button.should exist
    end
  end
  
end

The result varies by adapter:

$ RAUTOMATION_ADAPTER=autoit rspec button_bug.rb
..........F..F..

Failures:

  1) RAutomation::Button #button for locator {:index=>6, :value=>"1"}
     Failure/Error: button.should exist
       expected #"Calculator"}, 

@autoit_locators="[title:Calculator]">, @locators={:index=>6, :value=>"1"}, @button=#"Calculator"}, @autoit_locators="[title:Calculator]">, 

@locators={:class=>/button/i, :index=>6, :value=>"1"}, @autoit_locators="[regexpclass:(?i-mx:button);instance:7;text:1]">> to exist
     # ./button_bug.rb:49:in `block (3 levels) in '

  2) RAutomation::Button #button for locator {:class=>"Button", :index=>6, :value=>"1"}
     Failure/Error: button.should exist
       expected #"Calculator"}, 

@autoit_locators="[title:Calculator]">, @locators={:class=>"Button", :index=>6, :value=>"1"}, @button=#"Calculator"}, @autoit_locators="[title:Calculator]">, 

@locators={:class=>"Button", :index=>6, :value=>"1"}, @autoit_locators="[class:Button;instance:7;text:1]">> to exist
     # ./button_bug.rb:49:in `block (3 levels) in '

Finished in 1.08 seconds
16 examples, 2 failures
$ RAUTOMATION_ADAPTER=win_ffi rspec button_bug.rb
........F.FF.FFF

Failures:

  1) RAutomation::Button #button for locator {:id=>125, :index=>6}
     Failure/Error: button.should exist
       expected #"Calculator"}, @hwnd=6882536>, 

@locators={:id=>125, :index=>6}, @button=#"Calculator"}, @hwnd=6882536>, @locators={:class=>/button/i, :id=>125, :index=>6}>> to exist
     # ./button_bug.rb:49:in `block (3 levels) in '

  2) RAutomation::Button #button for locator {:index=>6, :value=>"1"}
     Failure/Error: button.should exist
       expected #"Calculator"}, @hwnd=6882536>, 

@locators={:index=>6, :value=>"1"}, @button=#"Calculator"}, @hwnd=6882536>, @locators={:class=>/button/i, :index=>6, :value=>"1"}>> to exist
     # ./button_bug.rb:49:in `block (3 levels) in '

  3) RAutomation::Button #button for locator {:class=>"Button", :id=>125, :index=>6}
     Failure/Error: button.should exist
       expected #"Calculator"}, @hwnd=6882536>, 

@locators={:class=>"Button", :id=>125, :index=>6}, @button=#"Calculator"}, @hwnd=6882536>, @locators={:class=>"Button", :id=>125, :index=>6}>> to exist
     # ./button_bug.rb:49:in `block (3 levels) in '

  4) RAutomation::Button #button for locator {:class=>"Button", :index=>6, :value=>"1"}
     Failure/Error: button.should exist
       expected #"Calculator"}, @hwnd=6882536>, 

@locators={:class=>"Button", :index=>6, :value=>"1"}, @button=#"Calculator"}, @hwnd=6882536>, @locators={:class=>"Button", :index=>6, :value=>"1"}>> to exist
     # ./button_bug.rb:49:in `block (3 levels) in '

  5) RAutomation::Button #button for locator {:id=>125, :index=>6, :value=>"1"}
     Failure/Error: button.should exist
       expected #"Calculator"}, @hwnd=6882536>, 

@locators={:id=>125, :index=>6, :value=>"1"}, @button=#"Calculator"}, @hwnd=6882536>, @locators={:class=>/button/i, :id=>125, :index=>6, :value=>"1"}>> to exist
     # ./button_bug.rb:49:in `block (3 levels) in '

  6) RAutomation::Button #button for locator {:class=>"Button", :id=>125, :index=>6, :value=>"1"}
     Failure/Error: button.should exist
       expected #"Calculator"}, @hwnd=6882536>, 

@locators={:class=>"Button", :id=>125, :index=>6, :value=>"1"}, @button=#"Calculator"}, @hwnd=6882536>, @locators={:class=>"Button", :id=>125, :index=>6, :value=>"1"}>> 

to exist
     # ./button_bug.rb:49:in `block (3 levels) in '

Finished in 0.98438 seconds
16 examples, 6 failures

Support for masked input fields

On .NET there is a masked input field that appears to be an edit control. With the currently version of RAutomation validation attached to the control is not trigged. Setting the 'text' of the control removes the mask, as the mask is stored as the control's text.

Feature Enhancement: select_list #select and #selected?

Method call for selecting an element in a select_list is poor.

Currently the spec is:
it "#selected? & #select" do
select_list = RAutomation::Window.new(:title => "MainFormWindow").select_list(:class => /COMBOBOX/i)
select_list.options(:text => "Apple")[0].should_not be_selected
select_list.options(:text => "Apple")[0].select.should be_true
select_list.options(:text => "Apple")[0].should be_selected
end

Would prefer it work like the following
it "#selected? & #select" do
select_list = RAutomation::Window.new(:title => "MainFormWindow").select_list(:class => /COMBOBOX/i)
select_list.selected?("Apple").should_not be_true
select_list.select("Apple").should be_true
select_list.selected?("Apple").should be_true

    #set alias for select, like in Watir
    select_list.set("Coconut").should be_true
    select_list.set?("Coconut").should be_true

    #raise exception if you try to call an option not in the list, used same exception name from watir
    expect { select_list.select("Mango") }.
        to raise_exception(RAutomation::NoValueFoundException )
end

set alias would also help for being able to, per request #11, loop over all sub-controls and call a generic #set

Cannot send square brackets or single quotes

Hi there,

I use rautomate to integrate with an application where the left square bracket "[" and the single quote " ' " are important. However, entering these keys in a string does not work.

Adding this to /adapter/win_32/keys.rb KEYS constant lets you use Window#send_keys(:left_square). I'd do a push request if I knew how to use git, but since I don't I'll just leave this here for whoever can add it into the code.

KEYS = {
...
:left_square => 0xDB,
:right_square => 0xDD,
:single_quote => 0xDE,
}..

Window#controls does not work without any arguments when using MsUia adapter

When using :ms_uia adapter then i'm getting an ArgumentError for the following code:

win.controls

Here is the relevant backtrace:

C:/bin/Ruby200/lib/ruby/gems/2.0.0/gems/rautomation-0.9.4/lib/rautomation/adapter/ms_uia/window.rb:216:in `controls': wrong number of arguments (0 for 1) (ArgumentError)

It seems to me that the problem is the fact that the Window#controls method is created by ElementCollections at https://github.com/jarmo/RAutomation/blob/master/lib/rautomation/adapter/ms_uia/window.rb#L11 and then overwritten at https://github.com/jarmo/RAutomation/blob/master/lib/rautomation/adapter/ms_uia/window.rb#L216-L219

It seems to me that the latter should be removed and the line @container.wait_until_present should be moved directly into ElementCollections.

@leviwilson, thoughts?

Cannot send dash, forwardslash, backslash

Hello I like the gem,

I want to use RAutomation to integrate with putty but the "-", "", and "/" symbols are important. However, these keys do not work when I try to .send_keys("-")

I'm not sure if this is something RAutomation would want to support or if the current character set is sufficient, but I would like to see this added!

Window#pid for adapter :autoit returns empty string.

Window#pid for adapter :autoit returns an empty string. For adapter :win_ffi, it returns an integet pid.

The code at adapter/autoit/window.rb is this:

  def pid
    @@autoit.WinGetProcess(hwnd)
  end

It would be better as:

  def pid
    @@autoit.WinGetProcess(title).to_i
  end

Here's a test that can be run in the spec directory:

  require 'spec_helper'
  
  describe RAutomation::Windows do
    
    [ :win_ffi, :autoit ].each do |adapter|
      title = SpecHelper::DATA[:window1_title]
      it "#pid with adapter=#{adapter} should return a positive integer" do
        window = RAutomation::Window.new(
          :adapter => adapter,
          :title => title
        )
        pid = window.pid
        puts "adapter=#{adapter} class=#{pid.class} value='#{pid}'"
        pid.should > 0
      end
    end
  
  end

Failing result on my machine:

adapter=win_ffi class=Fixnum value='2028'
.adapter=autoit class=String value=''
F

Failures:

  1) RAutomation::Windows #pid with adapter=autoit should return a positive inte
ger
     Failure/Error: pid.should > 0
     ArgumentError:
       comparison of String with 0 failed
     # ./pid_bug.rb:14

Finished in 3 seconds
2 examples, 1 failure

Feature Request: Grab all sub-controls in a Window

Be able to grab all sub-controls, text_field, select_list, check_box, etc, in a given RAutomation::Window. Something akin to the #child, but allows the use of control methods, and class specific methods for (select_list, check_box).

Feature Request: Enabled/Disabled Status

Like the Watir API, the ability to see if an element is enabled or disabled. I could see this functionality could be used for button, radio, checkbox, text_field and tables.

e.g.
@window.button(:name => "Start").enabled? @window.button(:name => "Start").disabled?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.