volt 0.8.27.beta3 → 0.8.27.beta4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/CHANGELOG.md +11 -0
  4. data/CONTRIBUTING.md +3 -2
  5. data/{Readme.md → README.md} +9 -12
  6. data/Rakefile +2 -9
  7. data/VERSION +1 -1
  8. data/app/volt/models/user.rb +8 -0
  9. data/app/volt/tasks/live_query/data_store.rb +13 -5
  10. data/app/volt/tasks/live_query/live_query.rb +45 -3
  11. data/app/volt/tasks/live_query/live_query_pool.rb +9 -1
  12. data/app/volt/tasks/query_tasks.rb +20 -2
  13. data/app/volt/tasks/store_tasks.rb +37 -20
  14. data/app/volt/tasks/user_tasks.rb +15 -13
  15. data/lib/volt/boot.rb +5 -3
  16. data/lib/volt/cli/console.rb +1 -0
  17. data/lib/volt/cli/generate.rb +15 -0
  18. data/lib/volt/cli.rb +19 -12
  19. data/lib/volt/config.rb +1 -1
  20. data/lib/volt/controllers/model_controller.rb +13 -3
  21. data/lib/volt/extra_core/extra_core.rb +1 -0
  22. data/lib/volt/extra_core/hash.rb +26 -0
  23. data/lib/volt/extra_core/object.rb +5 -1
  24. data/lib/volt/models/array_model.rb +86 -35
  25. data/lib/volt/models/associations.rb +53 -0
  26. data/lib/volt/models/buffer.rb +22 -10
  27. data/lib/volt/models/dirty.rb +88 -0
  28. data/lib/volt/models/errors.rb +21 -0
  29. data/lib/volt/models/field_helpers.rb +2 -2
  30. data/lib/volt/models/listener_tracker.rb +17 -0
  31. data/lib/volt/models/model.rb +213 -69
  32. data/lib/volt/models/model_helpers.rb +27 -17
  33. data/lib/volt/models/permissions.rb +246 -0
  34. data/lib/volt/models/persistors/array_store.rb +149 -81
  35. data/lib/volt/models/persistors/base.rb +16 -0
  36. data/lib/volt/models/persistors/cookies.rb +14 -9
  37. data/lib/volt/models/persistors/flash.rb +3 -0
  38. data/lib/volt/models/persistors/local_store.rb +0 -16
  39. data/lib/volt/models/persistors/model_store.rb +1 -2
  40. data/lib/volt/models/persistors/query/normalizer.rb +51 -0
  41. data/lib/volt/models/persistors/query/query_listener.rb +21 -5
  42. data/lib/volt/models/persistors/query/query_listener_pool.rb +0 -9
  43. data/lib/volt/models/persistors/store.rb +8 -0
  44. data/lib/volt/models/persistors/store_state.rb +4 -27
  45. data/lib/volt/models/state_helpers.rb +11 -0
  46. data/lib/volt/models/state_manager.rb +43 -0
  47. data/lib/volt/models/url.rb +5 -5
  48. data/lib/volt/models/validations.rb +38 -41
  49. data/lib/volt/models/validators/email_validator.rb +4 -9
  50. data/lib/volt/models/validators/format_validator.rb +23 -8
  51. data/lib/volt/models/validators/length_validator.rb +2 -2
  52. data/lib/volt/models/validators/numericality_validator.rb +7 -3
  53. data/lib/volt/models/validators/phone_number_validator.rb +4 -9
  54. data/lib/volt/models/validators/presence_validator.rb +2 -2
  55. data/lib/volt/models/validators/unique_validator.rb +2 -2
  56. data/lib/volt/models/validators/user_validation.rb +6 -0
  57. data/lib/volt/models.rb +8 -3
  58. data/lib/volt/page/bindings/attribute_binding.rb +10 -4
  59. data/lib/volt/page/bindings/content_binding.rb +9 -5
  60. data/lib/volt/page/bindings/if_binding.rb +25 -2
  61. data/lib/volt/page/bindings/template_binding.rb +19 -1
  62. data/lib/volt/page/bindings/yield_binding.rb +31 -0
  63. data/lib/volt/page/page.rb +11 -16
  64. data/lib/volt/reactive/class_eventable.rb +71 -0
  65. data/lib/volt/reactive/computation.rb +79 -10
  66. data/lib/volt/reactive/dependency.rb +27 -8
  67. data/lib/volt/reactive/eventable.rb +36 -22
  68. data/lib/volt/reactive/reactive_array.rb +2 -3
  69. data/lib/volt/reactive/reactive_hash.rb +8 -3
  70. data/lib/volt/router/routes.rb +2 -1
  71. data/lib/volt/server/component_templates.rb +0 -2
  72. data/lib/volt/server/html_parser/component_view_scope.rb +59 -0
  73. data/lib/volt/server/html_parser/view_handler.rb +3 -0
  74. data/lib/volt/server/html_parser/view_parser.rb +1 -0
  75. data/lib/volt/server/html_parser/view_scope.rb +17 -41
  76. data/lib/volt/server/rack/component_paths.rb +1 -10
  77. data/lib/volt/server/rack/index_files.rb +9 -4
  78. data/lib/volt/server/rack/opal_files.rb +22 -14
  79. data/lib/volt/server/rack/quiet_common_logger.rb +1 -1
  80. data/lib/volt/server/socket_connection_handler.rb +4 -0
  81. data/lib/volt/spec/setup.rb +26 -0
  82. data/lib/volt/tasks/dispatcher.rb +11 -0
  83. data/lib/volt/utils/event_counter.rb +29 -0
  84. data/lib/volt/utils/generic_pool.rb +12 -0
  85. data/lib/volt/utils/modes.rb +40 -0
  86. data/lib/volt/utils/promise_patch.rb +66 -0
  87. data/lib/volt/utils/timers.rb +33 -0
  88. data/lib/volt/volt/users.rb +48 -5
  89. data/lib/volt.rb +4 -0
  90. data/spec/apps/kitchen_sink/Gemfile +3 -1
  91. data/spec/apps/kitchen_sink/app/main/config/routes.rb +9 -8
  92. data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +9 -0
  93. data/spec/apps/kitchen_sink/app/main/controllers/yield_component_controller.rb +5 -0
  94. data/spec/apps/kitchen_sink/app/main/views/main/cookie_test.html +1 -1
  95. data/spec/apps/kitchen_sink/app/main/views/main/index.html +1 -1
  96. data/spec/apps/kitchen_sink/app/main/views/main/main.html +2 -1
  97. data/spec/apps/kitchen_sink/app/main/views/main/yield.html +18 -0
  98. data/spec/apps/kitchen_sink/app/main/views/yield-component/index.html +4 -0
  99. data/spec/extra_core/logger_spec.rb +4 -2
  100. data/spec/integration/user_spec.rb +42 -42
  101. data/spec/integration/yield_spec.rb +18 -0
  102. data/spec/models/associations_spec.rb +37 -0
  103. data/spec/models/dirty_spec.rb +102 -0
  104. data/spec/models/model_spec.rb +64 -8
  105. data/spec/models/model_state_spec.rb +24 -0
  106. data/spec/models/permissions_spec.rb +96 -0
  107. data/spec/models/user_spec.rb +8 -5
  108. data/spec/models/user_validation_spec.rb +24 -0
  109. data/spec/models/validations_spec.rb +44 -5
  110. data/spec/models/validators/email_validator_spec.rb +109 -82
  111. data/spec/models/validators/format_validator_spec.rb +4 -107
  112. data/spec/models/validators/length_validator_spec.rb +9 -9
  113. data/spec/models/validators/phone_number_validator_spec.rb +60 -103
  114. data/spec/models/validators/shared_examples_for_validators.rb +123 -0
  115. data/spec/reactive/class_eventable_spec.rb +37 -0
  116. data/spec/reactive/computation_spec.rb +68 -3
  117. data/spec/reactive/dependency_spec.rb +71 -0
  118. data/spec/reactive/eventable_spec.rb +21 -0
  119. data/spec/reactive/reactive_hash_spec.rb +12 -0
  120. data/spec/router/routes_spec.rb +50 -50
  121. data/spec/server/html_parser/view_parser_spec.rb +0 -3
  122. data/spec/server/rack/component_paths_spec.rb +11 -0
  123. data/spec/server/rack/quite_common_logger_spec.rb +3 -4
  124. data/spec/spec_helper.rb +7 -3
  125. data/templates/component/config/dependencies.rb +1 -7
  126. data/templates/component/config/routes.rb +1 -1
  127. data/templates/component/controllers/main_controller.rb.tt +20 -0
  128. data/templates/component/views/{index → main}/index.html.tt +0 -0
  129. data/templates/newgem/lib/newgem.rb.tt +1 -3
  130. data/templates/project/app/main/config/routes.rb +3 -3
  131. data/templates/project/app/main/views/main/main.html.tt +4 -4
  132. data/templates/project/config/app.rb.tt +6 -0
  133. data/volt.gemspec +11 -7
  134. metadata +96 -42
  135. data/lib/volt/models/model_state.rb +0 -21
  136. data/templates/component/controllers/main_controller.rb +0 -18
