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.
- data/LICENSE +165 -0
- data/README +67 -0
- data/README.rdoc +67 -0
- data/Rakefile +56 -0
- data/VERSION.yml +4 -0
- data/bin/rugui +16 -0
- data/lib/rugui/base_controller.rb +194 -0
- data/lib/rugui/base_model.rb +22 -0
- data/lib/rugui/base_object.rb +73 -0
- data/lib/rugui/base_view.rb +302 -0
- data/lib/rugui/base_view_helper.rb +23 -0
- data/lib/rugui/configuration.rb +136 -0
- data/lib/rugui/framework_adapters/GTK.rb +233 -0
- data/lib/rugui/framework_adapters/Qt4.rb +171 -0
- data/lib/rugui/framework_adapters/base_framework_adapter.rb +90 -0
- data/lib/rugui/framework_adapters/framework_adapter_support.rb +35 -0
- data/lib/rugui/gem_builder.rb +21 -0
- data/lib/rugui/gem_dependency.rb +282 -0
- data/lib/rugui/initialize_hooks.rb +36 -0
- data/lib/rugui/initializer.rb +162 -0
- data/lib/rugui/log_support.rb +118 -0
- data/lib/rugui/observable_property_proxy.rb +73 -0
- data/lib/rugui/observable_property_support.rb +251 -0
- data/lib/rugui/plugin/loader.rb +77 -0
- data/lib/rugui/property_observer.rb +58 -0
- data/lib/rugui/signal_support.rb +57 -0
- data/lib/rugui/tasks/gems_application.rake +71 -0
- data/lib/rugui/tasks/rugui.rb +8 -0
- data/lib/rugui/tasks/rugui_framework.rb +4 -0
- data/lib/rugui/tasks/runner_application.rake +4 -0
- data/lib/rugui/tasks/spec_application.rake +64 -0
- data/lib/rugui/tasks/spec_framework.rake +27 -0
- data/lib/rugui/tasks/test_application.rake +77 -0
- data/lib/rugui/vendor_gem_source_index.rb +140 -0
- data/lib/rugui/version.rb +9 -0
- data/lib/rugui.rb +37 -0
- data/spec/framework/base_controller_spec.rb +48 -0
- data/spec/framework/base_model_spec.rb +13 -0
- data/spec/framework/base_view_helper_spec.rb +13 -0
- data/spec/framework/base_view_spec.rb +92 -0
- data/spec/framework/log_support_spec.rb +16 -0
- data/spec/framework/observable_property_proxy_spec.rb +67 -0
- data/spec/framework/observable_property_support_spec.rb +283 -0
- data/spec/framework/property_observer_spec.rb +88 -0
- data/spec/helpers/controllers.rb +29 -0
- data/spec/helpers/initialize_hooks_helper.rb +18 -0
- data/spec/helpers/models.rb +9 -0
- data/spec/helpers/observables.rb +210 -0
- data/spec/helpers/view_helpers.rb +9 -0
- data/spec/helpers/views.rb +72 -0
- data/spec/rcov.opts +1 -0
- data/spec/resource_files/my_other_view.glade +46 -0
- data/spec/resource_files/my_view.glade +46 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +15 -0
- 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
|