bewildr 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+