@@ -1,146 +1,103 @@
1
1
  require 'spec_helper'
2
+ require 'models/validators/shared_examples_for_validators'
2
3
 
3
4
  describe Volt::PhoneNumberValidator do
4
- subject { Volt::PhoneNumberValidator.new(*params) }
5
- let(:params) { [model, field_name, options] }
5
+ subject { described_class.new(*init_params) }
6
+ let(:init_params) { [model, field_name] }
6
7
 
7
8
  let(:model) { Volt::Model.new phone_number: phone_number }
8
9
  let(:field_name) { :phone_number }
9
10
  let(:options) { true }
10
11
 
12
+ let(:phone_number) { field_content }
13
+ let(:field_contet) { valid_us_number }
11
14
  let(:valid_us_number) { '(123)-123-1234' }
12
15
  let(:valid_intl_number) { '+12 123 123 1234' }
13
16
  let(:invalid_number) { '1234-123-123456' }
14
- let(:phone_number) { valid_us_number }
15
-
16
- describe '.validate' do
17
- let(:result) { described_class.validate(*params.dup.insert(1, nil)) }
18
-
19
- before do
20
- allow(described_class).to receive(:new).and_return subject
21
- allow(subject).to receive(:errors).and_call_original
22
17
 
23
- result
24
- end
25
-
26
- it 'initializes a phone number validator with the provided arguments' do
27
- expect(described_class).to have_received(:new).with(*params)
28
- end
18
+ let(:validate) { described_class.validate(*params) }
19
+ let(:params) { [model, field_name, options] }
20
+ let(:message) { 'must be a phone number with area or country code' }
29
21
 
