bewildr 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/LICENSE +28 -0
  2. data/README +8 -0
  3. data/Rakefile +52 -0
  4. data/lib/bewildr.rb +50 -0
  5. data/lib/bewildr/application.rb +95 -0
  6. data/lib/bewildr/bewildr_helpers.rb +17 -0
  7. data/lib/bewildr/control_patterns/expand_collapse_pattern.rb +24 -0
  8. data/lib/bewildr/control_patterns/grid_pattern.rb +15 -0
  9. data/lib/bewildr/control_patterns/invoke_pattern.rb +11 -0
  10. data/lib/bewildr/control_patterns/range_value_pattern.rb +19 -0
  11. data/lib/bewildr/control_patterns/selection_item_pattern.rb +24 -0
  12. data/lib/bewildr/control_patterns/selection_pattern.rb +28 -0
  13. data/lib/bewildr/control_patterns/table_pattern.rb +17 -0
  14. data/lib/bewildr/control_patterns/toggle_pattern.rb +70 -0
  15. data/lib/bewildr/control_patterns/value_pattern.rb +20 -0
  16. data/lib/bewildr/control_patterns/window_pattern.rb +31 -0
  17. data/lib/bewildr/control_type.rb +59 -0
  18. data/lib/bewildr/control_type_additions/combo_box_additions.rb +87 -0
  19. data/lib/bewildr/control_type_additions/data_grid_additions.rb +16 -0
  20. data/lib/bewildr/control_type_additions/list_additions.rb +18 -0
  21. data/lib/bewildr/control_type_additions/menu_additions.rb +60 -0
  22. data/lib/bewildr/control_type_additions/menu_item_additions.rb +18 -0
  23. data/lib/bewildr/control_type_additions/tab_additions.rb +18 -0
  24. data/lib/bewildr/control_type_additions/text_additions.rb +16 -0
  25. data/lib/bewildr/control_type_additions/tree_additions.rb +59 -0
  26. data/lib/bewildr/control_type_additions/tree_item_additions.rb +18 -0
  27. data/lib/bewildr/control_type_additions/window_additions.rb +23 -0
  28. data/lib/bewildr/element.rb +171 -0
  29. data/lib/bewildr/exceptions.rb +8 -0
  30. data/lib/bewildr/ext/BewildrClickr.dll +0 -0
  31. data/lib/bewildr/finder.rb +66 -0
  32. data/lib/bewildr/windows.rb +23 -0
  33. metadata +93 -0
