rugui 1.2.0

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 (56) hide show
  1. data/LICENSE +165 -0
  2. data/README +67 -0
  3. data/README.rdoc +67 -0
  4. data/Rakefile +56 -0
  5. data/VERSION.yml +4 -0
  6. data/bin/rugui +16 -0
  7. data/lib/rugui/base_controller.rb +194 -0
  8. data/lib/rugui/base_model.rb +22 -0
  9. data/lib/rugui/base_object.rb +73 -0
  10. data/lib/rugui/base_view.rb +302 -0
  11. data/lib/rugui/base_view_helper.rb +23 -0
  12. data/lib/rugui/configuration.rb +136 -0
  13. data/lib/rugui/framework_adapters/GTK.rb +233 -0
  14. data/lib/rugui/framework_adapters/Qt4.rb +171 -0
  15. data/lib/rugui/framework_adapters/base_framework_adapter.rb +90 -0
  16. data/lib/rugui/framework_adapters/framework_adapter_support.rb +35 -0
  17. data/lib/rugui/gem_builder.rb +21 -0
  18. data/lib/rugui/gem_dependency.rb +282 -0
  19. data/lib/rugui/initialize_hooks.rb +36 -0
  20. data/lib/rugui/initializer.rb +162 -0
  21. data/lib/rugui/log_support.rb +118 -0
  22. data/lib/rugui/observable_property_proxy.rb +73 -0
  23. data/lib/rugui/observable_property_support.rb +251 -0
  24. data/lib/rugui/plugin/loader.rb +77 -0
  25. data/lib/rugui/property_observer.rb +58 -0
  26. data/lib/rugui/signal_support.rb +57 -0
  27. data/lib/rugui/tasks/gems_application.rake +71 -0
  28. data/lib/rugui/tasks/rugui.rb +8 -0
  29. data/lib/rugui/tasks/rugui_framework.rb +4 -0
  30. data/lib/rugui/tasks/runner_application.rake +4 -0
  31. data/lib/rugui/tasks/spec_application.rake +64 -0
  32. data/lib/rugui/tasks/spec_framework.rake +27 -0
  33. data/lib/rugui/tasks/test_application.rake +77 -0
  34. data/lib/rugui/vendor_gem_source_index.rb +140 -0
  35. data/lib/rugui/version.rb +9 -0
  36. data/lib/rugui.rb +37 -0
  37. data/spec/framework/base_controller_spec.rb +48 -0
  38. data/spec/framework/base_model_spec.rb +13 -0
  39. data/spec/framework/base_view_helper_spec.rb +13 -0
  40. data/spec/framework/base_view_spec.rb +92 -0
  41. data/spec/framework/log_support_spec.rb +16 -0
  42. data/spec/framework/observable_property_proxy_spec.rb +67 -0
  43. data/spec/framework/observable_property_support_spec.rb +283 -0
  44. data/spec/framework/property_observer_spec.rb +88 -0
  45. data/spec/helpers/controllers.rb +29 -0
  46. data/spec/helpers/initialize_hooks_helper.rb +18 -0
  47. data/spec/helpers/models.rb +9 -0
  48. data/spec/helpers/observables.rb +210 -0
  49. data/spec/helpers/view_helpers.rb +9 -0
  50. data/spec/helpers/views.rb +72 -0
  51. data/spec/rcov.opts +1 -0
  52. data/spec/resource_files/my_other_view.glade +46 -0
  53. data/spec/resource_files/my_view.glade +46 -0
  54. data/spec/spec.opts +4 -0
  55. data/spec/spec_helper.rb +15 -0
  56. metadata +149 -0