30
- it 'calls errors on the phone number validator' do
31
- expect(subject).to have_received :errors
32
- end
22
+ it_behaves_like 'a format validator'
33
23
 
34
- it 'returns the result of calling errors on the validator' do
35
- expect(subject.errors).to eq result
36
- end
24
+ before do
25
+ allow(described_class).to receive(:new).and_return subject
37
26
  end
38
27
 
39
- describe '#valid?' do
40
- context 'when using the default regex' do
41
- let(:options) { true }
42
-
43
- context 'when the phone number is a valid US number' do
44
- let(:phone_number) { valid_us_number }
45
-
46
- specify { expect(subject.valid?).to eq true }
47
- end
48
-
49
- context 'when the phone number is a valid international number' do
50
- let(:phone_number) { valid_intl_number }
51
-
52
- specify { expect(subject.valid?).to eq true }
53
- end
54
-
55
- context 'when the phone number uses dashes' do
56
- let(:phone_number) { '123-123-1234' }
28
+ context 'when the phone number is a valid US number' do
29
+ let(:phone_number) { valid_us_number }
57
30
 
58
- specify { expect(subject.valid?).to eq true }
59
- end
31
+ specify { expect(validate).to eq({}) }
60
32
 
61
- context 'when the phone number uses periods' do
62
- let(:phone_number) { '123.123.1234' }
33
+ context 'and when no override criteria is provided' do
34
+ before { validate }
63
35
 
64
- specify { expect(subject.valid?).to eq true }
36
+ it 'should have no errors' do
37
+ expect(subject.errors).to eq({})
65
38
  end
66
39
 
