volt 0.7.23 → 0.8.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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -1
  3. data/CHANGELOG.md +22 -0
  4. data/Gemfile +8 -0
  5. data/Guardfile +2 -2
  6. data/Readme.md +139 -136
  7. data/VERSION +1 -1
  8. data/app/volt/assets/js/setImmediate.js +175 -0
  9. data/app/volt/tasks/live_query/data_store.rb +0 -2
  10. data/app/volt/tasks/live_query/live_query.rb +4 -4
  11. data/docs/GETTING_STARTED.md +24 -3
  12. data/docs/WHY.md +1 -22
  13. data/lib/volt.rb +20 -1
  14. data/lib/volt/console.rb +20 -0
  15. data/lib/volt/controllers/model_controller.rb +25 -11
  16. data/lib/volt/extra_core/object.rb +2 -14
  17. data/lib/volt/extra_core/string.rb +4 -0
  18. data/lib/volt/models.rb +0 -1
  19. data/lib/volt/models/array_model.rb +8 -16
  20. data/lib/volt/models/cursor.rb +1 -1
  21. data/lib/volt/models/model.rb +40 -60
  22. data/lib/volt/models/model_hash_behaviour.rb +10 -24
  23. data/lib/volt/models/model_helpers.rb +2 -2
  24. data/lib/volt/models/model_state.rb +1 -1
  25. data/lib/volt/models/model_wrapper.rb +4 -4
  26. data/lib/volt/models/persistors/array_store.rb +44 -28
  27. data/lib/volt/models/persistors/base.rb +1 -1
  28. data/lib/volt/models/persistors/model_store.rb +1 -1
  29. data/lib/volt/models/persistors/params.rb +5 -1
  30. data/lib/volt/models/persistors/query/query_listener.rb +2 -0
  31. data/lib/volt/models/persistors/store.rb +3 -2
  32. data/lib/volt/models/persistors/store_state.rb +7 -2
  33. data/lib/volt/models/url.rb +35 -29
  34. data/lib/volt/models/validations.rb +7 -17
  35. data/lib/volt/page/bindings/attribute_binding.rb +57 -39
  36. data/lib/volt/page/bindings/base_binding.rb +0 -14
  37. data/lib/volt/page/bindings/content_binding.rb +15 -18
  38. data/lib/volt/page/bindings/each_binding.rb +67 -34
  39. data/lib/volt/page/bindings/if_binding.rb +15 -12
  40. data/lib/volt/page/bindings/template_binding.rb +77 -59
  41. data/lib/volt/page/bindings/template_binding/grouped_controllers.rb +19 -4
  42. data/lib/volt/page/channel.rb +22 -38
  43. data/lib/volt/page/channel_stub.rb +3 -6
  44. data/lib/volt/page/page.rb +24 -26
  45. data/lib/volt/page/string_template_renderer.rb +46 -0
  46. data/lib/volt/page/sub_context.rb +7 -1
  47. data/lib/volt/page/targets/binding_document/component_node.rb +11 -9
  48. data/lib/volt/page/tasks.rb +3 -2
  49. data/lib/volt/page/url_tracker.rb +4 -3
  50. data/lib/volt/reactive/computation.rb +131 -0
  51. data/lib/volt/reactive/dependency.rb +71 -0
  52. data/lib/volt/reactive/eventable.rb +82 -0
  53. data/lib/volt/reactive/hash_dependency.rb +36 -0
  54. data/lib/volt/{controllers → reactive}/reactive_accessors.rb +8 -11
  55. data/lib/volt/reactive/reactive_array.rb +100 -193
  56. data/lib/volt/reactive/reactive_hash.rb +49 -0
  57. data/lib/volt/server/html_parser/attribute_scope.rb +24 -4
  58. data/lib/volt/server/html_parser/if_view_scope.rb +15 -15
  59. data/lib/volt/server/html_parser/view_scope.rb +31 -1
  60. data/spec/apps/kitchen_sink/Gemfile +4 -8
  61. data/spec/apps/kitchen_sink/app/main/config/dependencies.rb +8 -0
  62. data/spec/apps/kitchen_sink/app/main/config/routes.rb +8 -1
  63. data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +8 -0
  64. data/spec/apps/kitchen_sink/app/main/views/main/bindings.html +73 -0
  65. data/spec/apps/kitchen_sink/app/main/views/main/index.html +6 -1
  66. data/spec/apps/kitchen_sink/app/main/views/main/main.html +26 -6
  67. data/spec/apps/kitchen_sink/app/main/views/main/store.html +6 -0
  68. data/spec/controllers/reactive_accessors_spec.rb +13 -15
  69. data/spec/integration/bindings_spec.rb +159 -0
  70. data/spec/integration/templates_spec.rb +15 -0
  71. data/spec/models/model_spec.rb +130 -228
  72. data/spec/reactive/computation_spec.rb +63 -0
  73. data/spec/reactive/dependency_spec.rb +5 -0
  74. data/spec/reactive/eventable_spec.rb +48 -0
  75. data/spec/reactive/reactive_array_spec.rb +97 -0
  76. data/spec/router/routes_spec.rb +26 -27
  77. data/spec/server/html_parser/view_parser_spec.rb +3 -21
  78. data/spec/server/rack/asset_files_spec.rb +1 -1
  79. data/templates/project/app/main/views/main/main.html +2 -2
  80. metadata +29 -41
  81. data/lib/volt/extra_core/time.rb +0 -16
  82. data/lib/volt/page/draw_cycle.rb +0 -31
  83. data/lib/volt/page/memory_test.rb +0 -26
  84. data/lib/volt/page/reactive_template.rb +0 -32
  85. data/lib/volt/reactive/array_extensions.rb +0 -12
  86. data/lib/volt/reactive/destructive_methods.rb +0 -19
  87. data/lib/volt/reactive/event_chain.rb +0 -125
  88. data/lib/volt/reactive/events.rb +0 -216
  89. data/lib/volt/reactive/object_tracking.rb +0 -14
  90. data/lib/volt/reactive/reactive_block.rb +0 -88
  91. data/lib/volt/reactive/reactive_generator.rb +0 -44
  92. data/lib/volt/reactive/reactive_tags.rb +0 -71
  93. data/lib/volt/reactive/reactive_value.rb +0 -427
  94. data/lib/volt/reactive/string_extensions.rb +0 -31
  95. data/spec/integration/test_integration_spec.rb +0 -14
  96. data/spec/models/event_chain_spec.rb +0 -150
  97. data/spec/models/model_buffers_spec.rb +0 -9
  98. data/spec/models/old_model_spec.rb +0 -67
  99. data/spec/models/reactive_array_spec.rb +0 -364
  100. data/spec/models/reactive_block_spec.rb +0 -13
  101. data/spec/models/reactive_call_times_spec.rb +0 -28
  102. data/spec/models/reactive_generator_spec.rb +0 -58
  103. data/spec/models/reactive_tags_spec.rb +0 -35
  104. data/spec/models/reactive_value_spec.rb +0 -370
  105. data/spec/models/store_spec.rb +0 -16
  106. data/spec/models/string_extensions_spec.rb +0 -57
