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.
- checksums.yaml +4 -4
- data/.travis.yml +8 -1
- data/CHANGELOG.md +22 -0
- data/Gemfile +8 -0
- data/Guardfile +2 -2
- data/Readme.md +139 -136
- data/VERSION +1 -1
- data/app/volt/assets/js/setImmediate.js +175 -0
- data/app/volt/tasks/live_query/data_store.rb +0 -2
- data/app/volt/tasks/live_query/live_query.rb +4 -4
- data/docs/GETTING_STARTED.md +24 -3
- data/docs/WHY.md +1 -22
- data/lib/volt.rb +20 -1
- data/lib/volt/console.rb +20 -0
- data/lib/volt/controllers/model_controller.rb +25 -11
- data/lib/volt/extra_core/object.rb +2 -14
- data/lib/volt/extra_core/string.rb +4 -0
- data/lib/volt/models.rb +0 -1
- data/lib/volt/models/array_model.rb +8 -16
- data/lib/volt/models/cursor.rb +1 -1
- data/lib/volt/models/model.rb +40 -60
- data/lib/volt/models/model_hash_behaviour.rb +10 -24
- data/lib/volt/models/model_helpers.rb +2 -2
- data/lib/volt/models/model_state.rb +1 -1
- data/lib/volt/models/model_wrapper.rb +4 -4
- data/lib/volt/models/persistors/array_store.rb +44 -28
- data/lib/volt/models/persistors/base.rb +1 -1
- data/lib/volt/models/persistors/model_store.rb +1 -1
- data/lib/volt/models/persistors/params.rb +5 -1
- data/lib/volt/models/persistors/query/query_listener.rb +2 -0
- data/lib/volt/models/persistors/store.rb +3 -2
- data/lib/volt/models/persistors/store_state.rb +7 -2
- data/lib/volt/models/url.rb +35 -29
- data/lib/volt/models/validations.rb +7 -17
- data/lib/volt/page/bindings/attribute_binding.rb +57 -39
- data/lib/volt/page/bindings/base_binding.rb +0 -14
- data/lib/volt/page/bindings/content_binding.rb +15 -18
- data/lib/volt/page/bindings/each_binding.rb +67 -34
- data/lib/volt/page/bindings/if_binding.rb +15 -12
- data/lib/volt/page/bindings/template_binding.rb +77 -59
- data/lib/volt/page/bindings/template_binding/grouped_controllers.rb +19 -4
- data/lib/volt/page/channel.rb +22 -38
- data/lib/volt/page/channel_stub.rb +3 -6
- data/lib/volt/page/page.rb +24 -26
- data/lib/volt/page/string_template_renderer.rb +46 -0
- data/lib/volt/page/sub_context.rb +7 -1
- data/lib/volt/page/targets/binding_document/component_node.rb +11 -9
- data/lib/volt/page/tasks.rb +3 -2
- data/lib/volt/page/url_tracker.rb +4 -3
- data/lib/volt/reactive/computation.rb +131 -0
- data/lib/volt/reactive/dependency.rb +71 -0
- data/lib/volt/reactive/eventable.rb +82 -0
- data/lib/volt/reactive/hash_dependency.rb +36 -0
- data/lib/volt/{controllers → reactive}/reactive_accessors.rb +8 -11
- data/lib/volt/reactive/reactive_array.rb +100 -193
- data/lib/volt/reactive/reactive_hash.rb +49 -0
- data/lib/volt/server/html_parser/attribute_scope.rb +24 -4
- data/lib/volt/server/html_parser/if_view_scope.rb +15 -15
- data/lib/volt/server/html_parser/view_scope.rb +31 -1
- data/spec/apps/kitchen_sink/Gemfile +4 -8
- data/spec/apps/kitchen_sink/app/main/config/dependencies.rb +8 -0
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +8 -1
- data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +8 -0
- data/spec/apps/kitchen_sink/app/main/views/main/bindings.html +73 -0
- data/spec/apps/kitchen_sink/app/main/views/main/index.html +6 -1
- data/spec/apps/kitchen_sink/app/main/views/main/main.html +26 -6
- data/spec/apps/kitchen_sink/app/main/views/main/store.html +6 -0
- data/spec/controllers/reactive_accessors_spec.rb +13 -15
- data/spec/integration/bindings_spec.rb +159 -0
- data/spec/integration/templates_spec.rb +15 -0
- data/spec/models/model_spec.rb +130 -228
- data/spec/reactive/computation_spec.rb +63 -0
- data/spec/reactive/dependency_spec.rb +5 -0
- data/spec/reactive/eventable_spec.rb +48 -0
- data/spec/reactive/reactive_array_spec.rb +97 -0
- data/spec/router/routes_spec.rb +26 -27
- data/spec/server/html_parser/view_parser_spec.rb +3 -21
- data/spec/server/rack/asset_files_spec.rb +1 -1
- data/templates/project/app/main/views/main/main.html +2 -2
- metadata +29 -41
- data/lib/volt/extra_core/time.rb +0 -16
- data/lib/volt/page/draw_cycle.rb +0 -31
- data/lib/volt/page/memory_test.rb +0 -26
- data/lib/volt/page/reactive_template.rb +0 -32
- data/lib/volt/reactive/array_extensions.rb +0 -12
- data/lib/volt/reactive/destructive_methods.rb +0 -19
- data/lib/volt/reactive/event_chain.rb +0 -125
- data/lib/volt/reactive/events.rb +0 -216
- data/lib/volt/reactive/object_tracking.rb +0 -14
- data/lib/volt/reactive/reactive_block.rb +0 -88
- data/lib/volt/reactive/reactive_generator.rb +0 -44
- data/lib/volt/reactive/reactive_tags.rb +0 -71
- data/lib/volt/reactive/reactive_value.rb +0 -427
- data/lib/volt/reactive/string_extensions.rb +0 -31
- data/spec/integration/test_integration_spec.rb +0 -14
- data/spec/models/event_chain_spec.rb +0 -150
- data/spec/models/model_buffers_spec.rb +0 -9
- data/spec/models/old_model_spec.rb +0 -67
- data/spec/models/reactive_array_spec.rb +0 -364
- data/spec/models/reactive_block_spec.rb +0 -13
- data/spec/models/reactive_call_times_spec.rb +0 -28
- data/spec/models/reactive_generator_spec.rb +0 -58
- data/spec/models/reactive_tags_spec.rb +0 -35
- data/spec/models/reactive_value_spec.rb +0 -370
- data/spec/models/store_spec.rb +0 -16
- 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,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
|