67
- context 'when the phone number uses spaces' do
68
- let(:phone_number) { '123 123 1234' }
40
+ specify { expect(subject).to be_valid }
41
+ end
42
+ end
69
43
 
70
- specify { expect(subject.valid?).to eq true }
71
- end
44
+ context 'when the model has an invalid phone number' do
45
+ let(:phone_number) { invalid_number }
72
46
 
73
- context 'when the phone number uses parentheses and a space' do
74
- let(:phone_number) { '(123) 123.1234' }
47
+ context 'and when no override criteria is provided' do
48
+ before { validate }
75
49
 
76
- specify { expect(subject.valid?).to eq true }
50
+ it 'returns an array of errors for phone number' do
51
+ expect(subject.errors).to eq field_name => [message]
77
52
  end
53
+ end
54
+ end
78
55
 
79
- context 'when an international number uses a plus' do
80
- let(:phone_number) { '+12 123 123 1234' }
81
-
82
- specify { expect(subject.valid?).to eq true }
83
- end
56
+ context 'when the phone number is a valid international number' do
57
+ let(:phone_number) { valid_intl_number }
84
58
 
85
- context 'when an international number does not use a plus' do
86
- let(:phone_number) { '12 123 123 1234' }
59
+ specify { expect(subject.valid?).to eq true }
60
+ end
87
61
 
88
- specify { expect(subject.valid?).to eq true }
89
- end
62
+ context 'when the phone number uses dashes' do
63
+ let(:phone_number) { '123-123-1234' }
90
64
 
91
- context 'when an international number is from the UK' do
92
- let(:phone_number) { '+12 123 1234 1234' }
65
+ specify { expect(subject.valid?).to eq true }
66
+ end
93
67
 
94
- specify { expect(subject.valid?).to eq true }
95
- end
96
- end
68
+ context 'when the phone number uses periods' do
69
+ let(:phone_number) { '123.123.1234' }
97
70
 
98
- context 'when using a custom regex' do
99
- let(:options) { { with: /\d{10}/ } }
71
+ specify { expect(subject.valid?).to eq true }
72
+ end
100
73
 
101
- context 'and the phone number qualifies' do
102
- let(:phone_number) { '1231231234' }
74
+ context 'when the phone number uses spaces' do
75
+ let(:phone_number) { '123 123 1234' }
103
76
 
104
- specify { expect(subject.valid?).to eq true }
105
- end
77
+ specify { expect(subject.valid?).to eq true }
78
+ end
106
79
 
107
- context 'and the phone number does not qualify' do
108
- let(:phone_number) { '123-123-1234' }
80
+ context 'when the phone number uses parentheses and a space' do
81
+ let(:phone_number) { '(123) 123.1234' }
109
82
 
110
- specify { expect(subject.valid?).to eq false }
111
- end
112
- end
83
+ specify { expect(subject.valid?).to eq true }
113
84
  end
114
85
 
115
- describe '#errors' do
116
- context 'when the model has a valid phone number' do
117
- let(:phone_number) { valid_us_number }
86
+ context 'when an international number uses a plus' do
87
+ let(:phone_number) { '+12 123 123 1234' }
118
88
 
119
- it 'returns an empty error hash' do
120
- expect(subject.errors).to eq({})
121
- end
122
- end
89
+ specify { expect(subject.valid?).to eq true }
90
+ end
123
91
 
124
- context 'when the model has an invalid phone number' do
125
- let(:phone_number) { invalid_number }
92
+ context 'when an international number does not use a plus' do
93
+ let(:phone_number) { '12 123 123 1234' }
126
94
 
127
- it 'returns an array of errors for phone number' do
128
- expect(subject.errors).to eq(
129
- phone_number: ['must be a phone number with area or country code'])
130
- end
131
- end
132
-
133
- context 'when provided a custom error message' do
134
- let(:options) { { message: custom_message } }
135
- let(:custom_message) { 'this is a custom message' }
95
+ specify { expect(subject.valid?).to eq true }
96
+ end
136
97
 
137
- context 'and the phone number is invalid' do
138
- let(:phone_number) { invalid_number }
98
+ context 'when an international number is from the UK' do
99
+ let(:phone_number) { '+12 123 1234 1234' }
139
100
 
