bryan-ash-wx-nobbie 0.0.3.2

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.
@@ -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
data/test/all_tests.rb ADDED
@@ -0,0 +1,8 @@
1
+
2
+ $LOAD_PATH.unshift '../lib'
3
+
4
+ require 'rubygems'
5
+ require 'nobbie/wx/acceptance_test'
6
+ require_all_in_directory [File.dirname(__FILE__), 'suite'].join(File::SEPARATOR)
7
+
8
+ APPLICATION_UNDER_TEST = TestApp.new
data/test/suite/app.rb ADDED
@@ -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