@@ -1,31 +0,0 @@
1
- class String
2
- # include ReactiveTags
3
-
4
- alias :__old_plus :+
5
- if RUBY_PLATFORM != 'opal'
6
- alias :__old_concat :<<
7
- end
8
- # alias :concat :__old_concat
9
-
10
- # In volt, we want a value + reactive strings to return a reactive string. So we
11
- # over-ride + to check for when we are adding a reactive string to a string.
12
- def +(val)
13
- result = __old_plus(val.cur)
14
- if val.reactive? && !result.reactive?
15
- result = ReactiveValue.new(result)
16
- end
17
-
18
- return result
19
- end
20
-
21
- if RUBY_PLATFORM != 'opal'
22
- def <<(val)
23
- if val.reactive?
24
- raise "Cannot append a reactive string to non-reactive string. Use + instead"
25
- end
26
- result = __old_concat(val)
27
-
28
- return result
29
- end
30
- end
31
- end
@@ -1,14 +0,0 @@
1
- if ENV['BROWSER']
2
- require 'spec_helper'
3
-
4
- describe "integration test", :type => :feature do
5
- it "should load the page" do
6
- visit '/'
7
-
8
- expect(page).to have_content('Home')
9
- # expect(page).to have_content('About')
10
- # page.has_text?('About')
11
- # puts "HAS CONTENT: #{page.has_text?('About')}"
12
- end
13
- end
14
- end
@@ -1,150 +0,0 @@
1
- require 'spec_helper'
2
- require 'volt/models'
3
-
4
- describe EventChain do
5
- before do
6
- @a = ReactiveValue.new(1)
7
- @b = ReactiveValue.new(2)
8
- end
9
-
10
- it "should chain events when we use add_object" do
11
-
12
- count = 0
13
- @b.on('changed') { count += 1 }
14
- @b.reactive_manager.event_chain.add_object(@a)
15
- expect(count).to eq(0)
16
-
17
- @a.trigger!('changed')
18
- expect(count).to eq(1)
19
- end
20
-
21
- it "should chain events after add_object is called" do
22
- @b.reactive_manager.event_chain.add_object(@a)
23
-
24
- add_count = 0
25
- @b.on('added') { add_count += 1 }
26
- expect(add_count).to eq(0)
27
- @a.trigger!('added')
28
-
29
- expect(add_count).to eq(1)
30
- end
31
-
32
-
33
- it "should remove events" do
34
- @b.reactive_manager.event_chain.add_object(@a)
35
-
36
- add_count = 0
37
- listener = @b.on('added') { add_count += 1 }
38
- expect(add_count).to eq(0)
39
- @a.trigger!('added')
40
-
41
- expect(add_count).to eq(1)
42
-
43
- # Make sure the event is registered
44
- # TODO: currently fails
45
- # expect(@a.reactive_manager.listeners.size).to eq(1)
46
- expect(@b.reactive_manager.event_chain.instance_variable_get('@event_chain').values[0].keys.include?(:added)).to eq(true)
47
-
48
- listener.remove
49
-
50
- # Make sure its removed
51
- # TODO: also fails
52
- # expect(@a.reactive_manager.listeners.size).to eq(0)
53
- expect(@b.reactive_manager.event_chain.instance_variable_get('@event_chain').values[0].keys.include?(:added)).to eq(false)
54
-
55
- @a.trigger!('added')
56
- expect(add_count).to eq(1)
57
- end
58
-
59
- it "should unchain directly" do
60
- count = 0
61
- a = ReactiveValue.new(Model.new)
62
- b = a._name
63
- listener = b.on('changed') { count += 1 }
64
-
65
- expect(b.reactive_manager.listeners[:changed].size).to eq(1)
66
- # TODO: ideally this would only bind 1 to a
67
- expect(a.reactive_manager.listeners[:changed].size).to eq(1)
68
-
69
- listener.remove
70
-
71
- expect(b.reactive_manager.listeners[:changed]).to eq(nil)
72
- expect(a.reactive_manager.listeners[:changed]).to eq(nil)
73
- end
74
-
75
- it "should unchain" do
76
- count = 0
77
- @b.on('changed') { count += 1 }
78
- b_object_listener = @b.reactive_manager.event_chain.add_object(@a)
79
- expect(count).to eq(0)
80
-
81
- @a.trigger!('changed')
82
- expect(count).to eq(1)
83
-
84
- b_object_listener.remove
85
-
86
- @a.trigger!('changed')
87
- expect(count).to eq(1)
88
- end
89
-
90
- it "should unchain up the chain" do
91
- count = 0
92
- a = ReactiveValue.new(Model.new)
93
-
94
- b = a._list
95
- expect(a.reactive_manager.listeners.size).to eq(0)
96
- listener = b.on('changed') { count += 1 }
97
-
98
- expect(a.reactive_manager.listeners.size).to eq(1)
99
-
100
- listener.remove
101
-
102
- expect(a.reactive_manager.listeners.size).to eq(0)
103
- end
104
-
105
- describe "double add/removes" do
106
- it "should unchain" do
107
- c = ReactiveValue.new(3)
108
- count = 0
109
- @b.on('changed') { count += 1 }
110
- c.on('changed') { count += 1 }
111
-
112
-
113
- # Chain b to a
114
- b_object_listener = @b.reactive_manager.event_chain.add_object(@a)
115
- c_object_listener = c.reactive_manager.event_chain.add_object(@a)
116
- expect(count).to eq(0)
117
-
118
- @a.trigger!('changed')
119
- expect(count).to eq(2)
120
-
121
- b_object_listener.remove
122
-
123
- @a.trigger!('changed')
124
- expect(count).to eq(3)
125
-
126
- c_object_listener.remove
127
-
128
- @a.trigger!('changed')
129
- expect(count).to eq(3)
130
- end
131
- end
132
-
133
- it "should free events when events are unbound" do
134
- a = ReactiveValue.new('cool')
135
- b = a + 'dude'
136
-
137
- expect(a.reactive_manager.event_chain.instance_variable_get('@event_counts')).to eq({})
138
-
139
- listener1 = b.on('changed') { }
140
- expect(a.reactive_manager.event_chain.instance_variable_get('@event_counts')).to_not eq({})
141
-
142
- listener2 = b.on('changed') { }
143
- listener1.remove
144
-
145
- expect(a.reactive_manager.event_chain.instance_variable_get('@event_counts')).to_not eq({})
146
- listener2.remove
147
-
148
- expect(a.reactive_manager.event_chain.instance_variable_get('@event_counts')).to eq({})
149
- end
150
- end
@@ -1,9 +0,0 @@
1
- require 'volt/models'
2
-
3
- describe Model do
4
- it "should create a buffer from an ArrayModel" do
5
- page = ReactiveValue.new(Model.new)
6
-
7
- page._items = []
8
- end
9
- end
@@ -1,67 +0,0 @@
1
- # # require 'volt/spec_helper'
2
- # require 'volt/models'
3
- #
4
- # describe Model do
5
- #
6
- #
7
- # describe "user models" do
8
- # class User < Model
9
- # def full_name
10
- # _first_name + _last_name
11
- # end
12
- # end
13
- #
14
- # class Info < Model ; end
15
- #
16
- # class Todo < Model ; end
17
- #
18
- # before do
19
- # class_models = {
20
- # ['*', '_user'] => User,
21
- # ['*', '_info'] => Info,
22
- # ['*', '_todo'] => Todo
23
- # }
24
- #
25
- # @model = ReactiveValue.new(Model.new({}, nil, 'page', class_models))
26
- # end
27
- #
28
- # it "should be loaded as the correct class" do
29
- # @model._users << {_name: 'Test'}
30
- # @model._users[0].cur.is_a?(User).should == true
31
- # end
32
- #
33
- # it "should be loaded in as the correct class for single items" do
34
- # @model._info._total_users = 5
35
- # @model._info.cur.is_a?(Info).should == true
36
- # end
37
- #
38
- # it "should load the correct nested class" do
39
- # @model._todo_lists << {_name: 'Test1', _todos: []}
40
- # @model._todo_lists[0]._todos << {_label: 'Do something'}
41
- # @model._todo_lists[0]._todos[0].cur.is_a?(Todo).should == true
42
- # end
43
- #
44
- # it "should assume the default model if used incorrectly" do
45
- # @model._infos._something = 10
46
- # @model._infos.cur.is_a?(Info).should == false
47
- # end
48
- #
49
- # it "should keep lookups as children for any looked up value" do
50
- # @model._users << {_first_name: 'Jim', _last_name: 'Bob'}
51
- #
52
- # @model._users.last.cur.is_a?(User).should == true
53
- # # @model._users.last.full_name.dependents.parents.size.should == 2
54
- # end
55
- #
56
- # it "should call changed on methods that depend on other values" do
57
- # @model._users << {_first_name: 'Jim', _last_name: 'Bob'}
58
- #
59
- # count = 0
60
- # @model._users.last.full_name.on('changed') { count += 1 }
61
- # count.should == 0
62
- #
63
- # @model._users.last._first_name = 'James'
64
- # count.should == 1
65
- # end
66
- # end
67
- # end
@@ -1,364 +0,0 @@
1
- require 'volt/models'
2
-
3
- describe ReactiveArray do
4
- it "should trigger a change event on any ReactiveValues derived from items in the array" do
5
- model = ReactiveValue.new(Model.new)
6
-
7
- model._my_ary = [1,2,3]
8
-
9
- array_one_item = model._my_ary[4]
10
-
11
- @changed = false
12
- array_one_item.on('changed') { @changed = true }
13
- expect(@changed).to eq(false)
14
-
15
- model._my_ary.insert(0,1,2)
16
-
17
- expect(@changed).to eq(true)
18
- end
19
-
20
- it "should trigger changed from an insert in all places after the index" do
21
- model = ReactiveValue.new(Model.new)
22
- model._my_ary = [1,2,3]
23
-
24
- count1 = 0
25
- count2 = 0
26
- model._my_ary[1].on('changed') { count1 += 1 }
27
- model._my_ary[3].on('changed') { count2 += 1 }
28
- expect(count1).to eq(0)
29
- expect(count2).to eq(0)
30
-
31
- model._my_ary.insert(1, 10)
32
- expect(count1).to eq(1)
33
- expect(count2).to eq(1)
34
-
35
- expect(model._my_ary.cur).to eq([1,10,2,3])
36
- end
37
-
38
- it "should pass the index the item was inserted at" do
39
- model = ReactiveValue.new(Model.new)
40
- model._my_ary = [1,2,3]
41
-
42
- model._my_ary.on('added') do |_, index|
43
- expect(index).to eq(2)
44
- end
45
-
46
- model._my_ary.insert(2, 20)
47
- end
48
-
49
- it "should pass the index the item was inserted at with multiple inserted objects" do
50
- model = ReactiveValue.new(Model.new)
51
- model._my_ary = [1,2,3]
52
-
53
- received = []
54
- model._my_ary.on('added') do |_, index|
55
- received << index
56
- end
57
-
58
- model._my_ary.insert(2, 20, 30)
59
-
60
- expect(received).to eq([2, 3])
61
- end
62
-
63
- it "should trigger changed on methods of an array model that involve just one cell" do
64
- model = ReactiveValue.new(ReactiveArray.new)
65
-
66
- model << 1
67
- model << 2
68
- model << 3
69
-
70
- max = model.max
71
- expect(max.cur).to eq(3)
72
-
73
- count = 0
74
- max.on('changed') { count += 1 }
75
- expect(count).to eq(0)
76
-
77
- model[0] = 10
78
-
79
- expect(count).to eq(1)
80
- expect(max.cur).to eq(10)
81
- end
82
-
83
- it "should not trigger changed events on cells that are not being updated" do
84
- model = ReactiveValue.new(ArrayModel.new([]))
85
-
86
- model << 1
87
- model << 2
88
- model << 3
89
-
90
- index_0_count = 0
91
- last_count = 0
92
- sum_count = 0
93
- model[0].on('changed') { index_0_count += 1 }
94
- model.last.on('changed') { last_count += 1 }
95
- model.sum.on('changed') { sum_count += 1 }
96
- model[1] = 20
97
-
98
- expect(index_0_count).to eq(0)
99
- expect(sum_count).to eq(1)
100
- expect(last_count).to eq(0)
101
-
102
- expect(model[0].cur).to eq(1)
103
- expect(model[1].cur).to eq(20)
104
- expect(model[2].cur).to eq(3)
105
- expect(model.last.cur).to eq(3)
106
- expect(model.sum.cur).to eq(24)
107
-
108
- model[2] = 100
109
- expect(last_count).to eq(1)
110
- end
111
-
112
- it "should trigger added when an element is added" do
113
- a = ReactiveValue.new(Model.new)
114
- count = 0
115
- a._items.on('added') { count += 1 }
116
- expect(count).to eq(0)
117
-
118
- a._items << 1
119
- expect(count).to eq(1)
120
- end
121
-
122
- it "should trigger updates when appending" do
123
- [:size, :length, :count, :last].each do |attribute|
124
- a = ReactiveValue.new(ReactiveArray.new([1,2,3]))
125
-
126
- count = 0
127
- val = a.send(attribute)
128
- old_value = val.cur
129
- val.on('changed') { count += 1 }
130
- expect(count).to eq(0)
131
-
132
- added_count = 0
133
- a.on('added') { added_count += 1 }
134
- expect(added_count).to eq(0)
135
-
136
- a << 4
137
-
138
- expect(val.cur).to eq(old_value + 1)
139
- expect(count).to eq(1)
140
-
141
- expect(added_count).to eq(1)
142
- end
143
- end
144
-
145
- describe "real world type specs" do
146
- it "should let you add in another array" do
147
- a = ReactiveValue.new(ReactiveArray.new([1,2,3]))
148
-
149
- pos_4 = a[4]
150
- expect(pos_4.cur).to eq(nil)
151
- pos_4_changed = 0
152
- pos_4.on('changed') { pos_4_changed += 1 }
153
-
154
- count = 0
155
- a.on('added') { count += 1 }
156
-
157
- a += [4,5,6]
158
- expect(a.cur).to eq([1,2,3,4,5,6])
159
- # TODO: Failing?
160
- # expect(pos_4_changed).to eq(1)
161
-
162
- # expect(count).to eq(3)
163
- end
164
-
165
- it "should trigger changes when an index that is Reactive changes" do
166
- index = ReactiveValue.new(0)
167
- model = ReactiveValue.new(Model.new)
168
- model._array << 1
169
- model._array << 2
170
- model._array << 3
171
- b = model._array[index]
172
-
173
- direct_count = 0
174
- b.on('changed') { direct_count += 1 }
175
- expect(direct_count).to eq(0)
176
-
177
- model._current_array = b
178
-
179
- count = 0
180
-
181
- model._current_array.on('changed') { count += 1 }
182
- expect(count).to eq(0)
183
-
184
- index.cur = 1
185
- expect(count).to eq(1)
186
- expect(direct_count).to eq(1)
187
- end
188
-
189
- it "should trigger changes when cell data changes when using ReactiveValue's as indicies" do
190
- index = ReactiveValue.new(0)
191
- index2 = ReactiveValue.new(0)
192
- model = ReactiveValue.new(Model.new)
193
- model._array << 1
194
- model._array << 2
195
- model._array << 3
196
-
197
- zero_cell = model._array[index]
198
- zero_cell2 = model._array[index2]
199
-
200
- count = 0
201
- count2 = 0
202
- zero_cell.on('changed') { count += 1 }
203
- zero_cell2.on('changed') { count2 += 1 }
204
-
205
- zero_cell.cur = 3
206
-
207
- expect(count).to eq(1)
208
- expect(count2).to eq(1)
209
- end
210
-
211
-
212
- it "should call added on an array within an array" do
213
- a = ReactiveValue.new(Model.new)
214
- index = ReactiveValue.new(0)
215
- count = 0
216
- a._items << ArrayModel.new([])
217
-
218
- a._items[0].on('added') { count += 1 }
219
- expect(count).to eq(0)
220
-
221
- a._items[0] << 1
222
- expect(count).to eq(1)
223
-
224
- end
225
-
226
- # TODO: Needs to be fixed
227
- # it "should call added through an index from one array to a sub array" do
228
- # model = ReactiveValue.new(Model.new)
229
- # index = ReactiveValue.new(nil)
230
- #
231
- # count = 0
232
- # model._current_todo._todos.on('added') { count += 1 }
233
- # expect(count).to eq(0)
234
- #
235
- # model._todo_lists << Model.new(_name: 'One', _todos: [])
236
- # model._todo_lists << Model.new(_name: 'Two', _todos: [])
237
- #
238
- # model._current_todo = model._todo_lists[0]
239
- #
240
- # model._current_todo._todos << "Svoltle todo"
241
- # expect(count).to eq(1)
242
- # end
243
-
244
- it "should trigger changed when an item is deleted" do
245
- model = ReactiveValue.new(Model.new)
246
- model._items = [1,2,3]
247
-
248
- cur = model._current = model._items[0]
249
-
250
- count = 0
251
- # model._items[0].on('changed') { count += 1}
252
- model._current.on('changed') { count += 1 }
253
- expect(count).to eq(0)
254
-
255
- model._items.delete_at(0)
256
-
257
- expect(count).to eq(1)
258
- end
259
-
260
- it "should not trigger changed on the array when an element is added" do
261
- a = ReactiveValue.new(Model.new)
262
- a._items = []
263
-
264
- count = 0
265
- a._items.on('changed') { count += 1}
266
- expect(count).to eq(0)
267
-
268
- a._items << 1
269
- expect(count).to eq(0)
270
- end
271
-
272
- it "should trigger changed for a Reactive index and a non-reactive index with the same value" do
273
- a = ReactiveValue.new(Model.new)
274
- index = ReactiveValue.new(0)
275
- a._items << 0
276
- a._items << 1
277
-
278
- count = 0
279
- a._items[0].on('changed') { count += 1 }
280
- expect(count).to eq(0)
281
-
282
- a._items[index] = 5
283
- expect(count).to eq(1)
284
-
285
- # Reversed
286
- count2 = 0
287
- a._items[index].on('changed') { count2 += 1 }
288
- expect(count2).to eq(0)
289
-
290
- index.cur = 1
291
-
292
- # Double update since one is bound to a Integer and one to a ReactiveValue
293
- # TODO: Any way to combine these
294
- expect(count2).to eq(2)
295
-
296
- a._items[1] = 2
297
- expect(count2).to eq(3)
298
-
299
- # a._items[index] = 10
300
-
301
-
302
- end
303
-
304
- it "should trigger changed with a negative index assignment" do
305
- a = ReactiveValue.new(ReactiveArray.new([1,2,3]))
306
-
307
- count_0 = 0
308
- count_1 = 0
309
-
310
- a[0].on('changed') { count_0 += 1 }
311
- a[1].on('changed') { count_1 += 1 }
312
-
313
- a[-2] = 50
314
-
315
- expect(count_0).to eq(0)
316
- expect(count_1).to eq(1)
317
- end
318
-
319
- it "should not trigger on other indicies" do
320
- a = ReactiveValue.new(ReactiveArray.new([1,2,3]))
321
-
322
- count = 0
323
- a[0].on('changed') { count += 1 }
324
- expect(count).to eq(0)
325
-
326
- a[1] = 5
327
- expect(count).to eq(0)
328
- end
329
- end
330
-
331
- # describe "concat, diff" do
332
- # it "should concat two arrays and trigger added/removed through" do
333
- # a = ReactiveValue.new(ReactiveArray.new([1,2,3]))
334
- # b = ReactiveValue.new(ReactiveArray.new([1,2,3]))
335
- #
336
- # c = a + b
337
- #
338
- # count = 0
339
- # # c.on('added') { count += 1 }
340
- # c.on('changed') { count += 1 }
341
- # expect(count).to eq(0)
342
- #
343
- # b << 4
344
- #
345
- # expect(count).to eq(1)
346
- # end
347
- # end
348
-
349
- describe "array methods" do
350
- it "should handle compact with events" do
351
- a = ReactiveValue.new(ReactiveArray.new([1,2,nil,3]))
352
-
353
- count = 0
354
- last_position = nil
355
- compact = a.compact
356
- compact.on('changed') { count += 1 }
357
- expect(count).to eq(0)
358
-
359
- a << 4
360
-
361
- expect(count).to eq(1)
362
- end
363
- end
364
- end