140
- it 'returns errors with the custom message' do
141
- expect(subject.errors).to eq(phone_number: [custom_message])
142
- end
143
- end
144
- end
101
+ specify { expect(subject.valid?).to eq true }
145
102
  end
146
- end
103
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for 'a format validator' do
4
+ let(:regex) { /^valid/ }
5
+ let(:proc_regex) { /^valid/ }
6
+ let(:test_proc) { ->(content) { proc_regex.match content } }
7
+
8
+ let(:proc_opts) { { with: test_proc, message: proc_message } }
9
+ let(:regex_opts) { { with: regex, message: regex_message } }
10
+
11
+ let(:field_content) { valid_content }
12
+ let(:invalid_content) { 'invalid_content' }
13
+ let(:valid_content) { 'valid_content' }
14
+
15
+ let(:proc_message) { 'proc is invalid' }
16
+ let(:regex_message) { 'regex is invalid' }
17
+
18
+ before do
19
+ allow(described_class).to receive(:new).and_return subject
20
+ end
21
+
22
+ context 'when the only override criterion is a regex' do
23
+ let(:options) { regex_opts }
24
+
25
+ before { validate }
26
+
27
+ context 'and when the field matches' do
28
+ let(:field_content) { valid_content }
29
+
30
+ it 'should have no errors' do
31
+ expect(subject.errors).to eq({})
32
+ end
33
+
34
+ specify { expect(subject).to be_valid }
35
+ end
36
+
37
+ context 'and when the field does not match' do
38
+ let(:field_content) { invalid_content }
39
+
40
+ it 'should report the related error message' do
41
+ expect(subject.errors).to eq field_name => [regex_message]
42
+ end
43
+
44
+ specify { expect(subject).to_not be_valid }
45
+ end
46
+ end
47
+
48
+ context 'when the only override criterion is a block' do
49
+ let(:options) { proc_opts }
50
+
51
+ before { validate }
52
+
53
+ context 'and when the field passes the block' do
54
+ let(:field_content) { valid_content }
55
+
56
+ it 'should have no errors' do
57
+ expect(subject.errors).to eq({})
58
+ end
59
+
60
+ specify { expect(subject).to be_valid }
61
+ end
62
+
63
+ context 'and when the field fails the block' do
64
+ let(:field_content) { invalid_content }
65
+
66
+ it 'should report the related error message' do
67
+ expect(subject.errors).to eq field_name => [proc_message]
68
+ end
69
+
70
+ specify { expect(subject).to_not be_valid }
71
+ end
72
+ end
73
+
74
+ context 'when there is both regex and block criteria' do
75
+ let(:options) { [ regex_opts, proc_opts ] }
76
+
77
+ before { validate }
78
+
79
+ context 'and when the field passes all criteria' do
80
+ let(:field_content) { valid_content }
81
+
82
+ it 'should have no errors' do
83
+ expect(subject.errors).to eq({})
84
+ end
85
+
86
+ specify { expect(subject).to be_valid }
87
+ end
88
+
89
+ context 'and when the field fails the regex' do
90
+ let(:regex) { /^invalid/ }
91
+
92
+ it 'should report the related error message' do
93
+ expect(subject.errors).to eq field_name => [regex_message]
94
+ end
95
+
96
+ specify { expect(subject).to_not be_valid }
97
+ end
98
+
99
+ context 'and when the field fails the block' do
100
+ let(:proc_regex) { /^invalid/ }
101
+
102
+ it 'should report the related error message' do
103
+ expect(subject.errors).to eq field_name => [proc_message]
104
+ end
105
+
106
+ specify { expect(subject).to_not be_valid }
107
+ end
108
+
109
+ context 'and when the field fails both the regex and the block' do
110
+ let(:field_content) { invalid_content }
111
+
112
+ it 'should report the regex error message' do
113
+ expect(subject.errors[field_name]).to include regex_message
114
+ end
115
+
116
+ it 'should report the proc error message' do
117
+ expect(subject.errors[field_name]).to include proc_message
118
+ end
119
+
120
+ specify { expect(subject).to_not be_valid }
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ class TestClassEventable
4
+ include Volt::ClassEventable
5
+
6
+ attr_reader :run_count
7
+
8
+ def initialize
9
+ @run_count = 0
10
+ end
11
+
12
+ on(:works) do
13
+ ran_works
14
+ end
15
+
16
+ def ran_works
17
+ @run_count += 1
18
+ end
19
+
20
+ def trigger_works_event!
21
+ trigger!(:works, 20)
22
+ end
23
+ end
24
+
25
+ describe Volt::ClassEventable do
26
+ it 'does something' do
27
+ test_ev = TestClassEventable.new
28
+
29
+ expect(test_ev.run_count).to eq(0)
30
+ test_ev.trigger_works_event!
31
+
32
+ expect(test_ev.run_count).to eq(1)
33
+ test_ev.trigger_works_event!
34
+
35
+ expect(test_ev.run_count).to eq(2)
36
+ end
37
+ end
@@ -38,6 +38,57 @@ describe Volt::Computation do
38
38
  expect(values).to eq([nil, 'one'])