@@ -0,0 +1,92 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'spec_helper')
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'helpers', 'views')
4
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'helpers', 'view_helpers')
5
+
6
+ describe RuGUI::BaseView do
7
+ before(:each) do
8
+ @my_view = MyView.new
9
+ @my_child_view = MyChildView.new
10
+ @my_other_view = MyOtherView.new
11
+ @my_other_view_instance = MyOtherView.new
12
+ end
13
+
14
+ describe "with view widget registering" do
15
+ it "should make widgets available as attributes in the view class instance" do
16
+ @my_view.top_window.should be_an_instance_of(Gtk::Window)
17
+ @my_view.vertical_container.should be_an_instance_of(Gtk::VBox)
18
+ @my_view.button_above.should be_an_instance_of(Gtk::Button)
19
+ @my_view.button_below.should be_an_instance_of(Gtk::Button)
20
+ @my_view.label.should be_an_instance_of(Gtk::Label)
21
+ end
22
+ end
23
+
24
+ describe "with builder file accessor" do
25
+ it "should return different value for different view classes" do
26
+ @my_view.builder_file.should_not == @my_other_view.builder_file
27
+ end
28
+
29
+ it "should return the same value for same view classes" do
30
+ @my_other_view.builder_file.should == @my_other_view_instance.builder_file
31
+ end
32
+
33
+ it "should return the same value for subclasses which don't override it" do
34
+ @my_view.builder_file.should == @my_child_view.builder_file
35
+ end
36
+ end
37
+
38
+ describe "when creating a view without builder file" do
39
+ it "should not raise error" do
40
+ lambda {
41
+ @no_builder_view_instance = NoBuilderView.new
42
+ }.should_not raise_error(RuGUI::BuilderFileNotFoundError)
43
+ end
44
+ end
45
+
46
+ describe "when including a child view into a parent view" do
47
+ it "should include the root widget of the child view into the specified widget in the parent view" do
48
+ @my_view.include_view :vertical_container, @my_child_view
49
+ @my_view.vertical_container.children.include?(@my_child_view.root_widget).should be_true
50
+ end
51
+ end
52
+
53
+ describe "whent removing a child view from a parent view" do
54
+ before do
55
+ @my_view.include_view :vertical_container, @my_child_view
56
+ end
57
+
58
+ it "should remove the root widget of the child view from the specified widget in the parent view" do
59
+ @my_view.remove_view :vertical_container, @my_child_view
60
+ @my_view.vertical_container.children.include?(@my_child_view.root_widget).should_not be_true
61
+ end
62
+ end
63
+
64
+ describe "with view helpers" do
65
+ it "should include a default view helper automatically if it exists" do
66
+ @my_view.respond_to?(:helper).should be_true
67
+ @my_view.helper.should be_an_instance_of(MyViewHelper)
68
+ end
69
+
70
+ it "should not include a default view helper automatically if it does not exists" do
71
+ @my_other_view.respond_to?(:helper).should be_false
72
+ end
73
+
74
+ it "should notify the view when an observable property is changed in the view helper" do
75
+ @my_view.helper.message = "another message"
76
+ @my_view.message.should == "MyViewHelper property message changed from Some label in the middle to another message"
77
+ end
78
+
79
+ it "should be notified using named observable property change calls" do
80
+ @my_view.my_other_view_helper_instance.message = "foo"
81
+ @my_view.message.should == "Property message of my_other_view_helper_instance changed from Some label in the middle to foo"
82
+ end
83
+ end
84
+
85
+ describe "with initialization hooks" do
86
+ it "should call before initialize and after initialize methods" do
87
+ view = MyView.new
88
+ view.before_initialize_called?.should be_true
89
+ view.after_initialize_called?.should be_true
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,16 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'spec_helper')
2
+
3
+ class MyObjectWithLogSupport
4
+ include RuGUI::LogSupport
5
+ end
6
+
7
+ describe RuGUI::LogSupport do
8
+ before(:each) do
9
+ @my_object_with_log_support = MyObjectWithLogSupport.new
10
+ end
11
+
12
+ it "should have a default logger if it is not initialized" do
13
+ @my_object_with_log_support.respond_to?(:logger).should be_true
14
+ @my_object_with_log_support.logger.should be_an_instance_of(Logger)
15
+ end
16
+ end
@@ -0,0 +1,67 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'spec_helper')
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'helpers', 'observables')
3
+
4
+ describe RuGUI::ObservablePropertyProxy do
5
+ before(:each) do
6
+ @observable = FakeObservable.new
7
+ @custom_type = CustomType.new
8
+ @custom_type.custom_property = "initial_value"
9
+
10
+ @observable_properties = {
11
+ :object => RuGUI::ObservablePropertyProxy.new(Object.new, @observable, :my_object_observable_property),
12
+ :string => RuGUI::ObservablePropertyProxy.new("some_value", @observable, :my_string_observable_property),
13
+ :fixnum => RuGUI::ObservablePropertyProxy.new(1, @observable, :my_fixnum_observable_property),
14
+ :float => RuGUI::ObservablePropertyProxy.new(1.1, @observable, :my_float_observable_property),
15
+ :array => RuGUI::ObservablePropertyProxy.new([], @observable, :my_array_observable_property),
16
+ :hash => RuGUI::ObservablePropertyProxy.new({}, @observable, :my_hash_observable_property),
17
+ :custom_type => RuGUI::ObservablePropertyProxy.new(@custom_type, @observable, :my_custom_type_observable_property),
18
+ }
19
+ end
20
+
21
+ [:object, :string, :fixnum, :float, :array, :hash, :custom_type].each do |type|
22
+ describe "with #{type.to_s.camelize} observable properties" do
23
+ it "should work as proxy for #{type.to_s.camelize} methods" do
24
+ @observable_properties[type].should be_an_instance_of(type.to_s.camelize.constantize)
25
+ type.to_s.camelize.constantize.instance_methods.each do |method_name|
26
+ @observable_properties[type].respond_to?(method_name).should be_true
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ describe "with notification" do
33
+ it "should notifiy the observable when calling methods that changes the observable property" do
34
+ @observable_properties[:string].reverse! # reversing a string
35
+ @observable.property_changed_message.should == "my_string_observable_property changed from some_value to eulav_emos"
36
+
37
+ @observable_properties[:array] << 1 # adding an element into an array
38
+ @observable.property_changed_message.should == "my_array_observable_property changed from to 1"
39
+
40
+ @observable_properties[:hash][:key] = "value" # setting or changing a value in a hash
41
+ @observable.property_changed_message.should == "my_hash_observable_property changed from to keyvalue"
42
+
43
+ @observable_properties[:custom_type].change_custom_property("new_value") # calling a custom method which changes the property
44
+ @observable.property_changed_message.should == "my_custom_type_observable_property changed from initial_value to new_value"
45
+
46
+ @observable_properties[:custom_type].custom_property = "another_new_value" # changing a custom property with setter method
47
+ @observable.property_changed_message.should == "my_custom_type_observable_property changed from new_value to another_new_value"
48
+ end
49
+
50
+ it "should not notifiy the observable when calling methods that does not changes the observable property" do
51
+ @observable_properties[:string].reverse # reversing a string and returning a new copy of it
52
+ @observable.property_changed_message.should be_nil
53
+
54
+ @observable_properties[:array].index("some_value") # getting an element in the array
55
+ @observable.property_changed_message.should be_nil
56
+
57
+ @observable_properties[:hash].include?("some_key") # checking if a key is included in a hash
58
+ @observable.property_changed_message.should be_nil
59
+
60
+ @observable_properties[:custom_type].custom_method # calling a custom method which does not change
61
+ @observable.property_changed_message.should be_nil
62
+
63
+ @observable_properties[:custom_type].custom_method_with_parameters("something", "something else", "arg1", "arg2", "arg...") # calling a custom method which does not change
64
+ @observable.property_changed_message.should be_nil
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,283 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'spec_helper')
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'helpers', 'observables')
4
+
5
+ describe RuGUI::ObservablePropertySupport do
6
+ before(:each) do
7
+ @observable = AnotherFakeObservable.new
8
+ @observer = AnotherFakeObserver.new
9
+ @observable.register_observer(@observer)
10
+ end
11
+
12
+ describe "with notification" do
13
+ it "should notify the observer when setting a new value in a observable property" do
14
+ @observable.my_observable_property = "something"
15
+ @observer.property_updated_message.should == "AnotherFakeObservable property my_observable_property changed from to something"
16
+
17
+ @observable.my_observable_property = 1
18
+ @observer.property_updated_message.should == "AnotherFakeObservable property my_observable_property changed from something to 1"
19
+
20
+ @observable.my_observable_property = ["somearray"]
21
+ @observer.property_updated_message.should == "AnotherFakeObservable property my_observable_property changed from 1 to somearray"
22
+
23
+ @observable.my_observable_property = {'key' => "value"}
24
+ @observer.property_updated_message.should == "AnotherFakeObservable property my_observable_property changed from somearray to key"
25
+ end
26
+
27
+ it "should notify the observer when changing the value of a observable property" do
28
+ @observable.my_observable_property = "something"
29
+ @observable.my_observable_property << "_else"
30
+ @observer.property_updated_message.should == "AnotherFakeObservable property my_observable_property changed from something to something_else"
31
+
32
+ @observable.my_observable_property = ["somearray"]
33
+ @observable.my_observable_property << "another_value"
34
+ @observer.property_updated_message.should == "AnotherFakeObservable property my_observable_property changed from somearray to somearrayanother_value"
35
+
36
+ @observable.my_observable_property = {'key' => "value"}
37
+ @observable.my_observable_property['another_key'] = "another_value"
38
+ @observer.property_updated_message.should == "AnotherFakeObservable property my_observable_property changed from key to another_keykey"
39
+ end
40
+
41
+ it "should not notify the observer when setting the same value in a observable property" do
42
+ set_same_value_twice_clearing_property_updated_message("something")
43
+ @observer.property_updated_message.should be_nil
44
+
45
+ set_same_value_twice_clearing_property_updated_message(["somearray"])
46
+ @observer.property_updated_message.should be_nil
47
+
48
+ set_same_value_twice_clearing_property_updated_message({'key' => "value"})
49
+ @observer.property_updated_message.should be_nil
50
+ end
51
+
52
+ def set_same_value_twice_clearing_property_updated_message(value)
53
+ @observable.my_observable_property = value
54
+ @observer.property_updated_message = nil
55
+ @observable.my_observable_property = value
56
+ end
57
+ end
58
+
59
+ describe "with CustomType observable properties" do
60
+ it "should notify the observer when changing the CustomType instance changes" do
61
+ custom_type_fake_observable = CustomTypeFakeObservable.new
62
+ custom_type_fake_observable.register_observer(@observer)
63
+
64
+ # Setting a value.
65
+ custom_type_fake_observable.custom_type_observable_property.core_observable_property = "foo"
66
+
67
+ # The observer must be notified, the message itself does not need to be meaniful
68
+ @observer.property_updated_message.should == "CustomTypeFakeObservable property custom_type_observable_property changed from AnotherFakeObservable to AnotherFakeObservable"
69
+
70
+ # Clearing the observer property_updated_message
71
+ @observer.property_updated_message = nil
72
+
73
+ # Reseting
74
+ custom_type_fake_observable.reset!
75
+
76
+ # The observer must be notified, the message itself does not need to be meaniful
77
+ @observer.property_updated_message.should == "CustomTypeFakeObservable property custom_type_observable_property changed from AnotherFakeObservable to AnotherFakeObservable"
78
+ end
79
+ end
80
+
81
+ describe "with observable property options" do
82
+ it "should initialize properties configured with an initial value properly" do
83
+ @observable.initialized_observable_property.should == "some_initial_value"
84
+ end
85
+
86
+ it "should set the configured reset_value when reseting an observable" do
87
+ @observable.resetable_observable_property.should be_nil
88
+ @observable.reset!
89
+ @observable.resetable_observable_property.should == "some_reset_value"
90
+ end
91
+
92
+ it "should set the inital_value and the reset_value as appropriate" do
93
+ @observable.initialized_and_resetable_observable_property.should == "some_initial_value"
94
+ @observable.reset!
95
+ @observable.initialized_and_resetable_observable_property.should == "some_reset_value"
96
+ end
97
+
98
+ it "should not be shared among different observable classes" do
99
+ observable_properties_options = {
100
+ :core_observable_property => { :core => true, :initial_value => "some_initial_value", :reset_value => "some_initial_value" },
101
+ :initialized_observable_property => { :core => false, :initial_value => "some_initial_value", :reset_value => "some_initial_value" },
102
+ :resetable_observable_property => { :core => false, :initial_value => nil, :reset_value => "some_reset_value" },
103
+ :initialized_and_resetable_observable_property => { :core => false, :initial_value => "some_initial_value", :reset_value => "some_reset_value" },
104
+ :my_observable_property => { :core => false, :initial_value => nil, :reset_value => nil },
105
+ :my_array_observable_property => { :reset_value => [], :initial_value => [], :core => false },
106
+ :my_hash_observable_property => { :reset_value => {}, :initial_value => {}, :core => false },
107
+ }
108
+ AnotherFakeObservable.observable_properties_options.should == observable_properties_options
109
+
110
+ observable_properties_options = {
111
+ :another_observable_property => {:core => false, :initial_value => "some_other_initial_value", :reset_value => "some_other_initial_value"},
112
+ :first_core_observable_property => {:core => true, :initial_value => "first", :reset_value => "first"},
113
+ :second_core_observable_property => {:core => true, :initial_value => "second", :reset_value => "second"},
114
+ }
115
+ SomeOtherFakeObservable.observable_properties_options.should == observable_properties_options
116
+ end
117
+
118
+ it "should not let initial_value and reset_value be modified when the property value changes" do
119
+ AnotherFakeObservable.observable_properties_options[:my_array_observable_property][:initial_value].should == []
120
+ AnotherFakeObservable.observable_properties_options[:my_array_observable_property][:reset_value].should == []
121
+
122
+ AnotherFakeObservable.observable_properties_options[:my_hash_observable_property][:initial_value].should == {}
123
+ AnotherFakeObservable.observable_properties_options[:my_hash_observable_property][:reset_value].should == {}
124
+
125
+ @observable.my_array_observable_property << 1
126
+ AnotherFakeObservable.observable_properties_options[:my_array_observable_property][:initial_value].should == []
127
+ AnotherFakeObservable.observable_properties_options[:my_array_observable_property][:reset_value].should == []
128
+
129
+ @observable.my_hash_observable_property[:foo] = 'bar'
130
+ AnotherFakeObservable.observable_properties_options[:my_hash_observable_property][:initial_value].should == {}
131
+ AnotherFakeObservable.observable_properties_options[:my_hash_observable_property][:reset_value].should == {}
132
+ end
133
+
134
+ it "should prevent properties from being reset if configured" do
135
+ observable = ResetPreventedFakeObservable.new
136
+ observable.reset_prevented_observable_property = 'bar'
137
+ observable.reset!
138
+ observable.reset_prevented_observable_property.should == 'bar'
139
+ end
140
+
141
+ it "should prevent properties from being reset even if a :reset_value was configured" do
142
+ observable = ResetPreventedFakeObservable.new
143
+ observable.reset_prevented_with_reset_value_observable_property = 'bar'
144
+ observable.reset!
145
+ observable.reset_prevented_with_reset_value_observable_property.should == 'bar'
146
+ end
147
+
148
+ it "should create 'question' methods for configured boolean properties" do
149
+ observable = BooleanPropertiesFakeObservable.new
150
+ observable.boolean_observable_property = true
151
+ observable.respond_to?(:boolean_observable_property?).should be_true
152
+ observable.boolean_observable_property?.should be_true
153
+ end
154
+
155
+ it "should not create 'question' methods for non boolean properties" do
156
+ observable = BooleanPropertiesFakeObservable.new
157
+ observable.non_boolean_observable_property = "any other value"
158
+ observable.respond_to?(:non_boolean_observable_property?).should be_false
159
+ end
160
+ end
161
+
162
+ describe "with two instances comparison" do
163
+ it "should be equals when all configured core observable properties are equals" do
164
+ some_other_observable = AnotherFakeObservable.new
165
+ some_other_observable.should == @observable
166
+ end
167
+
168
+ it "should not be equals when at least one of the configured core observable properties are not equals" do
169
+ some_other_observable1 = SomeOtherFakeObservable.new
170
+ some_other_observable1.first_core_observable_property = "different_value"
171
+ some_other_observable2 = SomeOtherFakeObservable.new
172
+ some_other_observable1.should_not == some_other_observable2
173
+
174
+ some_other_observable1 = SomeOtherFakeObservable.new
175
+ some_other_observable2 = SomeOtherFakeObservable.new
176
+ some_other_observable2.first_core_observable_property = "different_value"
177
+ some_other_observable1.should_not == some_other_observable2
178
+ end
179
+ end
180
+
181
+ describe "with observable properties copy" do
182
+ before(:each) do
183
+ @parent = ParentFakeObservable.new
184
+ @child = ChildFakeObservable.new
185
+ @parent.child_observable_property = @child
186
+
187
+ @parent.my_own_observable_property = "parent"
188
+ @child.my_observable_property = "child"
189
+
190
+ @another_parent = ParentFakeObservable.new
191
+ @another_child = ChildFakeObservable.new
192
+ @another_parent.child_observable_property = @another_child
193
+
194
+ @another_parent.my_own_observable_property = "another_parent"
195
+ @another_child.my_observable_property = "another child"
196
+ end
197
+
198
+ it "should copy all observable properties from observables which have common properties" do
199
+ @parent.copy_observable_properties_from(@another_parent)
200
+ @parent.my_own_observable_property.should == @another_parent.my_own_observable_property
201
+ end
202
+
203
+ it "should perform deep copy of observable properties which holds observables" do
204
+ @parent.copy_observable_properties_from(@another_parent)
205
+ @parent.child_observable_property.should == @another_parent.child_observable_property
206
+ end
207
+
208
+ it "should not perform deep copy if 'deep' parameter is false" do
209
+ @parent.copy_observable_properties_from(@another_parent, false)
210
+ @parent.my_own_observable_property.should == @another_parent.my_own_observable_property
211
+ @parent.child_observable_property.should_not == @another_parent.child_observable_property
212
+ end
213
+ end
214
+
215
+ describe "with observable properties mapped for an instance" do
216
+ before(:each) do
217
+ @observable = SomeOtherFakeObservable.new
218
+ @observable.first_core_observable_property = "first value"
219
+ @observable.second_core_observable_property = "second value"
220
+ @observable.another_observable_property = "another observable value"
221
+
222
+ @mock_observable_properties = {
223
+ :first_core_observable_property => "first value",
224
+ :second_core_observable_property => "second value",
225
+ :another_observable_property => "another observable value"
226
+ }
227
+
228
+ @another_mock_observable_properties = {
229
+ :another_observable_property => "another",
230
+ :first_core_observable_property => "first",
231
+ :second_core_observable_property => "second"
232
+ }
233
+ end
234
+
235
+ it "should return a map of all observable properties with theirs values" do
236
+ @observable.observable_properties.should == @mock_observable_properties
237
+ end
238
+
239
+ describe "with initial value in initialization method" do
240
+ it "should set observable properties values" do
241
+ observable = SomeOtherFakeObservable.new(@mock_observable_properties)
242
+ observable.observable_properties.should == @mock_observable_properties
243
+ end
244
+ end
245
+
246
+ describe "without initial value in initialization method" do
247
+ it "should use :initial_value for observable properties values" do
248
+ observable = SomeOtherFakeObservable.new :another_observable_property => "another"
249
+ observable.observable_properties.should == @another_mock_observable_properties
250
+ end
251
+ end
252
+
253
+ describe "updating observable properties values" do
254
+ before do
255
+ @observable = SomeOtherFakeObservable.new :another_observable_property => "fake data"
256
+ end
257
+
258
+ it "should update values" do
259
+ @observable.update_observable_properties({ :another_observable_property => "another" })
260
+ @observable.observable_properties.should == @another_mock_observable_properties
261
+ end
262
+
263
+ it "should ignore non observable properties values" do
264
+ @observable.update_observable_properties({ :another_observable_property => "another", :id => 151 })
265
+ @observable.observable_properties.should == @another_mock_observable_properties
266
+ end
267
+ end
268
+
269
+ describe "with indifferent hash access" do
270
+ it "should accept property names with both string or symbol keys" do
271
+ observable = SomeOtherFakeObservable.new :another_observable_property => "fake data"
272
+ observable.another_observable_property.should == "fake data"
273
+ observable.update_observable_properties({ :another_observable_property => "another" })
274
+ observable.another_observable_property.should == "another"
275
+
276
+ observable = SomeOtherFakeObservable.new 'another_observable_property' => "fake data"
277
+ observable.another_observable_property.should == "fake data"
278
+ observable.update_observable_properties({ 'another_observable_property' => "another" })
279
+ observable.another_observable_property.should == "another"
280
+ end
281
+ end
282
+ end
283
+ end
@@ -0,0 +1,88 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'spec_helper')
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'helpers', 'observables')
4
+
5
+ describe RuGUI::PropertyObserver do
6
+ before(:each) do
7
+ @observer = FakeObserverForPropertyObserverTest.new
8
+ end
9
+
10
+ describe "with notification" do
11
+ it "should be notified when setting a new value in a observable property" do
12
+ @observer.observable.my_observable_property = "something"
13
+ @observer.property_updated_message.should == "FakeObservableForPropertyObserverTest property my_observable_property changed from to something"
14
+
15
+ @observer.observable.my_observable_property = 1
16
+ @observer.property_updated_message.should == "FakeObservableForPropertyObserverTest property my_observable_property changed from something to 1"
17
+
18
+ @observer.observable.my_observable_property = ["somearray"]
19
+ @observer.property_updated_message.should == "FakeObservableForPropertyObserverTest property my_observable_property changed from 1 to somearray"
20
+
21
+ @observer.observable.my_observable_property = {'key' => "value"}
22
+ @observer.property_updated_message.should == "FakeObservableForPropertyObserverTest property my_observable_property changed from somearray to key"
23
+ end
24
+
25
+ it "should be notified when changing the value of a observable property" do
26
+ @observer.observable.my_observable_property = "something"
27
+ @observer.observable.my_observable_property << "_else"
28
+ @observer.property_updated_message.should == "FakeObservableForPropertyObserverTest property my_observable_property changed from something to something_else"
29
+
30
+ @observer.observable.my_observable_property = ["somearray"]
31
+ @observer.observable.my_observable_property << "another_value"
32
+ @observer.property_updated_message.should == "FakeObservableForPropertyObserverTest property my_observable_property changed from somearray to somearrayanother_value"
33
+
34
+ @observer.observable.my_observable_property = {'key' => "value"}
35
+ @observer.observable.my_observable_property['another_key'] = "another_value"
36
+ @observer.property_updated_message.should == "FakeObservableForPropertyObserverTest property my_observable_property changed from key to another_keykey"
37
+ end
38
+
39
+ it "should not be notified when setting the same value in a observable property" do
40
+ set_same_value_twice_clearing_property_updated_message("something")
41
+ @observer.property_updated_message.should be_nil
42
+
43
+ set_same_value_twice_clearing_property_updated_message(["somearray"])
44
+ @observer.property_updated_message.should be_nil
45
+
46
+ set_same_value_twice_clearing_property_updated_message({'key' => "value"})
47
+ @observer.property_updated_message.should be_nil
48
+ end
49
+
50
+ def set_same_value_twice_clearing_property_updated_message(value)
51
+ @observer.observable.my_observable_property = value
52
+ @observer.property_updated_message = nil
53
+ @observer.observable.my_observable_property = value
54
+ end
55
+ end
56
+
57
+ describe "class specific methods" do
58
+ it "should be called when observable property changes" do
59
+ @observer.observable.my_observable_property = "something"
60
+ @observer.class_specific_method_called_message.should == "Property my_observable_property changed, called from class specific method"
61
+
62
+ # clearing message
63
+ @observer.class_specific_method_called_message = nil
64
+
65
+ @observer.observable.my_observable_property << "something"
66
+ @observer.class_specific_method_called_message.should == "Property my_observable_property changed, called from class specific method"
67
+ end
68
+ end
69
+
70
+ describe "named instance specific methods" do
71
+ it "should be called when observable property changes" do
72
+ @observer.named_observable.my_observable_property = "something"
73
+ @observer.instance_specific_method_called_message.should == "Property my_observable_property changed, called from named instance specific method"
74
+
75
+ # clearing message
76
+ @observer.instance_specific_method_called_message = nil
77
+
78
+ @observer.named_observable.my_observable_property << "something"
79
+ @observer.instance_specific_method_called_message.should == "Property my_observable_property changed, called from named instance specific method"
80
+ end
81
+
82
+ it "should not be called when the instance name collides with the class name" do
83
+ lambda {
84
+ @observer.fake_named_observable_test.my_observable_property = "something"
85
+ }.should change(@observer, :property_changed_counter).by(1) # Should call only the class method
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,29 @@
1
+ # Defines some controllers used in specs.
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), 'initialize_hooks_helper')
4
+
5
+ class MyController < RuGUI::BaseController
6
+ include InitializeHooksHelper
7
+
8
+ attr_accessor :message
9
+
10
+ def setup_views
11
+ register_view :my_view
12
+ end
13
+
14
+ def setup_models
15
+ register_model :my_model
16
+ register_model :my_model, :my_other_model_instance
17
+ end
18
+
19
+ def setup_controllers
20
+ register_controller :my_child_controller
21
+ end
22
+
23
+ def property_my_other_model_instance_my_property_changed(model, new_value, old_value)
24
+ @message = "Property my_property of named observable my_other_model_instance changed from #{old_value} to #{new_value}."
25
+ end
26
+ end
27
+
28
+ class MyChildController < RuGUI::BaseController
29
+ end
@@ -0,0 +1,18 @@
1
+ module InitializeHooksHelper
2
+ def before_initialize_called?
3
+ @before_initialize_called == true
4
+ end
5
+
6
+ def after_initialize_called?
7
+ @after_initialize_called == true
8
+ end
9
+
10
+ protected
11
+ def before_initialize
12
+ @before_initialize_called = true
13
+ end
14
+
15
+ def after_initialize
16
+ @after_initialize_called = true
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ # Defines some models used in specs.
2
+
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), 'initialize_hooks_helper')
4
+
5
+ class MyModel < RuGUI::BaseModel
6
+ include InitializeHooksHelper
7
+
8
+ observable_property :my_property
9
+ end