qml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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