39
39
  end
40
40
 
41
+ it 'should watch_until! a value matches' do
42
+ a = Volt::ReactiveHash.new
43
+
44
+ a[:b] = 5
45
+
46
+ count = 0
47
+ -> do
48
+ a[:b]
49
+ end.watch_until!(10) do
50
+ count += 1
51
+ end
52
+
53
+ expect(count).to eq(0)
54
+
55
+ a[:b] = 7
56
+ Volt::Computation.flush!
57
+ expect(count).to eq(0)
58
+
59
+ a[:b] = 10
60
+ Volt::Computation.flush!
61
+ expect(count).to eq(1)
62
+
63
+ # Should only trigger once
64
+ a[:b] = 5
65
+ Volt::Computation.flush!
66
+ expect(count).to eq(1)
67
+
68
+ a[:b] = 10
69
+ Volt::Computation.flush!
70
+ expect(count).to eq(1)
71
+ end
72
+
73
+ it 'should trigger a changed dependency only once on a flush' do
74
+ a = Volt::Dependency.new
75
+
76
+ count = 0
77
+ -> { count += 1 ; a.depend }.watch!
78
+
79
+ expect(count).to eq(1)
80
+
81
+ a.changed!
82
+ a.changed!
83
+ a.changed!
84
+
85
+ expect(count).to eq(1)
86
+
87
+ Volt::Computation.flush!
88
+
89
+ expect(count).to eq(2)
90
+ end
91
+
41
92
  it 'should support nested watches' do
42
93
  a = Volt::ReactiveHash.new
43
94
 
@@ -61,6 +112,20 @@ describe Volt::Computation do
61
112
  expect(values).to eq([nil, nil, 'inner', 'outer', 'inner'])
62
113
  end
63
114
 
115
+ describe "watch_and_resolve!" do
116
+ it 'should resolve any returnted promises' do
117
+ promise = Promise.new.resolve('resolved')
118
+ count = 0
119
+
120
+ -> { promise }.watch_and_resolve! do |result|
121
+ expect(result).to eq('resolved')
122
+ count += 1
123
+ end
124
+
125
+ expect(count).to eq(1)
126
+ end
127
+ end
128
+
64
129
  # Currently Class#class_variable_set/get isn't in opal
65
130
  # https://github.com/opal/opal/issues/677
66
131
  unless RUBY_PLATFORM == 'opal'
@@ -72,7 +137,7 @@ describe Volt::Computation do
72
137
  Volt::Computation.class_variable_set :@@flush_queue, []
73
138
  end
74
139
 
75
- context 'when stopped' do
140
+ describe 'when stopped' do
76
141
  before(:each) { computation.instance_variable_set :@stopped, true }
77
142
 
78
143
  it "doesn't add self to flush queue" do
@@ -82,7 +147,7 @@ describe Volt::Computation do
82
147
  end
83
148
  end
84
149
 
85
- context 'when computing' do
150
+ describe 'when computing' do
86
151
  before(:each) { computation.instance_variable_set :@computing, true }
87
152
 
88
153
  it "doesn't add self to flush queue" do
@@ -92,7 +157,7 @@ describe Volt::Computation do
92
157
  end
93
158
  end
94
159
 
