qml 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +46 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +15 -0
  5. data/.yardopts +4 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +351 -0
  9. data/Rakefile +6 -0
  10. data/examples/assets/fonts/fontawesome-webfont.ttf +0 -0
  11. data/examples/fizzbuzz/fizzbuzz.rb +43 -0
  12. data/examples/fizzbuzz/main.qml +38 -0
  13. data/examples/imageprovider/imageprovider.rb +57 -0
  14. data/examples/imageprovider/main.qml +51 -0
  15. data/examples/todo/main.qml +70 -0
  16. data/examples/todo/todo.rb +36 -0
  17. data/examples/twitter/main.qml +36 -0
  18. data/examples/twitter/twitter.rb +55 -0
  19. data/ext/qml/accessclass.cpp +71 -0
  20. data/ext/qml/accessclass.h +19 -0
  21. data/ext/qml/accessobject.cpp +30 -0
  22. data/ext/qml/accessobject.h +22 -0
  23. data/ext/qml/application.cpp +54 -0
  24. data/ext/qml/application.h +17 -0
  25. data/ext/qml/common.h +18 -0
  26. data/ext/qml/ext_accesssupport.cpp +77 -0
  27. data/ext/qml/ext_accesssupport.h +42 -0
  28. data/ext/qml/ext_gcmarker.cpp +39 -0
  29. data/ext/qml/ext_gcmarker.h +27 -0
  30. data/ext/qml/ext_kernel.cpp +62 -0
  31. data/ext/qml/ext_kernel.h +11 -0
  32. data/ext/qml/ext_metaobject.cpp +410 -0
  33. data/ext/qml/ext_metaobject.h +62 -0
  34. data/ext/qml/ext_pluginloader.cpp +55 -0
  35. data/ext/qml/ext_pluginloader.h +32 -0
  36. data/ext/qml/ext_pointer.cpp +134 -0
  37. data/ext/qml/ext_pointer.h +43 -0
  38. data/ext/qml/ext_testutil.cpp +42 -0
  39. data/ext/qml/ext_testutil.h +11 -0
  40. data/ext/qml/extconf.rb +84 -0
  41. data/ext/qml/foreignclass.cpp +72 -0
  42. data/ext/qml/foreignclass.h +88 -0
  43. data/ext/qml/foreignmetaobject.cpp +345 -0
  44. data/ext/qml/foreignmetaobject.h +46 -0
  45. data/ext/qml/foreignobject.cpp +22 -0
  46. data/ext/qml/foreignobject.h +21 -0
  47. data/ext/qml/functioninfo.h +16 -0
  48. data/ext/qml/init.cpp +69 -0
  49. data/ext/qml/listmodel.cpp +112 -0
  50. data/ext/qml/listmodel.h +43 -0
  51. data/ext/qml/markable.h +12 -0
  52. data/ext/qml/objectdata.cpp +26 -0
  53. data/ext/qml/objectdata.h +20 -0
  54. data/ext/qml/objectgc.cpp +69 -0
  55. data/ext/qml/objectgc.h +28 -0
  56. data/ext/qml/plugins/core/applicationextension.cpp +34 -0
  57. data/ext/qml/plugins/core/applicationextension.h +28 -0
  58. data/ext/qml/plugins/core/componentextension.cpp +41 -0
  59. data/ext/qml/plugins/core/componentextension.h +28 -0
  60. data/ext/qml/plugins/core/contextextension.cpp +39 -0
  61. data/ext/qml/plugins/core/contextextension.h +29 -0
  62. data/ext/qml/plugins/core/core.pro +29 -0
  63. data/ext/qml/plugins/core/coreplugin.cpp +87 -0
  64. data/ext/qml/plugins/core/coreplugin.h +49 -0
  65. data/ext/qml/plugins/core/engineextension.cpp +27 -0
  66. data/ext/qml/plugins/core/engineextension.h +28 -0
  67. data/ext/qml/plugins/core/imageprovider.cpp +38 -0
  68. data/ext/qml/plugins/core/imageprovider.h +18 -0
  69. data/ext/qml/plugins/core/imagerequestpromise.cpp +19 -0
  70. data/ext/qml/plugins/core/imagerequestpromise.h +21 -0
  71. data/ext/qml/plugins/core/qmlexception.cpp +11 -0
  72. data/ext/qml/plugins/core/qmlexception.h +17 -0
  73. data/ext/qml/plugins/testutil/objectlifechecker.cpp +17 -0
  74. data/ext/qml/plugins/testutil/objectlifechecker.h +24 -0
  75. data/ext/qml/plugins/testutil/ownershiptest.cpp +26 -0
  76. data/ext/qml/plugins/testutil/ownershiptest.h +30 -0
  77. data/ext/qml/plugins/testutil/testobject.cpp +6 -0
  78. data/ext/qml/plugins/testutil/testobject.h +108 -0
  79. data/ext/qml/plugins/testutil/testobjectsubclass.cpp +10 -0
  80. data/ext/qml/plugins/testutil/testobjectsubclass.h +19 -0
  81. data/ext/qml/plugins/testutil/testutil.pro +20 -0
  82. data/ext/qml/plugins/testutil/testutilplugin.cpp +47 -0
  83. data/ext/qml/plugins/testutil/testutilplugin.h +32 -0
  84. data/ext/qml/qmltyperegisterer.cpp +74 -0
  85. data/ext/qml/qmltyperegisterer.h +30 -0
  86. data/ext/qml/rubyclass.cpp +94 -0
  87. data/ext/qml/rubyclass.h +234 -0
  88. data/ext/qml/rubyvalue.cpp +690 -0
  89. data/ext/qml/rubyvalue.h +256 -0
  90. data/ext/qml/signalforwarder.cpp +66 -0
  91. data/ext/qml/signalforwarder.h +29 -0
  92. data/ext/qml/util.cpp +120 -0
  93. data/ext/qml/util.h +101 -0
  94. data/ext/qml/valuereference.cpp +50 -0
  95. data/ext/qml/valuereference.h +22 -0
  96. data/ext/qml/weakvaluereference.cpp +27 -0
  97. data/ext/qml/weakvaluereference.h +19 -0
  98. data/lib/qml.rb +41 -0
  99. data/lib/qml/access.rb +137 -0
  100. data/lib/qml/application.rb +139 -0
  101. data/lib/qml/class_builder.rb +126 -0
  102. data/lib/qml/component.rb +53 -0
  103. data/lib/qml/context.rb +71 -0
  104. data/lib/qml/data.rb +2 -0
  105. data/lib/qml/data/array_model.rb +103 -0
  106. data/lib/qml/data/error.rb +5 -0
  107. data/lib/qml/data/list_model.rb +146 -0
  108. data/lib/qml/dispatchable.rb +34 -0
  109. data/lib/qml/dispatcher.rb +61 -0
  110. data/lib/qml/engine.rb +54 -0
  111. data/lib/qml/error_converter.rb +15 -0
  112. data/lib/qml/errors.rb +26 -0
  113. data/lib/qml/geometry.rb +3 -0
  114. data/lib/qml/geometry/point.rb +5 -0
  115. data/lib/qml/geometry/rectangle.rb +5 -0
  116. data/lib/qml/geometry/size.rb +5 -0
  117. data/lib/qml/image_provider.rb +87 -0
  118. data/lib/qml/meta_object.rb +20 -0
  119. data/lib/qml/models.rb +1 -0
  120. data/lib/qml/name_helper.rb +12 -0
  121. data/lib/qml/platform.rb +15 -0
  122. data/lib/qml/plugin_loader.rb +46 -0
  123. data/lib/qml/plugins.rb +26 -0
  124. data/lib/qml/qml.rb +1 -0
  125. data/lib/qml/qt.rb +6 -0
  126. data/lib/qml/qt_classes.rb +9 -0
  127. data/lib/qml/qt_object_base.rb +108 -0
  128. data/lib/qml/reactive.rb +8 -0
  129. data/lib/qml/reactive/bindable.rb +79 -0
  130. data/lib/qml/reactive/chained_signal.rb +25 -0
  131. data/lib/qml/reactive/error.rb +5 -0
  132. data/lib/qml/reactive/object.rb +278 -0
  133. data/lib/qml/reactive/property.rb +19 -0
  134. data/lib/qml/reactive/signal.rb +116 -0
  135. data/lib/qml/reactive/signal_spy.rb +27 -0
  136. data/lib/qml/reactive/signals/map_signal.rb +21 -0
  137. data/lib/qml/reactive/signals/merge_signal.rb +21 -0
  138. data/lib/qml/reactive/signals/select_signal.rb +21 -0
  139. data/lib/qml/reactive/simple_property.rb +17 -0
  140. data/lib/qml/reactive/unbound_property.rb +42 -0
  141. data/lib/qml/reactive/unbound_signal.rb +51 -0
  142. data/lib/qml/root_path.rb +3 -0
  143. data/lib/qml/test_util.rb +1 -0
  144. data/lib/qml/test_util/object_life_checker.rb +17 -0
  145. data/lib/qml/version.rb +3 -0
  146. data/lib/qml/wrappable.rb +9 -0
  147. data/qml.gemspec +28 -0
  148. data/spec/assets/testobj.qml +5 -0
  149. data/spec/qml/.access_spec.rb.swp +0 -0
  150. data/spec/qml/access_spec.rb +162 -0
  151. data/spec/qml/application_spec.rb +43 -0
  152. data/spec/qml/component_spec.rb +44 -0
  153. data/spec/qml/context_spec.rb +43 -0
  154. data/spec/qml/conversion_spec.rb +59 -0
  155. data/spec/qml/data/array_model_spec.rb +215 -0
  156. data/spec/qml/dispatchable_spec.rb +26 -0
  157. data/spec/qml/dispatcher_spec.rb +48 -0
  158. data/spec/qml/geometry/point_spec.rb +4 -0
  159. data/spec/qml/geometry/rectangle_spec.rb +4 -0
  160. data/spec/qml/geometry/size_spec.rb +4 -0
  161. data/spec/qml/plugin_loader_spec.rb +33 -0
  162. data/spec/qml/qt_object_base_spec.rb +119 -0
  163. data/spec/qml/reactive/object_spec.rb +273 -0
  164. data/spec/qml/reactive/property_spec.rb +70 -0
  165. data/spec/qml/reactive/signal_spec.rb +191 -0
  166. data/spec/qml/reactive/signal_spy_spec.rb +26 -0
  167. data/spec/qml/test_object_spec.rb +186 -0
  168. data/spec/qml_spec.rb +7 -0
  169. data/spec/spec_helper.rb +5 -0
  170. metadata +321 -0
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe QML::Geometry::Point do
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe QML::Geometry::Rectangle do
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe QML::Geometry::Size do
4
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe QML::PluginLoader do
4
+
5
+ let(:loader) { QML::PluginLoader.new path, 'rubyqml-testutil' }
6
+
7
+ describe 'load' do
8
+
9
+ context 'with signle path' do
10
+ let(:path) { QML::ROOT_PATH + 'ext/qml/plugins/testutil' + QML::PluginLoader.lib_filename('rubyqml-testutil') }
11
+ let(:loader) { QML::PluginLoader.new path }
12
+ it 'creates an object instance' do
13
+ loader.load
14
+ expect(loader.instance).to be_a QML::QtObjectBase
15
+ end
16
+ end
17
+
18
+ context 'with correct file path' do
19
+ let(:path) { QML::ROOT_PATH + 'ext/qml/plugins/testutil' }
20
+ it 'creates an object instance' do
21
+ loader.load
22
+ expect(loader.instance).to be_a QML::QtObjectBase
23
+ end
24
+ end
25
+
26
+ context 'with wrong file path' do
27
+ let(:path) { QML::ROOT_PATH + 'ext/qml/plugins/wrong' }
28
+ it 'fails with QML::PluginError' do
29
+ expect { loader.load }.to raise_error(QML::PluginError)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+
3
+ describe QML::QtObjectBase do
4
+
5
+ describe '#qml_eval' do
6
+
7
+ let(:component) do
8
+ QML::Component.new data: <<-EOS
9
+ import QtQuick 2.0
10
+ QtObject {
11
+ property string foo: 'foo'
12
+ property string bar: 'bar'
13
+ }
14
+ EOS
15
+ end
16
+ let(:object) { component.create }
17
+ let(:expression) { 'foo + bar' }
18
+ let(:result) { object.qml_eval(expression) }
19
+
20
+ it 'evaluates a JS expression in its QML scope' do
21
+ expect(result).to eq 'foobar'
22
+ end
23
+
24
+ context 'when expression is wrong' do
25
+ let(:expression) { 'hoge + piyo' }
26
+ it 'raises QML::QMLError' do
27
+ expect { result }.to raise_error(QML::QMLError)
28
+ end
29
+ end
30
+
31
+ context 'when object does not belong to context' do
32
+ let(:object) { QML::Plugins.test_util.createTestObject }
33
+ it 'raises QML::QMLError' do
34
+ expect { result }.to raise_error(QML::QMLError)
35
+ end
36
+ end
37
+ end
38
+
39
+ describe 'ownership' do
40
+ let(:ownership_test) { QML::Plugins.test_util.create_ownership_test }
41
+
42
+ context 'when it is returned from a method' do
43
+ it 'gets ownership of the object' do
44
+ checker = -> { QML::TestUtil::ObjectLifeChecker.new(ownership_test.create_object) }.call
45
+ QML.application.collect_garbage
46
+ expect(checker.alive?).to eq false
47
+ end
48
+ end
49
+
50
+ context 'when it is obtained from a property' do
51
+ it 'does not get ownership of the object' do
52
+ checker = -> { QML::TestUtil::ObjectLifeChecker.new(ownership_test.property_object) }.call
53
+ QML.application.collect_garbage
54
+ expect(checker.alive?).to eq true
55
+ end
56
+ end
57
+
58
+ context 'when it has a parent' do
59
+ it 'does not get ownership of the object' do
60
+ checker = -> { QML::TestUtil::ObjectLifeChecker.new(ownership_test.sub_object) }.call
61
+ QML.application.collect_garbage
62
+ expect(checker.alive?).to eq true
63
+ end
64
+ end
65
+
66
+ context 'when it is created by component' do
67
+ let(:component) do
68
+ QML::Component.new data: <<-EOS
69
+ import QtQuick 2.0
70
+ Item {}
71
+ EOS
72
+ end
73
+ it 'gets ownership' do
74
+ checker = -> { QML::TestUtil::ObjectLifeChecker.new(component.create) }.call
75
+ QML.application.collect_garbage
76
+ expect(checker.alive?).to eq false
77
+ end
78
+ end
79
+
80
+ describe '#managed?' do
81
+ [true, false].each do |cond|
82
+ context "when managed = #{cond}" do
83
+ it "returns #{cond}" do
84
+ obj = ownership_test.create_object
85
+ obj.managed = cond
86
+ expect(obj.managed?).to eq cond
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ context 'on garbage collection' do
93
+
94
+ context 'when managed' do
95
+ it 'gets destroyed' do
96
+ checker = -> {
97
+ obj = ownership_test.create_object
98
+ obj.managed = true
99
+ QML::TestUtil::ObjectLifeChecker.new(obj)
100
+ }.call
101
+ QML.application.collect_garbage
102
+ expect(checker.alive?).to eq false
103
+ end
104
+ end
105
+
106
+ context 'when not managed' do
107
+ it 'does not get destroyed' do
108
+ checker = -> {
109
+ obj = ownership_test.create_object
110
+ obj.managed = false
111
+ QML::TestUtil::ObjectLifeChecker.new(obj)
112
+ }.call
113
+ QML.application.collect_garbage
114
+ expect(checker.alive?).to eq true
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,273 @@
1
+ require 'spec_helper'
2
+
3
+ describe QML::Reactive::Object do
4
+
5
+ class Button
6
+ include QML::Reactive::Object
7
+ signal :pressed, [:pos]
8
+ variadic_signal :message
9
+ property :name, 'button'
10
+ property :id, 0
11
+ property :name_double do
12
+ name + name
13
+ end
14
+ on :pressed do |pos|
15
+ self.name = pos
16
+ end
17
+ on_changed :id do
18
+ self.name = "ID: #{id}"
19
+ end
20
+ on_changed :id do
21
+ end
22
+ alias_property :title, :name
23
+ alias_signal :clicked, :pressed
24
+ end
25
+
26
+ class ToggleButton < Button
27
+ signal :pressed, [:x, :y]
28
+ signal :toggled, [:on]
29
+ property(:name) { 'toggle button' }
30
+ property(:info) { 'some info' }
31
+ end
32
+
33
+ let(:button) { Button.new }
34
+ let(:toggle_button) { ToggleButton.new }
35
+
36
+ describe '.property' do
37
+
38
+ it 'defines getter' do
39
+ expect(button.name).to eq('button')
40
+ end
41
+
42
+ it 'defines setter' do
43
+ button.name = 'hoge'
44
+ expect(button.name).to eq('hoge')
45
+ end
46
+
47
+ it 'can set property binding' do
48
+ button.name = 'poyo'
49
+ expect(button.name_double).to eq 'poyopoyo'
50
+ end
51
+
52
+ it 'defines notify signal' do
53
+ spy = QML::Reactive::SignalSpy.new(button.name_changed)
54
+ button.name = 'hoge'
55
+ expect(spy.args.last).to eq(['hoge'])
56
+ end
57
+
58
+ it 'returns the name' do
59
+ result = nil
60
+ Class.new do
61
+ include QML::Reactive::Object
62
+ result = property :foo
63
+ end
64
+ expect(result).to eq :foo
65
+ end
66
+
67
+ context 'in subclass' do
68
+
69
+ it 'defines property in subclass' do
70
+ expect(toggle_button.info).to eq('some info')
71
+ end
72
+
73
+ it 'does not define property in superclass' do
74
+ expect(button.properties).not_to include(:info)
75
+ end
76
+
77
+ it 'overrides superclass property' do
78
+ expect(toggle_button.name).to eq('toggle button')
79
+ end
80
+ end
81
+ end
82
+
83
+ describe '.alias_property' do
84
+ it 'returns the name' do
85
+ result = nil
86
+ Class.new do
87
+ include QML::Reactive::Object
88
+ property :foo
89
+ result = alias_property :bar, :foo
90
+ end
91
+ expect(result).to eq :bar
92
+ end
93
+ it 'aliases a property' do
94
+ expect(button.property(:title)).to eq button.property(:name)
95
+ expect(button.signal(:title_changed)).to eq button.signal(:name_changed)
96
+ end
97
+ end
98
+
99
+ describe '.signal' do
100
+
101
+ it 'defines a signal' do
102
+ spy = button.pressed.spy
103
+ button.pressed.emit([10, 22])
104
+ expect(spy.args.last).to eq([[10, 22]])
105
+ end
106
+
107
+ it 'returns the name' do
108
+ result = nil
109
+ Class.new do
110
+ include QML::Reactive::Object
111
+ result = signal :sig, []
112
+ end
113
+ expect(result).to eq(:sig)
114
+ end
115
+
116
+ context 'when the args parameter is not passed' do
117
+ it 'defines a variadic signal' do
118
+ spy = button.message.spy
119
+ button.message.emit(*%w{emitting some message})
120
+ expect(spy.args.last).to eq(%w{emitting some message})
121
+ end
122
+ end
123
+
124
+ context 'in subclass' do
125
+
126
+ it 'defines signal in subclass' do
127
+ spy = toggle_button.toggled.spy
128
+ toggle_button.toggled.emit(true)
129
+ expect(spy.args.last).to eq([true])
130
+ end
131
+
132
+ it 'does not define signal in superclass' do
133
+ expect(button.signals).not_to include(:toggled)
134
+ end
135
+
136
+ it 'overrides superclass signal' do
137
+ signal = toggle_button.pressed
138
+ expect(signal.arity).to eq(2)
139
+ end
140
+
141
+ it 'defines overridden signal in subclass' do
142
+ spy = toggle_button.pressed.spy
143
+ toggle_button.pressed.emit(10, 20)
144
+ expect(spy.args.last).to eq([10, 20])
145
+ end
146
+ end
147
+ end
148
+
149
+ describe '.alias_signal' do
150
+
151
+ it 'returns the name' do
152
+ result = nil
153
+ Class.new do
154
+ include QML::Reactive::Object
155
+ signal :foo, []
156
+ result = alias_signal :bar, :foo
157
+ end
158
+ expect(result).to eq :bar
159
+ end
160
+
161
+ it 'aliases a signal' do
162
+ expect(button.clicked).to eq button.pressed
163
+ end
164
+ end
165
+
166
+ describe '.on' do
167
+ it 'adds signal handler' do
168
+ button.pressed.emit "pressed at top"
169
+ expect(button.name).to eq "pressed at top"
170
+ end
171
+ end
172
+
173
+ describe '.on_changed' do
174
+ it 'add property changed signal handler' do
175
+ button.id = 2
176
+ expect(button.name).to eq "ID: 2"
177
+ end
178
+ end
179
+
180
+ describe '.instance_signals' do
181
+ context 'when include_super is false' do
182
+ it 'returns all signal definitions of the class' do
183
+ signals = ToggleButton.instance_signals(false)
184
+ expect(signals).to match_array %i{pressed toggled name_changed info_changed}
185
+ end
186
+ end
187
+
188
+ context 'when include_super is not specified' do
189
+ it 'returns all signal definitions of the class and its superclasses' do
190
+ signals = ToggleButton.instance_signals
191
+ expect(signals).to match_array %i{pressed message toggled name_changed id_changed info_changed name_double_changed clicked title_changed}
192
+ end
193
+ end
194
+ end
195
+
196
+ describe '.instance_properties' do
197
+ context 'when include_super is false' do
198
+ it 'returns all property definitions of the class' do
199
+ properties = ToggleButton.instance_properties(false)
200
+ expect(properties).to match_array %i{name info}
201
+ end
202
+ end
203
+
204
+ context 'when include_super is not specified' do
205
+ it 'returns all property definitions of the class and its superclasses' do
206
+ properties = ToggleButton.instance_properties
207
+ expect(properties).to match_array %i{name id info name_double title}
208
+ end
209
+ end
210
+ end
211
+
212
+ describe '.instance_signal' do
213
+ it 'returns the UnboundSignal for name' do
214
+ s = ToggleButton.instance_signal(:pressed)
215
+ expect(s).to be_a QML::Reactive::UnboundSignal
216
+ expect(s.name).to eq :pressed
217
+ expect(s.arity).to eq 2
218
+ end
219
+ context 'when signal does not exist' do
220
+ it 'fails with NameError' do
221
+ expect { ToggleButton.instance_signal(:non_existent) }.to raise_error(NameError)
222
+ end
223
+ end
224
+ end
225
+
226
+ describe '.instance_property' do
227
+ it 'returns the UnboundProperty for name' do
228
+ p = ToggleButton.instance_property(:name)
229
+ expect(p).to be_a QML::Reactive::UnboundProperty
230
+ expect(p.name).to eq :name
231
+ expect(p.initial_binding.call).to eq 'toggle button'
232
+ end
233
+ context 'when property does not exist' do
234
+ it 'fails with NameError' do
235
+ expect { ToggleButton.instance_property(:non_existent) }.to raise_error(NameError)
236
+ end
237
+ end
238
+ end
239
+
240
+ describe '#signals' do
241
+ it 'returns signal names for object' do
242
+ expect(toggle_button.signals).to match_array %i{pressed message toggled id_changed name_changed info_changed name_double_changed clicked title_changed}
243
+ end
244
+ end
245
+
246
+ describe '#properties' do
247
+ it 'return property names for object' do
248
+ expect(toggle_button.properties).to match_array %i{name id info name_double title}
249
+ end
250
+ end
251
+
252
+ describe '#signal' do
253
+ it 'returns Signal for name' do
254
+ expect(toggle_button.signal(:pressed)).to eq toggle_button.pressed
255
+ end
256
+ context 'when signal does not exist' do
257
+ it 'fails with NameError' do
258
+ expect { toggle_button.signal(:non_existent) }.to raise_error(NameError)
259
+ end
260
+ end
261
+ end
262
+
263
+ describe '#property' do
264
+ it 'returns Property for name' do
265
+ expect(toggle_button.property(:name).value).to eq toggle_button.name
266
+ end
267
+ context 'when property does not exist' do
268
+ it 'fails with NameError' do
269
+ expect { toggle_button.property(:non_existent) }.to raise_error(NameError)
270
+ end
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe QML::Reactive::Property do
4
+
5
+ describe '#initialize' do
6
+
7
+ context 'when a value is given' do
8
+ it 'initializes with the value' do
9
+ p = QML::Reactive::Property.new(2)
10
+ expect(p.value).to eq(2)
11
+ end
12
+ end
13
+
14
+ context 'when a block is given' do
15
+ it 'initializes with the property binding' do
16
+ p1 = QML::Reactive::Property.new(2)
17
+ p2 = QML::Reactive::Property.new { p1.value + 2 }
18
+ p1.value = 10
19
+ expect(p2.value).to eq(12)
20
+ end
21
+ end
22
+ end
23
+
24
+ describe 'access to the value' do
25
+ describe '#value, #value=' do
26
+ it 'sets and gets the contained value' do
27
+ property = QML::Reactive::Property.new
28
+ property.value = '(´・_・`)'
29
+ expect(property.value).to eq('(´・_・`)')
30
+ end
31
+ end
32
+ end
33
+
34
+ describe 'property binding' do
35
+
36
+ describe '#bind' do
37
+
38
+ it 'sets a property binding' do
39
+ p1 = QML::Reactive::Property.new 'foo'
40
+ p2 = QML::Reactive::Property.new 'bar'
41
+ p3 = QML::Reactive::Property.new
42
+ p4 = QML::Reactive::Property.new
43
+ p3.bind { p1.value + p2.value }
44
+ p4.bind { p3.value }
45
+ p1.value = 'hoge'
46
+ p2.value = 'piyo'
47
+ expect(p3.value).to eq('hogepiyo')
48
+ expect(p4.value).to eq('hogepiyo')
49
+ end
50
+
51
+ context 'when binding is recursive' do
52
+ it 'raises error' do
53
+ property = QML::Reactive::Property.new
54
+ expect{ property.bind { property.value } }.to raise_error(QML::Reactive::Error)
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ describe '#changed' do
61
+ it 'returns a signal that is emitted when the value is changed' do
62
+ property = QML::Reactive::Property.new
63
+ changed_value = nil
64
+ property.changed.connect { |val| changed_value = val }
65
+
66
+ property.value = 'piyopiyo'
67
+ expect(changed_value).to eq('piyopiyo')
68
+ end
69
+ end
70
+ end