data/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ Copyright (c) 2010, Nathaniel Ritmeyer
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+
14
+ 3. Neither the name Nathaniel Ritmeyer nor the names of contributors to
15
+ this software may be used to endorse or promote products derived from this
16
+ software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
19
+ IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
22
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README ADDED
@@ -0,0 +1,8 @@
1
+ == bewildr
2
+ Test WPF apps in (iron) ruby!
3
+
4
+ This is pre-alpha software - it has a way to go before being useable...
5
+
6
+ Documentation is on the way...
7
+
8
+ Nat Ritmeyer
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/rdoctask'
6
+ require 'rake/testtask'
7
+ require 'spec/rake/spectask'
8
+ require 'cucumber'
9
+ require 'cucumber/rake/task'
10
+
11
+ spec = Gem::Specification.new do |s|
12
+ s.name = 'bewildr'
13
+ s.version = '0.1'
14
+ s.has_rdoc = true
15
+ s.extra_rdoc_files = ['README', 'LICENSE']
16
+ s.summary = 'Test your WPF apps with (iron) ruby!'
17
+ s.description = s.summary
18
+ s.author = 'Nat Ritmeyer'
19
+ s.email = 'nat@natontesting.com'
20
+ s.homepage = 'http://github.com/natritmeyer/bewildr'
21
+ s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib}/**/*")
22
+ s.require_path = "lib"
23
+ s.bindir = "bin"
24
+ end
25
+
26
+ Rake::GemPackageTask.new(spec) do |p|
27
+ p.gem_spec = spec
28
+ p.need_tar = true
29
+ p.need_zip = true
30
+ end
31
+
32
+ Rake::RDocTask.new do |rdoc|
33
+ files =['README', 'LICENSE', 'lib/**/*.rb']
34
+ rdoc.rdoc_files.add(files)
35
+ rdoc.main = "README" # page to start on
36
+ rdoc.title = "bewildr Docs"
37
+ rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
38
+ rdoc.options << '--line-numbers'
39
+ end
40
+
41
+ Rake::TestTask.new do |t|
42
+ t.test_files = FileList['test/**/*.rb']
43
+ end
44
+
45
+ Spec::Rake::SpecTask.new do |t|
46
+ t.spec_files = FileList['spec/**/*.rb']
47
+ t.libs << Dir["lib"]
48
+ end
49
+
50
+ Cucumber::Rake::Task.new(:features) do |t|
51
+ t.cucumber_opts = "features --format pretty --no-color"
52
+ end
@@ -0,0 +1,50 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ #don't load bewildr unless we're using ironruby
4
+ #get rid of the following line and make sure that the gemspec sets it to be
5
+ #iron ruby only: http://www.ironruby.net/documentation/real_ruby_applications/rubygems
6
+
7
+ raise LoadError, "Bewildr only works under IronRuby" unless RUBY_ENGINE == "ironruby"
8
+
9
+ #require the UI Automation dlls
10
+ load_assembly 'UIAutomationClient, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
11
+ load_assembly 'UIAutomationTypes, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
12
+ load_assembly 'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
13
+
14
+ #require BewildrClickr - stopgap until the ffi gem works under ironruby
15
+ require File.join(File.expand_path(File.dirname(__FILE__)), "bewildr", "ext", "BewildrClickr.dll")
16
+ CLICKR = Bewildr::Clickr::Clickr.new
17
+
18
+ #load plain old ruby libraries
19
+ require 'timeout'
20
+
21
+ #require bewildr classes
22
+ require 'bewildr/exceptions'
23
+ require 'bewildr/bewildr_helpers'
24
+ require 'bewildr/control_type'
25
+ require 'bewildr/finder'
26
+ require 'bewildr/application'
27
+ require 'bewildr/windows'
28
+ require 'bewildr/element'
29
+
30
+ require 'bewildr/control_patterns/window_pattern'
31
+ require 'bewildr/control_patterns/invoke_pattern'
32
+ require 'bewildr/control_patterns/value_pattern'
33
+ require 'bewildr/control_patterns/toggle_pattern'
34
+ require 'bewildr/control_patterns/selection_pattern'
35
+ require 'bewildr/control_patterns/expand_collapse_pattern'
36
+ require 'bewildr/control_patterns/selection_item_pattern'
37
+ require 'bewildr/control_patterns/range_value_pattern'
38
+ require 'bewildr/control_patterns/grid_pattern'
39
+ require 'bewildr/control_patterns/table_pattern'
40
+
41
+ require 'bewildr/control_type_additions/text_additions'
42
+ require 'bewildr/control_type_additions/combo_box_additions'
43
+ require 'bewildr/control_type_additions/window_additions'
44
+ require 'bewildr/control_type_additions/menu_additions'
45
+ require 'bewildr/control_type_additions/menu_item_additions'
46
+ require 'bewildr/control_type_additions/tab_additions'
47
+ require 'bewildr/control_type_additions/list_additions'
48
+ require 'bewildr/control_type_additions/tree_additions'
49
+ require 'bewildr/control_type_additions/tree_item_additions'
50
+ require 'bewildr/control_type_additions/data_grid_additions'
@@ -0,0 +1,95 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ class Application
5
+ def initialize(proc)
6
+ @proc = proc
7
+ @proc.wait_for_input_idle(10)
8
+ @proc_id = proc.id
9
+ end
10
+ private :initialize
11
+
12
+ def kill
13
+ @proc.kill
14
+ Timeout::timeout(5) do
15
+ sleep 0.1 until @proc.has_exited
16
+ end
17
+ end
18
+
19
+ def running?
20
+ @proc.nil? ? false : !@proc.has_exited
21
+ end
22
+
23
+ def wait_for_termination
24
+ Timeout::timeout(30) do
25
+ sleep 0.2 while running?
26
+ end
27
+ end
28
+
29
+ def get_windows
30
+ Bewildr::Windows.windows_by_process_id(@proc_id)
31
+ end
32
+
33
+ def get_window_by_name(input)
34
+ case input
35
+ when String then return get_windows.select{|window| window.name.strip == input.strip}.first
36
+ when Regexp then return get_windows.select{|window| input.match(window.name.strip).nil? == false}.first
37
+ else
38
+ raise ArgumentError, "input not a string or regexp but a #{input.class}"
39
+ end
40
+ end
41
+ alias :get_window :get_window_by_name
42
+
43
+ def wait_for_window(input, wait_time = 30)
44
+ begin
45
+ Timeout::timeout(wait_time) do
46
+ begin
47
+ my_window = get_window(input)
48
+ raise if my_window.nil?
49
+ return my_window
50
+ rescue
51
+ sleep 0.2
52
+ retry
53
+ end
54
+ end
55
+ rescue Timeout::Error
56
+ raise ElementDoesntExist
57
+ end
58
+ end
59
+
60
+ def window_count
61
+ get_windows.size
62
+ end
63
+
64
+ #takes name or full path of exe to start
65
+ def self.start(process_name)
66
+ Bewildr::Application.new(System::Diagnostics::Process.start(process_name))
67
+ end
68
+
69
+ def self.start_with_settings(settings_hash)
70
+ #TODO
71
+ end
72
+
73
+ def self.attach_to_process_name(process_name)
74
+ Bewildr::Application.new(System::Diagnostics::Process.get_processes_by_name(process_name).first)
75
+ end
76
+
77
+ def self.attach_to_process(process)
78
+ Bewildr::Application.new(process)
79
+ end
80
+
81
+ def self.start_app_and_wait_for_window(path, window_name)
82
+ app = Bewildr::Application.start(path)
83
+ window = app.wait_for_window(window_name)
84
+ return app, window
85
+ end
86
+
87
+ def self.kill_all_processes_with_name(input)
88
+ System::Diagnostics::Process.get_processes_by_name(input).each {|p| p.kill}
89
+ end
90
+
91
+ def self.processes_with_name(input)
92
+ System::Diagnostics::Process.get_processes_by_name(input).collect {|p| Bewildr::Application.attach_to_process(p) }
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,17 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module BewildrHelpers
5
+ def r_array_to_cs_array_of_strings(args)
6
+ System::Array[System::String].new(args.map {|arg| arg.to_s.to_clr_string})
7
+ end
8
+
9
+ def r_array_to_cs_array_of_conditions(args)
10
+ System::Array[System::Windows::Automation::Condition].new(args)
11
+ end
12
+
13
+ def r_string_to_c_string(r_string)
14
+ System::String.new(r_string)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlPatterns
5
+ module ExpandCollapsePattern
6
+ def expand
7
+ @automation_element.get_current_pattern(System::Windows::Automation::ExpandCollapsePattern.pattern).expand unless expand_state == :expanded or expand_state == :leaf
8
+ end
9
+
10
+ def collapse
11
+ @automation_element.get_current_pattern(System::Windows::Automation::ExpandCollapsePattern.pattern).collapse unless expand_state == :collapsed or expand_state == :leaf
12
+ end
13
+
14
+ def expand_state
15
+ case @automation_element.get_current_pattern(System::Windows::Automation::ExpandCollapsePattern.pattern).current.expand_collapse_state
16
+ when System::Windows::Automation::ExpandCollapseState.collapsed then return :collapsed
17
+ when System::Windows::Automation::ExpandCollapseState.expanded then return :expanded
18
+ when System::Windows::Automation::ExpandCollapseState.partially_expanded then return :partially_expanded
19
+ when System::Windows::Automation::ExpandCollapseState.leaf_node then return :leaf
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlPatterns
5
+ module GridPattern
6
+ def row_count
7
+ @automation_element.get_current_pattern(System::Windows::Automation::GridPattern.pattern).current.row_count
8
+ end
9
+
10
+ def column_count
11
+ @automation_element.get_current_pattern(System::Windows::Automation::GridPattern.pattern).current.column_count
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlPatterns
5
+ module InvokePattern
6
+ def click
7
+ @automation_element.get_current_pattern(System::Windows::Automation::InvokePattern.pattern).invoke
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlPatterns
5
+ module RangeValuePattern
6
+ def value
7
+ @automation_element.get_current_pattern(System::Windows::Automation::RangeValuePattern.pattern).current.value
8
+ end
9
+
10
+ def maximum
11
+ @automation_element.get_current_pattern(System::Windows::Automation::RangeValuePattern.pattern).current.maximum
12
+ end
13
+
14
+ def minimum
15
+ @automation_element.get_current_pattern(System::Windows::Automation::RangeValuePattern.pattern).current.minimum
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+
4
+ module Bewildr
5
+ module ControlPatterns
6
+ module SelectionItemPattern
7
+ def select
8
+ @automation_element.get_current_pattern(System::Windows::Automation::SelectionItemPattern.pattern).select
9
+ end
10
+
11
+ def is_selected?
12
+ @automation_element.get_current_pattern(System::Windows::Automation::SelectionItemPattern.pattern).current.is_selected
13
+ end
14
+
15
+ def selected?
16
+ is_selected?
17
+ end
18
+
19
+ def unselected?
20
+ !is_selected?
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlPatterns
5
+ module SelectionPattern
6
+ def get_selection
7
+ my_selected_items = @automation_element.get_current_pattern(System::Windows::Automation::SelectionPattern.pattern).current.get_selection
8
+
9
+ c_array_list = System::Collections::ArrayList.new(my_selected_items)
10
+ item_array = c_array_list.to_array.to_a
11
+
12
+ return [] if item_array.size == 0
13
+ item_array.to_a.collect {|item| Bewildr::Element.new(item)}
14
+ end
15
+
16
+ def can_select_multiple?
17
+ @automation_element.get_current_pattern(System::Windows::Automation::SelectionPattern.pattern).current.can_select_multiple
18
+ end
19
+
20
+ def selected
21
+ case can_select_multiple?
22
+ when true then get_selection
23
+ when false then get_selection.first
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlPatterns
5
+ module TablePattern
6
+ def column_headers
7
+ @automation_element.get_current_pattern(System::Windows::Automation::TablePattern.pattern).current.get_column_headers.collect do |header|
8
+ Bewildr::Element.new(header)
9
+ end
10
+ end
11
+
12
+ def column_header_names
13
+ column_headers.collect {|header| header.name }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,70 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlPatterns
5
+ module TogglePattern
6
+
7
+ def self.extended(base)
8
+ base.instance_eval do
9
+ case @control_type
10
+ when :check_box
11
+ def check
12
+ set_state_to :on
13
+ end
14
+
15
+ def uncheck
16
+ set_state_to :off
17
+ end
18
+
19
+ def checked?
20
+ state == :on
21
+ end
22
+
23
+ def unchecked?
24
+ state == :off
25
+ end
26
+
27
+ def checked_state
28
+ state
29
+ end
30
+ when :button
31
+ def toggle(value)
32
+ set_state_to(value)
33
+ end
34
+
35
+ def toggle_state
36
+ state
37
+ end
38
+
39
+ def toggle
40
+ flip_state
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def set_state_to(value)
49
+ raise ElementNotEnabled unless enabled?
50
+ case value
51
+ when :on then flip_state while state != :on
52
+ when :off then flip_state while state != :off
53
+ else raise ArgumentError, "Didn't receive :on or :off"
54
+ end
55
+ end
56
+
57
+ def state
58
+ case @automation_element.get_current_pattern(System::Windows::Automation::TogglePattern.pattern).current.toggle_state
59
+ when System::Windows::Automation::ToggleState.Off then return :off
60
+ when System::Windows::Automation::ToggleState.On then return :on
61
+ when System::Windows::Automation::ToggleState.Indeterminate then return :indeterminate
62
+ end
63
+ end
64
+
65
+ def flip_state
66
+ @automation_element.get_current_pattern(System::Windows::Automation::TogglePattern.pattern).toggle
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,20 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlPatterns
5
+ module ValuePattern
6
+ def is_password_field?
7
+ @automation_element.current.class_name.to_s == "PasswordBox" ? true : false
8
+ end
9
+
10
+ def text
11
+ raise PasswordFieldReadAttempt, "You can't get the text of a password field" if is_password_field?
12
+ @automation_element.get_current_pattern(System::Windows::Automation::ValuePattern.pattern).current.value.to_s
13
+ end
14
+
15
+ def text=(input)
16
+ @automation_element.get_current_pattern(System::Windows::Automation::ValuePattern.pattern).set_value(input)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlPatterns
5
+ module WindowPattern
6
+ def close
7
+ @automation_element.get_current_pattern(System::Windows::Automation::WindowPattern.pattern).close
8
+ end
9
+
10
+ def minimize
11
+ @automation_element.get_current_pattern(System::Windows::Automation::WindowPattern.pattern).set_window_visual_state(System::Windows::Automation::WindowVisualState.minimized)
12
+ end
13
+
14
+ def maximize
15
+ @automation_element.get_current_pattern(System::Windows::Automation::WindowPattern.pattern).set_window_visual_state(System::Windows::Automation::WindowVisualState.maximized)
16
+ end
17
+
18
+ def restore
19
+ @automation_element.get_current_pattern(System::Windows::Automation::WindowPattern.pattern).set_window_visual_state(System::Windows::Automation::WindowVisualState.normal)
20
+ end
21
+
22
+ def visual_state
23
+ case @automation_element.get_current_pattern(System::Windows::Automation::WindowPattern.pattern).current.window_visual_state
24
+ when System::Windows::Automation::WindowVisualState.maximized then return :maximized
25
+ when System::Windows::Automation::WindowVisualState.minimized then return :minimized
26
+ when System::Windows::Automation::WindowVisualState.normal then return :normal
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,59 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ class ControlType
5
+ class << self
6
+ def symbol_for_enum(input_control_type_enum)
7
+ raise "Unknown control type: #{input_control_type_enum}" unless @@control_type_map.value?(input_control_type_enum)
8
+ @@control_type_map.index(input_control_type_enum)
9
+ end
10
+
11
+ def class_for_symbol(input_symbol)
12
+ raise "Unknown control type: #{input_symbol}" unless @@control_type_map.key?(input_symbol)
13
+ @@control_type_map[input_symbol]
14
+ end
15
+ end
16
+
17
+ @@control_type_map = {
18
+ :button => System::Windows::Automation::ControlType.Button,
19
+ :calendar => System::Windows::Automation::ControlType.Calendar,
20
+ :check_box => System::Windows::Automation::ControlType.CheckBox,
21
+ :combo_box => System::Windows::Automation::ControlType.ComboBox,
22
+ :custom => System::Windows::Automation::ControlType.Custom,
23
+ :data_grid => System::Windows::Automation::ControlType.DataGrid,
24
+ :data_item => System::Windows::Automation::ControlType.DataItem,
25
+ :document => System::Windows::Automation::ControlType.Document,
26
+ :edit => System::Windows::Automation::ControlType.Edit,
27
+ :group => System::Windows::Automation::ControlType.Group,
28
+ :header => System::Windows::Automation::ControlType.Header,
29
+ :header_item => System::Windows::Automation::ControlType.HeaderItem,
30
+ :hyperlink => System::Windows::Automation::ControlType.Hyperlink,
31
+ :image => System::Windows::Automation::ControlType.Image,
32
+ :list => System::Windows::Automation::ControlType.List,
33
+ :list_item => System::Windows::Automation::ControlType.ListItem,
34
+ :menu => System::Windows::Automation::ControlType.Menu,
35
+ :menu_bar => System::Windows::Automation::ControlType.MenuBar,
36
+ :menu_item => System::Windows::Automation::ControlType.MenuItem,
37
+ :pane => System::Windows::Automation::ControlType.Pane,
38
+ :progress_bar => System::Windows::Automation::ControlType.ProgressBar,
39
+ :radio_button => System::Windows::Automation::ControlType.RadioButton,
40
+ :scroll_bar => System::Windows::Automation::ControlType.ScrollBar,
41
+ :seperator => System::Windows::Automation::ControlType.Separator,
42
+ :slider => System::Windows::Automation::ControlType.Slider,
43
+ :spinner => System::Windows::Automation::ControlType.Spinner,
44
+ :split_button => System::Windows::Automation::ControlType.SplitButton,
45
+ :status_bar => System::Windows::Automation::ControlType.StatusBar,
46
+ :tab => System::Windows::Automation::ControlType.Tab,
47
+ :tab_item => System::Windows::Automation::ControlType.TabItem,
48
+ :table => System::Windows::Automation::ControlType.Table,
49
+ :text => System::Windows::Automation::ControlType.Text,
50
+ :thumb => System::Windows::Automation::ControlType.Thumb,
51
+ :title_bar => System::Windows::Automation::ControlType.TitleBar,
52
+ :tool_bar => System::Windows::Automation::ControlType.ToolBar,
53
+ :tool_tip => System::Windows::Automation::ControlType.ToolTip,
54
+ :tree => System::Windows::Automation::ControlType.Tree,
55
+ :tree_item => System::Windows::Automation::ControlType.TreeItem,
56
+ :window => System::Windows::Automation::ControlType.Window
57
+ }
58
+ end
59
+ end
@@ -0,0 +1,87 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlTypeAdditions
5
+ module ComboBoxAdditions
6
+ def self.extended(base)
7
+ base.extend Bewildr::ControlPatterns::ExpandCollapsePattern
8
+ base.extend Bewildr::ControlPatterns::SelectionPattern
9
+ base.extend Bewildr::ControlPatterns::SelectionItemPattern
10
+
11
+ base.instance_eval do
12
+ def items
13
+ my_list_items = list_items
14
+ return nil if my_list_items.nil?
15
+ my_list_items.collect {|item| item.name}
16
+ end
17
+
18
+ def list_items
19
+ begin
20
+ expand_combo
21
+ bewildr_list_items = get(:type => :list_item, :scope => :children)
22
+ bewildr_list_items.nil? ? nil : bewildr_list_items
23
+ ensure
24
+ collapse_combo
25
+ end
26
+ end
27
+
28
+ def count
29
+ my_items = items
30
+ my_items.nil? ? 0 : my_items.size
31
+ end
32
+
33
+ def select(input)
34
+ case input
35
+ when String then select_by_name(input)
36
+ when Integer then select_by_index(input)
37
+ else raise ArgumentError, "Select by name or by index"
38
+ end
39
+ end
40
+
41
+ def select_by_name(input)
42
+ begin
43
+ expand_combo
44
+ my_item = list_items.find {|item| item.name == input}
45
+ raise NoSuchItemInComboBox if my_item.nil?
46
+ my_item.select
47
+ ensure
48
+ collapse_combo
49
+ end
50
+ end
51
+
52
+ def select_by_index(input)
53
+ raise "Index must be 0 or greater" if input < 0
54
+ begin
55
+ expand_combo
56
+ my_item = list_items[input].select
57
+ ensure
58
+ collapse_combo
59
+ end
60
+ end
61
+
62
+ def selected
63
+ #TODO: find a way to not need to expand and collapse before getting the selected item
64
+ expand_combo
65
+ collapse_combo
66
+ #get_selection.first
67
+ get_selection.first.name
68
+ end
69
+
70
+ def expand_combo
71
+ expand
72
+ Timeout.timeout(30) do
73
+ sleep 0.2 until expand_state == :expanded
74
+ end
75
+ end
76
+
77
+ def collapse_combo
78
+ collapse
79
+ Timeout.timeout(30) do
80
+ sleep 0.2 until expand_state == :collapsed
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,16 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlTypeAdditions
5
+ module DataGridAdditions
6
+ def self.extended(base)
7
+ base.extend Bewildr::ControlPatterns::GridPattern
8
+ base.extend Bewildr::ControlPatterns::TablePattern
9
+
10
+ base.instance_eval do
11
+
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlTypeAdditions
5
+ module ListAdditions
6
+ def self.extended(base)
7
+ base.extend Bewildr::ControlPatterns::SelectionPattern
8
+
9
+ base.instance_eval do
10
+ def select(input)
11
+ selectable_elements = get(:type => :list_item, :scope => :children)
12
+ selectable_elements.find {|selectable_element| selectable_element.name == input}.select
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,60 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlTypeAdditions
5
+ module MenuAdditions
6
+ def self.extended(base)
7
+ base.extend Bewildr::ControlPatterns::ExpandCollapsePattern
8
+ base.extend Bewildr::ControlPatterns::SelectionPattern
9
+ base.extend Bewildr::ControlPatterns::SelectionItemPattern
10
+
11
+ base.instance_eval do
12
+ def root_menu_items
13
+ get(:type =>:menu_item, :scope => :children)
14
+ end
15
+
16
+ def select_menu(path)
17
+ menu_item(path).click
18
+ end
19
+
20
+ def select_node(path)
21
+ node(path).select
22
+ end
23
+
24
+ def menu_item(path)
25
+ current_menu_items = root_menu_items
26
+ matching_menu_item = nil
27
+ path.each_with_index do |target_menu_item, index|
28
+ case current_menu_items
29
+ when Array
30
+ matching_menu_item = current_menu_items.find {|node| node.name == target_menu_item} #TODO: make this work with regexes as well as strings...
31
+ raise ElementDoesntExist if matching_menu_item.nil?
32
+ when Bewildr::Element
33
+ if current_menu_items.name == target_menu_item #TODO: make this work with regexes as well as strings...
34
+ matching_menu_item = current_menu_items
35
+ else
36
+ raise ElementDoesntExist
37
+ end
38
+ end
39
+ raise ElementDoesntExist if matching_menu_item.nil?
40
+ if path.size != index + 1
41
+ matching_menu_item.expand
42
+ current_menu_items = matching_menu_item.sub_menus
43
+ end
44
+ end
45
+ return matching_menu_item
46
+ end
47
+
48
+ def contains_menu_item?(path)
49
+ begin
50
+ menu_item(path)
51
+ return true
52
+ rescue ElementDoesntExist => e
53
+ return false
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,18 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlTypeAdditions
5
+ module MenuItemAdditions
6
+ def self.extended(base)
7
+ base.extend Bewildr::ControlPatterns::ExpandCollapsePattern
8
+ base.extend Bewildr::ControlPatterns::InvokePattern
9
+
10
+ base.instance_eval do
11
+ def sub_menus
12
+ get(:type => :menu_item, :scope => :children)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlTypeAdditions
5
+ module TabAdditions
6
+ def self.extended(base)
7
+ base.extend Bewildr::ControlPatterns::SelectionPattern
8
+
9
+ base.instance_eval do
10
+ def select(input)
11
+ selectable_elements = get(:type => :tab_item, :scope => :children)
12
+ selectable_elements.find {|selectable_element| selectable_element.name == input}.select
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlTypeAdditions
5
+ module TextAdditions
6
+ def self.extended(base)
7
+ base.instance_eval do
8
+ def text
9
+ existence_check
10
+ name
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,59 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlTypeAdditions
5
+ module TreeAdditions
6
+ def self.extended(base)
7
+ base.extend Bewildr::ControlPatterns::ExpandCollapsePattern
8
+ base.extend Bewildr::ControlPatterns::SelectionPattern
9
+
10
+ base.instance_eval do
11
+ def root_nodes
12
+ get(:type => :tree_item, :scope => :children)
13
+ end
14
+
15
+ def root_node
16
+ root_nodes.first
17
+ end
18
+
19
+ def select_node(path)
20
+ node(path).select
21
+ end
22
+
23
+ def node(path)
24
+ current_nodes = root_nodes
25
+ matching_node = nil
26
+ path.each_with_index do |target_node, index|
27
+ case current_nodes
28
+ when Array
29
+ matching_node = current_nodes.find {|node| node.name == target_node} #TODO: make this work with regexes as well as strings...
30
+ raise ElementDoesntExist if matching_node.nil?
31
+ when Bewildr::Element
32
+ if current_nodes.name == target_node #TODO: make this work with regexes as well as strings...
33
+ matching_node = current_nodes
34
+ else
35
+ raise ElementDoesntExist
36
+ end
37
+ end
38
+ raise ElementDoesntExist if matching_node.nil?
39
+ if path.size != index + 1
40
+ matching_node.expand
41
+ current_nodes = matching_node.child_nodes
42
+ end
43
+ end
44
+ return matching_node
45
+ end
46
+
47
+ def contains_node?(path)
48
+ begin
49
+ node(path)
50
+ return true
51
+ rescue ElementDoesntExist => e
52
+ return false
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,18 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlTypeAdditions
5
+ module TreeItemAdditions
6
+ def self.extended(base)
7
+ base.extend Bewildr::ControlPatterns::ExpandCollapsePattern
8
+ base.extend Bewildr::ControlPatterns::SelectionItemPattern
9
+
10
+ base.instance_eval do
11
+ def child_nodes
12
+ get(:type => :tree_item, :scope => :children)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ module ControlTypeAdditions
5
+ module WindowAdditions
6
+ def self.extended(base)
7
+ base.extend Bewildr::ControlPatterns::WindowPattern
8
+
9
+ base.instance_eval do
10
+ def open?
11
+ exists?
12
+ end
13
+
14
+ def wait_for_close
15
+ Timeout::timeout(30) do
16
+ sleep 0.2 while open?
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,171 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ class Element
5
+ attr_reader :automation_element
6
+ attr_reader :control_type
7
+
8
+ def initialize(input)
9
+ @automation_element = input
10
+ case input
11
+ when System::Windows::Automation::AutomationElement
12
+ set_control_type
13
+ build_element
14
+ when nil then @control_type = :non_existent
15
+ else raise BewildrInternalError, "Can only initialize an element with a nil or a Sys::Win::Auto::AE[C], not a #{input.class}"
16
+ end
17
+ end
18
+
19
+ def name
20
+ existence_check
21
+ @automation_element.current.name.to_s
22
+ end
23
+
24
+ def id
25
+ existence_check
26
+ @automation_element.current.automation_id.to_s
27
+ end
28
+
29
+ def exists?
30
+ return false if @control_type == :non_existent
31
+ begin
32
+ @automation_element.current.bounding_rectangle
33
+ return true
34
+ rescue System::Windows::Automation::ElementNotAvailableException, TypeError => e
35
+ return false
36
+ end
37
+ end
38
+ alias :exist? :exists?
39
+
40
+ def contains?(condition_hash)
41
+ get(condition_hash).exists?
42
+ end
43
+ alias :contain? :contains?
44
+
45
+ def existence_check
46
+ raise ElementDoesntExist unless exists?
47
+ end
48
+ private :existence_check
49
+
50
+ def enabled?
51
+ existence_check
52
+ @automation_element.current.is_enabled
53
+ end
54
+
55
+ #:id => "id"
56
+ #:name => "bob"
57
+ #:type => :button
58
+ #:scope => :children / :descendants
59
+ #:how_many => :first / :all
60
+ def get(condition_hash)
61
+ existence_check
62
+ condition = Finder.condition_for(condition_hash)
63
+ scope = Finder.scope_for(condition_hash)
64
+ how_many = Finder.how_many_for(condition_hash)
65
+
66
+ result = @automation_element.send how_many, scope, condition
67
+ case result
68
+ when System::Windows::Automation::AutomationElement, nil then return Bewildr::Element.new(result)
69
+ when System::Windows::Automation::AutomationElementCollection
70
+ c_array_list = System::Collections::ArrayList.new(result)
71
+ element_array = c_array_list.to_array.to_a
72
+ case
73
+ when element_array.size == 0 then return Bewildr::Element.new(nil)
74
+ when element_array.size == 1 then return Bewildr::Element.new(element_array.first)
75
+ when element_array.size > 1 then return element_array.collect {|element| Bewildr::Element.new(element) }
76
+ end
77
+ end
78
+ end
79
+
80
+ #add "children/child" and "descendants/descendant" methods
81
+
82
+ def children
83
+ get({:scope => :children}).collect {|element| Bewildr::Element.new(element)}
84
+ end
85
+
86
+ def click
87
+ CLICKR.click(clickable_point)
88
+ end
89
+
90
+ def double_click
91
+ CLICKR.double_click(clickable_point)
92
+ end
93
+
94
+ def right_click
95
+ CLICKR.right_click(clickable_point)
96
+ end
97
+
98
+ def clickable_point
99
+ existence_check
100
+ @automation_element.get_clickable_point
101
+ end
102
+
103
+ private
104
+
105
+ def set_control_type
106
+ @control_type = Bewildr::ControlType.symbol_for_enum(@automation_element.current.control_type)
107
+ end
108
+
109
+ #list of control types comes from http://msdn.microsoft.com/en-us/library/ms750574.aspx
110
+ def build_element
111
+ case @control_type
112
+ when :button
113
+ when :calendar
114
+ when :check_box
115
+ extend Bewildr::ControlPatterns::TogglePattern
116
+ when :combo_box
117
+ extend Bewildr::ControlTypeAdditions::ComboBoxAdditions
118
+ when :custom
119
+ when :data_grid
120
+ extend Bewildr::ControlTypeAdditions::DataGridAdditions
121
+ when :data_item
122
+ when :document
123
+ when :edit
124
+ extend Bewildr::ControlPatterns::ValuePattern
125
+ when :group
126
+ when :header
127
+ when :header_item
128
+ when :hyperlink
129
+ extend Bewildr::ControlTypeAdditions::TextAdditions
130
+ when :image
131
+ when :list
132
+ extend Bewildr::ControlTypeAdditions::ListAdditions
133
+ when :list_item
134
+ extend Bewildr::ControlPatterns::SelectionItemPattern
135
+ when :menu
136
+ extend Bewildr::ControlTypeAdditions::MenuAdditions
137
+ when :menu_bar
138
+ when :menu_item
139
+ extend Bewildr::ControlTypeAdditions::MenuItemAdditions
140
+ when :pane
141
+ when :progress_bar
142
+ extend Bewildr::ControlPatterns::RangeValuePattern
143
+ when :radio_button
144
+ extend Bewildr::ControlPatterns::SelectionItemPattern
145
+ when :scroll_bar
146
+ when :seperator
147
+ when :slider
148
+ when :spinner
149
+ when :split_button
150
+ when :status_bar
151
+ when :tab
152
+ extend Bewildr::ControlTypeAdditions::TabAdditions
153
+ when :tab_item
154
+ extend Bewildr::ControlPatterns::SelectionItemPattern
155
+ when :table
156
+ when :text
157
+ extend Bewildr::ControlTypeAdditions::TextAdditions
158
+ when :thumb
159
+ when :title_bar
160
+ when :tool_bar
161
+ when :tool_tip
162
+ when :tree
163
+ extend Bewildr::ControlTypeAdditions::TreeAdditions
164
+ when :tree_item
165
+ extend Bewildr::ControlTypeAdditions::TreeItemAdditions
166
+ when :window
167
+ extend Bewildr::ControlTypeAdditions::WindowAdditions
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,8 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ class ElementNotEnabled < StandardError; end
4
+ class ElementDoesntExist < StandardError; end
5
+ class PasswordFieldReadAttempt < StandardError; end
6
+ class NoSuchItemInComboBox < StandardError; end
7
+
8
+ class BewildrInternalError < StandardError; end
@@ -0,0 +1,66 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ class Finder
5
+ extend Bewildr::BewildrHelpers
6
+
7
+ class << self
8
+ def condition_for(condition_hash)
9
+ conditions = condition_hash.select {|key, value| [:id, :name, :type].include?(key) }
10
+ conditions = Hash[*conditions.flatten]
11
+ case
12
+ when conditions.length == 0 then raise "Condition needs to include at least an :id, a :name or a :type"
13
+ when conditions.length == 1 then return single_condition(conditions)
14
+ when conditions.length > 1 then return multiple_conditions(conditions)
15
+ end
16
+ end
17
+
18
+ def scope_for(condition_hash)
19
+ case condition_hash[:scope]
20
+ when :children then System::Windows::Automation::TreeScope.Children
21
+ when :descendants, nil then System::Windows::Automation::TreeScope.Descendants
22
+ end
23
+ end
24
+
25
+ #returns the method to call
26
+ def how_many_for(condition_hash)
27
+ case condition_hash[:how_many]
28
+ when :first then :find_first
29
+ when :all, nil then :find_all
30
+ else raise "Invalid number of elements to look for. Use ':first' or ':all'"
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def multiple_conditions(condition_hash)
37
+ condition_array = []
38
+ condition_hash.keys.each {|key| condition_array << single_condition({key => condition_hash[key]}) }
39
+ System::Windows::Automation::AndCondition.new(r_array_to_cs_array_of_conditions(condition_array))
40
+ end
41
+
42
+ def single_condition(condition_hash)
43
+ case condition_hash.keys.first
44
+ when :id then id_condition(condition_hash)
45
+ when :name then name_condition(condition_hash)
46
+ when :type then type_condition(condition_hash)
47
+ end
48
+ end
49
+
50
+ def id_condition(condition_hash)
51
+ value = r_string_to_c_string(condition_hash[:id].to_s)
52
+ System::Windows::Automation::PropertyCondition.new(System::Windows::Automation::AutomationElement.automation_id_property, value)
53
+ end
54
+
55
+ def name_condition(condition_hash)
56
+ value = r_string_to_c_string(condition_hash[:name])
57
+ System::Windows::Automation::PropertyCondition.new(System::Windows::Automation::AutomationElement.name_property, value)
58
+ end
59
+
60
+ def type_condition(condition_hash)
61
+ value = Bewildr::ControlType.class_for_symbol(condition_hash[:type])
62
+ System::Windows::Automation::PropertyCondition.new(System::Windows::Automation::AutomationElement.control_type_property, value)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,23 @@
1
+ #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
+
3
+ module Bewildr
4
+ class Windows
5
+ def self.windows_by_process_id(process_id)
6
+ #find top level windows
7
+ window_scope = System::Windows::Automation::TreeScope.Children
8
+ process_id_property = System::Windows::Automation::PropertyCondition.new(System::Windows::Automation::AutomationElement.process_id_property, process_id.to_i)
9
+ top_level_windows = System::Windows::Automation::AutomationElement.root_element.find_all(window_scope, process_id_property).to_a
10
+
11
+ all_windows = []
12
+ all_windows << top_level_windows
13
+
14
+ #loop through the top level windows looking for child windows
15
+ top_level_windows.each do |top_level_window|
16
+ control_type_property = System::Windows::Automation::PropertyCondition.new(System::Windows::Automation::AutomationElement.control_type_property, System::Windows::Automation::ControlType.Window)
17
+ all_windows << top_level_window.find_all(window_scope, control_type_property).to_a
18
+ end
19
+
20
+ all_windows.flatten.collect {|window| Bewildr::Element.new(window)}
21
+ end
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bewildr
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ version: "0.1"
9
+ platform: ruby
10
+ authors:
11
+ - Nat Ritmeyer
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-04-20 00:00:00 +01:00
17
+ default_executable:
18
+ dependencies: []
19
+
20
+ description: Test your WPF apps with (iron) ruby!
21
+ email: nat@natontesting.com
22
+ executables: []
23
+
24
+ extensions: []
25
+
26
+ extra_rdoc_files:
27
+ - README
28
+ - LICENSE
29
+ files:
30
+ - LICENSE
31
+ - README
32
+ - Rakefile
33
+ - lib/bewildr/application.rb
34
+ - lib/bewildr/bewildr_helpers.rb
35
+ - lib/bewildr/control_patterns/expand_collapse_pattern.rb
36
+ - lib/bewildr/control_patterns/grid_pattern.rb
37
+ - lib/bewildr/control_patterns/invoke_pattern.rb
38
+ - lib/bewildr/control_patterns/range_value_pattern.rb
39
+ - lib/bewildr/control_patterns/selection_item_pattern.rb
40
+ - lib/bewildr/control_patterns/selection_pattern.rb
41
+ - lib/bewildr/control_patterns/table_pattern.rb
42
+ - lib/bewildr/control_patterns/toggle_pattern.rb
43
+ - lib/bewildr/control_patterns/value_pattern.rb
44
+ - lib/bewildr/control_patterns/window_pattern.rb
45
+ - lib/bewildr/control_type.rb
46
+ - lib/bewildr/control_type_additions/combo_box_additions.rb
47
+ - lib/bewildr/control_type_additions/data_grid_additions.rb
48
+ - lib/bewildr/control_type_additions/list_additions.rb
49
+ - lib/bewildr/control_type_additions/menu_additions.rb
50
+ - lib/bewildr/control_type_additions/menu_item_additions.rb
51
+ - lib/bewildr/control_type_additions/tab_additions.rb
52
+ - lib/bewildr/control_type_additions/text_additions.rb
53
+ - lib/bewildr/control_type_additions/tree_additions.rb
54
+ - lib/bewildr/control_type_additions/tree_item_additions.rb
55
+ - lib/bewildr/control_type_additions/window_additions.rb
56
+ - lib/bewildr/element.rb
57
+ - lib/bewildr/exceptions.rb
58
+ - lib/bewildr/ext/BewildrClickr.dll
59
+ - lib/bewildr/finder.rb
60
+ - lib/bewildr/windows.rb
61
+ - lib/bewildr.rb
62
+ has_rdoc: true
63
+ homepage: http://github.com/natritmeyer/bewildr
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ requirements: []
86
+
87
+ rubyforge_project:
88
+ rubygems_version: 1.3.6
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Test your WPF apps with (iron) ruby!
92
+ test_files: []
93
+