95
- context 'when not stopped and not computing' do
160
+ describe 'when not stopped and not computing' do
96
161
  before(:each) do
97
162
  computation.instance_variable_set :@stopped, false
98
163
  computation.instance_variable_set :@computing, false
@@ -1,4 +1,75 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Volt::Dependency do
4
+ it 'should trigger on_dep and on_stop_dep when setup and torn down' do
5
+ dep_count = 0
6
+ stop_dep_count = 0
7
+ dep = Volt::Dependency.new(-> { dep_count += 1 }, -> { stop_dep_count += 1 })
8
+
9
+ expect(dep_count).to eq(0)
10
+ expect(stop_dep_count).to eq(0)
11
+
12
+ a = -> { dep.depend }.watch!
13
+ b = -> { dep.depend }.watch!
14
+
15
+ expect(dep_count).to eq(1)
16
+ expect(stop_dep_count).to eq(0)
17
+
18
+ a.stop
19
+ expect(dep_count).to eq(1)
20
+ expect(stop_dep_count).to eq(0)
21
+
22
+ b.stop
23
+ expect(dep_count).to eq(1)
24
+ expect(stop_dep_count).to eq(1)
25
+
26
+ # Make sure it triggers if we watch again
27
+ c = -> { dep.depend }.watch!
28
+ d = -> { dep.depend }.watch!
29
+
30
+ expect(dep_count).to eq(2)
31
+ expect(stop_dep_count).to eq(1)
32
+
33
+ c.stop
34
+ expect(dep_count).to eq(2)
35
+ expect(stop_dep_count).to eq(1)
36
+
37
+ d.stop
38
+ expect(dep_count).to eq(2)
39
+ expect(stop_dep_count).to eq(2)
40
+ end
41
+
42
+ it 'should trigger on_dep and on_stop_dep when changed and setup again' do
43
+ dep_count = 0
44
+ stop_dep_count = 0
45
+ dep = Volt::Dependency.new(-> { dep_count += 1 }, -> { stop_dep_count += 1 })
46
+
47
+ expect(dep_count).to eq(0)
48
+ expect(stop_dep_count).to eq(0)
49
+
50
+ a = -> { dep.depend }.watch!
51
+ b = -> { dep.depend }.watch!
52
+
53
+ expect(dep_count).to eq(1)
54
+ expect(stop_dep_count).to eq(0)
55
+
56
+ dep.changed!
57
+ expect(dep_count).to eq(1)
58
+ expect(stop_dep_count).to eq(1)
59
+
60
+ # Make sure it triggers if we watch again
61
+ c = -> { dep.depend }.watch!
62
+ d = -> { dep.depend }.watch!
63
+
64
+ expect(dep_count).to eq(2)
65
+ expect(stop_dep_count).to eq(1)
66
+
67
+ c.stop
68
+ expect(dep_count).to eq(2)
69
+ expect(stop_dep_count).to eq(1)
70
+
71
+ d.stop
72
+ expect(dep_count).to eq(2)
73
+ expect(stop_dep_count).to eq(2)
74
+ end
4
75
  end
@@ -45,4 +45,25 @@ describe Volt::Eventable do
45
45
  test_eventable.trigger_works_event!
46
46
  expect(count).to eq(2)
47
47
  end
48
+
49
+ it 'should allow multiple events' do
50
+ test_eventable = TestEventable.new
51
+
52
+ called = false
53
+ listener = test_eventable.on(:broken, :works) do |arg|
54
+ expect(arg).to eq(20)
55
+ called = true
56
+ end
57
+
58
+ test_eventable.trigger_works_event!
59
+ expect(called).to eq(true)
60
+
61
+ # Stop the listener
62
+ listener.remove
63
+ called = false
64
+
65
+ # Shouldn't run now
66
+ test_eventable.trigger_works_event!
67
+ expect(called).to eq(false)
68
+ end
48
69
  end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Volt::ReactiveHash do
4
+ it 'should clear' do
5
+ a = Volt::ReactiveHash.new
6
+ a[:name] = 'Bob'
7
+
8
+ expect(a[:name]).to eq('Bob')
9
+ a.clear
10
+ expect(a[:name]).to eq(nil)
11
+ end
12
+ end