wx-nobbie 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,85 @@
1
+ require 'nobbie/wx/platform'
2
+ require 'nobbie/wx/command_factory'
3
+ require 'nobbie/wx/launcher'
4
+
5
+ impl = File.dirname(__FILE__) + File::SEPARATOR + 'impl'
6
+ Dir.glob("#{impl}/**/*.rb") {|f| require "#{f}" }
7
+
8
+ module Nobbie
9
+ module Wx
10
+
11
+ module Operations
12
+
13
+ # Types text into the component specified in the path.
14
+ # Supported components: TextCtrl, ComboBox
15
+ def type(text, path)
16
+ execute(command_factory.create_type_into_command(coerce_path(path), text))
17
+ end
18
+
19
+ # Clicks the component specified in the path.
20
+ # Supported components: Button
21
+ def click(path)
22
+ execute(command_factory.create_click_on_command(coerce_path(path)))
23
+ end
24
+
25
+ # Returns the component specified in the path. Useful for performing operations that Nobbie does not
26
+ # currently support.
27
+ # Supported components: Any
28
+ def component(path)
29
+ execute(command_factory.create_get_component_command(coerce_path(path)))
30
+ end
31
+
32
+ # Returns a SelectionOperations[link:classes/Nobbie/Wx/SelectOperations.html] for interacting with
33
+ # the component specified in the path
34
+ def selection(path)
35
+ SelectOperations.new(self, coerce_path(path))
36
+ end
37
+
38
+ # Returns a ChoosableOperations[link:classes/Nobbie/Wx/ChoosableOperations.html] for interacting with
39
+ # the component specified in the path
40
+ def choosable(path)
41
+ ChoosableOperations.new(self, coerce_path((path)))
42
+ end
43
+
44
+ # Determines if the component specified in the path is currently enabled.
45
+ # Supported components: Any
46
+ def enabled?(path)
47
+ execute(command_factory.create_is_enabled_command(coerce_path(path)))
48
+ end
49
+
50
+ # Creates an instance of the default {path builder}[link:classes/Nobbie/Wx/ElementPathBuilder.html].
51
+ # Override this method if you wish to provide an alternative default path builder (because coerce_path
52
+ # uses in_() internally).
53
+ def in_(name)
54
+ ElementPathBuilder.new(name)
55
+ end
56
+
57
+ # Creates an instance of the default {command factory}[link:classes/Nobbie/Wx/CommandFactory.html].
58
+ # Override this method if you wish to provide an alternative command factory.
59
+ def command_factory
60
+ Command::Factory.new
61
+ end
62
+
63
+ private
64
+
65
+ def coerce_path(path)
66
+ return path if path.respond_to?(:find_component)
67
+
68
+ if path.is_a?(Hash) && path.has_key?(:in)
69
+ return path[:in].is_a?(String) ? in_(path[:in]) : path[:in]
70
+ end
71
+
72
+ return in_(path.id2name) if path.is_a?(Symbol)
73
+ return in_(path) if path.is_a?(String)
74
+
75
+ Kernel.raise("Unable to coerce path: #{path}")
76
+ end
77
+
78
+ #todo: pull up
79
+ def execute(command)
80
+ Command::Executor.new.execute(command)
81
+ end
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'wx'
3
+
4
+ #todo: move this into Nobbie::Wx namespace ... once name clash is fixed
5
+ class Platform #:nodoc:
6
+ include Wx
7
+
8
+ WINDOWS = 'WXMSW'
9
+ MAC = 'WXMAC'
10
+ SUPPORTED_PLATFORMS = [WINDOWS, MAC]
11
+
12
+ def self.windows?
13
+ name == WINDOWS
14
+ end
15
+
16
+ def self.ensure_supported
17
+ Kernel.raise "Sorry '#{name}' is not currently supported, Nobbie-Wx is only available for the following platforms: [#{SUPPORTED_PLATFORMS.join(',')}]" unless supported?
18
+ end
19
+
20
+ private
21
+
22
+ def self.supported?
23
+ SUPPORTED_PLATFORMS.include?(name)
24
+ end
25
+
26
+ def self.name
27
+ Wx::PLATFORM
28
+ end
29
+ end
30
+
31
+ Platform.ensure_supported
@@ -0,0 +1,6 @@
1
+
2
+ require 'rubygems'
3
+ require_gem 'nobbie-wx'
4
+ require_all_in_directory [File.dirname(__FILE__), 'suite'].join(File::SEPARATOR)
5
+
6
+ APPLICATION_UNDER_TEST = TestApp.new
@@ -0,0 +1,144 @@
1
+ require 'rubygems'
2
+ require 'wx'
3
+ require 'wx_sugar'
4
+
5
+ include Wx
6
+
7
+ class TestFrame < Frame
8
+ def initialize(*args)
9
+ super
10
+
11
+ #todo: sort out all this :minsize => true stuff out .. need some way to specify defaults
12
+
13
+ panel = add(Panel, :proportion => 1)
14
+ panel.arrange_vertically(:padding => 4)
15
+
16
+ test_notebook = name('test_notebook', panel.add(Notebook, :minsize => true, :proportion => 2))
17
+
18
+ test_notebook.add_page(name('type', test_notebook.add(Panel) {|p| p.arrange_vertically
19
+ listen(:text, name('text_ctrl', p.add(TextCtrl[:value => 'text_ctrl'], :minsize => true)), :update)
20
+ listen(:text, name('readonly_text_ctrl', p.add(TextCtrl[:value => 'readonly_text_ctrl', :style => TE_READONLY], :minsize => true)), :update)
21
+ listen(:text, disable(name('disabled_text_ctrl', p.add(TextCtrl[:value => 'disabled_text_ctrl'], :minsize => true))), :update)
22
+
23
+ listen(:text, name('combo_box', p.add(ComboBox[:value => 'combo_box'], :minsize => true)), :update)
24
+ readonly_combo_box = name('readonly_combo_box', p.add(ComboBox[:style => CB_READONLY], :minsize => true))
25
+ readonly_combo_box.append('readonly_combo_box')
26
+ readonly_combo_box.selection = 0
27
+ listen(:text, readonly_combo_box, :update)
28
+ listen(:text, disable(name('disabled_combo_box', p.add(ComboBox[:value => 'disabled_combo_box'], :minsize => true))), :update)
29
+ }), 'type')
30
+
31
+ test_notebook.add_page(name('click', test_notebook.add(Panel, :minsize => true) {|p| p.arrange_vertically
32
+ listen(:button, name('button', p.add(Button[:label => 'regular_button'], :minsize => true)), :update)
33
+ listen(:button, name('labelled_button_name', p.add(Button[:label => 'labelled_button'], :minsize => true)), :update)
34
+ listen(:button, disable(name('disabled_button', p.add(Button[:label => 'disabled_button'], :minsize => true))), :update)
35
+ name('static_text', p.add(StaticText[:label => 'static_text'], :minsize => true))
36
+ }), 'click')
37
+
38
+ test_notebook.add_page(name('selection', test_notebook.add(Panel) {|p| p.arrange_vertically
39
+ notebook = name('notebook', p.add(Notebook, :minsize => true))
40
+ notebook.add_page(name('notebook_page1', notebook.add(Panel)), 'notebook_page1')
41
+ notebook.add_page(name('notebook_page2', notebook.add(Panel)), 'notebook_page2')
42
+ notebook.evt_notebook_page_changing(notebook.get_id()) {|e| update(e) }
43
+
44
+ disabled_notebook = disable(name('disabled_notebook', p.add(Notebook, :minsize => true)))
45
+ disabled_notebook.add_page(name('disabled_notebook_page1', disabled_notebook.add(Panel)), 'disabled_notebook_page1')
46
+ disabled_notebook.add_page(name('disabled_notebook_page2', disabled_notebook.add(Panel)), 'disabled_notebook_page2')
47
+ disabled_notebook.evt_notebook_page_changing(disabled_notebook.get_id()) {|e| update(e) }
48
+
49
+ #todo: make me have a visible name on screen
50
+ combo_box_with_items = name('combo_box_with_items', p.add(ComboBox, :minsize => true))
51
+ combo_box_with_items.append('combo_box_item')
52
+ listen(:combobox, combo_box_with_items, :update)
53
+
54
+ disabled_combo_box_with_items = disable(name('disabled_combo_box_with_items', p.add(ComboBox, :minsize => true)))
55
+ disabled_combo_box_with_items.append('disabled_combo_box_item1')
56
+ disabled_combo_box_with_items.append('disabled_combo_box_item2')
57
+ listen(:combobox, disabled_combo_box_with_items, :update)
58
+
59
+ list_box_with_items = name('list_box_with_items', p.add(ListBox, :minsize => true))
60
+ list_box_with_items.append('list_box_item')
61
+ listen(:listbox, list_box_with_items, :update)
62
+
63
+ disabled_list_box_with_items = disable(name('disabled_list_box_with_items', p.add(ListBox, :minsize => true)))
64
+ disabled_list_box_with_items.append('disabled_list_box_item1')
65
+ disabled_list_box_with_items.append('disabled_list_box_item2')
66
+ listen(:listbox, disabled_list_box_with_items, :update)
67
+
68
+ choice_with_items = name('choice_with_items', p.add(Choice, :minsize => true))
69
+ choice_with_items.append('choice_item')
70
+ listen(:choice, choice_with_items, :update)
71
+
72
+ disabled_choice_with_items = disable(name('disabled_choice_with_items', p.add(Choice, :minsize => true)))
73
+ disabled_choice_with_items.append('disabled_choice_item1')
74
+ disabled_choice_with_items.append('disabled_choice_item2')
75
+ listen(:choice, disabled_choice_with_items, :update)
76
+
77
+ }), 'selection')
78
+
79
+ test_notebook.add_page(name('choose', test_notebook.add(Panel) {|p| p.arrange_vertically
80
+ #todo: make me have a visible name on screen
81
+ listen(:radiobutton, name('radio_button', p.add(RadioButton, :minsize => true)), :update)
82
+
83
+ #todo: make me have a visible name on screen
84
+ listen(:radiobutton, disable(name('disabled_radio_button', p.add(RadioButton, :minsize => true))), :update)
85
+
86
+ #todo: make me have a visible name on screen
87
+ listen(:checkbox, name('check_box', p.add(CheckBox, :minsize => true)), :update)
88
+
89
+ #todo: make me have a visible name on screen
90
+ listen(:checkbox, disable(name('disabled_check_box', p.add(CheckBox, :minsize => true))), :update)
91
+
92
+ }), 'choose')
93
+
94
+ @log = name('log', panel.add(TextCtrl[:style => TE_READONLY | TE_MULTILINE], :minsize => true, :proportion => 1))
95
+
96
+ menu_bar = MenuBar.new
97
+ file_menu = Menu.new
98
+
99
+ #todo: remove these crappy id's ... there must be a nice sugary way to build menu's
100
+ file_new = file_menu.append(101, "&New...\tCtrl+N")
101
+ file_disabled = file_menu.append(102, "&disabled")
102
+
103
+ menu_bar.append(file_menu, '&File')
104
+ set_menu_bar(menu_bar)
105
+
106
+ #todo: make disable() handle menus ...
107
+ menu_bar.enable(102, false)
108
+
109
+ #todo: make update() handle menus ...
110
+ listen(:menu, @file_new) {|e| log('file_new') }
111
+ end
112
+
113
+ def on_init
114
+ self.update
115
+ end
116
+
117
+ private
118
+
119
+ def name(name, component)
120
+ component.name = name
121
+ component
122
+ end
123
+
124
+ def disable(component)
125
+ component.disable
126
+ component
127
+ end
128
+
129
+ def log(text)
130
+ @log.append_text(text)
131
+ end
132
+
133
+ def update(e)
134
+ @log.append_text("#{e.event_object.name}: #{e.string}\n")
135
+ end
136
+ end
137
+
138
+ class TestApp < App
139
+ def on_init
140
+ TestFrame.new(nil, :title => 'test', :size => [1024, 768]).show
141
+ end
142
+ end
143
+
144
+ TestApp.new.main_loop if __FILE__ == $0
@@ -0,0 +1,46 @@
1
+ module NobbieTestCase
2
+ include Nobbie::Wx
3
+
4
+ def setup
5
+ puts "\n[Started: #{name}]"
6
+ begin
7
+ select_tab_for_test
8
+ rescue ValueNotFoundException
9
+ #ok - this test doesn't have its own tab'
10
+ end
11
+ end
12
+
13
+ def teardown
14
+ puts "\n[Finished: #{name}]"
15
+ end
16
+
17
+ def select_tab_for_test
18
+ clear_events
19
+ tab = self.class.name.gsub('Test', '').downcase
20
+ selection(:in => 'test_notebook').choose tab
21
+ assert_equal tab, selection(:in => 'test_notebook').selected_value
22
+ end
23
+
24
+ def text(component)
25
+ component.nil? ? nil : component.value
26
+ end
27
+
28
+ def clear_events
29
+ log.clear
30
+ end
31
+
32
+ def assert_exception(e)
33
+ assert_raise e do yield end
34
+ assert_events
35
+ end
36
+
37
+ def assert_events(expected_items=[])
38
+ expected_items = [expected_items] unless expected_items.is_a?(Array)
39
+ actual_items = text(log).split("\n")
40
+ assert_equal expected_items, actual_items
41
+ end
42
+
43
+ def log
44
+ component 'log'
45
+ end
46
+ end
@@ -0,0 +1,52 @@
1
+ class TestChoose < Test::Unit::TestCase
2
+ include NobbieTestCase
3
+
4
+ #todo: rename file to choosable
5
+ #todo: should be TestChoosable
6
+ def test_choose_with_radio_button
7
+ assert !choosable('radio_button').chosen?
8
+ choosable('radio_button').choose
9
+ assert choosable('radio_button').chosen?
10
+ assert_events 'radio_button: '
11
+ end
12
+
13
+ def test_choose_with_check_box
14
+ assert !choosable('check_box').chosen?
15
+ choosable('check_box').choose
16
+ assert choosable('check_box').chosen?
17
+ assert_events 'check_box: '
18
+ end
19
+
20
+ def test_choose_with_component_disabled_radio_button
21
+ assert_exception ComponentDisabledException do choosable('disabled_radio_button').choose end
22
+ end
23
+
24
+ def test_choose_with_component_disabled_check_box
25
+ assert_exception ComponentDisabledException do choosable('disabled_check_box').choose end
26
+ end
27
+
28
+ def test_choose_with_unsupported_operation_for_component
29
+ assert_exception UnsupportedOperationForComponentException do choosable('button').choose end
30
+ end
31
+
32
+ def test_choose_with_component_not_found
33
+ assert_exception ComponentNotFoundException do choosable('missing').choose end
34
+ end
35
+
36
+ def test_chosen_with_unsupported_operation_for_component
37
+ assert_exception UnsupportedOperationForComponentException do choosable('button').chosen? end
38
+ end
39
+
40
+ def test_chosen_with_component_not_found
41
+ assert_exception ComponentNotFoundException do choosable('missing').chosen? end
42
+ end
43
+
44
+ def test_chosen_with_component_disabled_radio_button
45
+ assert !choosable('disabled_radio_button').chosen?
46
+ end
47
+
48
+ def test_chosen_with_component_disabled_check_box
49
+ assert !choosable('disabled_check_box').chosen?
50
+ end
51
+ end
52
+
@@ -0,0 +1,28 @@
1
+ class TestClick < Test::Unit::TestCase
2
+ include NobbieTestCase
3
+
4
+ def test_click_with_named_button
5
+ click 'button'
6
+ #todo: improve event detail
7
+ assert_events 'button: '
8
+ end
9
+
10
+ def test_click_with_labelled_button
11
+ click 'labelled_button'
12
+ #todo: improve event detail
13
+ assert_events 'labelled_button_name: '
14
+ end
15
+
16
+ def test_click_with_component_not_found
17
+ assert_exception ComponentNotFoundException do click 'missing' end
18
+ end
19
+
20
+ def test_click_with_component_disabled
21
+ assert_exception ComponentDisabledException do click 'disabled_button' end
22
+ end
23
+
24
+ def test_click_with_unsupported_operation_for_component
25
+ assert_exception UnsupportedOperationForComponentException do click 'static_text' end
26
+ end
27
+ end
28
+
@@ -0,0 +1,13 @@
1
+ class TestEnabled < Test::Unit::TestCase
2
+ include NobbieTestCase
3
+
4
+ def test_enabled
5
+ assert enabled?('text_ctrl')
6
+ assert !enabled?('disabled_text_ctrl')
7
+ end
8
+
9
+ def test_enabled_with_component_not_found
10
+ assert_exception ComponentNotFoundException do enabled?('missing') end
11
+ end
12
+ end
13
+
@@ -0,0 +1,22 @@
1
+ class TestLauncher < Test::Unit::TestCase
2
+
3
+ def test_application_under_test_is_not_defined
4
+ begin
5
+ Nobbie::Wx::ApplicationLauncher.module_eval('def get_application; raise NameError.new; end;')
6
+ Nobbie::Wx::ApplicationLauncher.new
7
+ fail
8
+ rescue RuntimeError => e
9
+ assert_equal Nobbie::Wx::ApplicationLauncher::AUT_NOT_DEFINED, e.message
10
+ end
11
+ end
12
+
13
+ def test_application_under_test_is_not_a_wx_app
14
+ begin
15
+ Nobbie::Wx::ApplicationLauncher.module_eval('def get_application; String.new; end;')
16
+ Nobbie::Wx::ApplicationLauncher.new
17
+ fail
18
+ rescue RuntimeError => e
19
+ assert_equal Nobbie::Wx::ApplicationLauncher::AUT_NOT_WX_APP, e.message
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ class UserPathBuilder
2
+ def find_component
3
+ "something"
4
+ end
5
+ end
6
+
7
+ class TestOperations < Test::Unit::TestCase
8
+
9
+ def test_coerce_path
10
+ assert_path component('text_ctrl')
11
+ assert_path component(:in => 'text_ctrl')
12
+ assert_path component(in_('text_ctrl'))
13
+ assert_path component(Nobbie::Wx::ElementPathBuilder.new('text_ctrl'))
14
+ assert_path component(UserPathBuilder.new)
15
+ assert_path component(:text_ctrl)
16
+ begin
17
+ component(Hash.new)
18
+ fail
19
+ rescue RuntimeError => e
20
+ assert_equal 'Unable to coerce path: ', e.message
21
+ end
22
+ end
23
+
24
+ def assert_path(path)
25
+ assert_not_nil path
26
+ end
27
+ end