volt 0.9.2 → 0.9.3.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/CONTRIBUTING.md +4 -0
- data/Gemfile +3 -0
- data/app/volt/assets/js/volt_js_polyfills.js +0 -1
- data/app/volt/assets/js/volt_watch.js +217 -0
- data/app/volt/models/user.rb +7 -2
- data/app/volt/tasks/query_tasks.rb +6 -0
- data/lib/volt/boot.rb +1 -1
- data/lib/volt/cli/generate.rb +1 -1
- data/lib/volt/config.rb +12 -2
- data/lib/volt/controllers/model_controller.rb +1 -1
- data/lib/volt/data_stores/base_adaptor_client.rb +34 -0
- data/lib/volt/data_stores/{base.rb → base_adaptor_server.rb} +1 -1
- data/lib/volt/data_stores/data_store.rb +23 -7
- data/lib/volt/models/array_model.rb +3 -2
- data/lib/volt/models/model.rb +29 -91
- data/lib/volt/models/{dirty.rb → model_helpers/dirty.rb} +0 -0
- data/lib/volt/models/{listener_tracker.rb → model_helpers/listener_tracker.rb} +0 -0
- data/lib/volt/models/model_helpers/model_change_helpers.rb +76 -0
- data/lib/volt/models/{model_helpers.rb → model_helpers/model_helpers.rb} +0 -0
- data/lib/volt/models/persistors/array_store.rb +2 -23
- data/lib/volt/models/persistors/query/normalizer.rb +0 -44
- data/{templates/project/lib/.empty_directory → lib/volt/models/validations/errors.rb} +0 -0
- data/lib/volt/models/{validations.rb → validations/validations.rb} +80 -26
- data/lib/volt/page/bindings/attribute_binding.rb +17 -3
- data/lib/volt/page/page.rb +1 -0
- data/lib/volt/reactive/eventable.rb +1 -0
- data/lib/volt/server.rb +2 -1
- data/lib/volt/server/component_templates.rb +66 -16
- data/lib/volt/server/forking_server.rb +16 -14
- data/lib/volt/server/html_parser/sandlebars_parser.rb +2 -0
- data/lib/volt/server/html_parser/view_scope.rb +2 -0
- data/lib/volt/server/rack/component_paths.rb +4 -2
- data/lib/volt/server/rack/opal_files.rb +4 -2
- data/lib/volt/server/socket_connection_handler.rb +5 -1
- data/lib/volt/server/template_handlers/handlers.rb +0 -0
- data/lib/volt/spec/setup.rb +23 -8
- data/lib/volt/tasks/dispatcher.rb +4 -0
- data/lib/volt/utils/promise_patch.rb +3 -0
- data/lib/volt/version.rb +1 -1
- data/spec/apps/kitchen_sink/Gemfile +5 -0
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +1 -0
- data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +10 -0
- data/spec/apps/kitchen_sink/app/main/views/main/bindings.html +20 -0
- data/spec/apps/kitchen_sink/app/main/views/main/form.html +73 -0
- data/spec/apps/kitchen_sink/app/main/views/main/main.html +1 -0
- data/spec/integration/bindings_spec.rb +33 -0
- data/spec/integration/user_spec.rb +51 -21
- data/spec/models/associations_spec.rb +8 -0
- data/spec/models/model_spec.rb +7 -0
- data/spec/models/user_spec.rb +20 -0
- data/spec/models/validations_spec.rb +2 -1
- data/spec/models/validators/block_validations_spec.rb +53 -0
- data/spec/page/bindings/template_binding/view_lookup_for_path_spec.rb +10 -0
- data/spec/page/path_string_renderer_spec.rb +6 -0
- data/spec/reactive/eventable_spec.rb +24 -6
- data/spec/server/component_templates_spec.rb +21 -0
- data/spec/server/html_parser/sandlebars_parser_spec.rb +12 -13
- data/spec/server/html_parser/view_parser_spec.rb +3 -0
- data/spec/server/rack/asset_files_spec.rb +2 -2
- data/spec/server/rack/http_resource_spec.rb +10 -0
- data/spec/tasks/dispatcher_spec.rb +5 -0
- data/spec/tasks/user_tasks_spec.rb +59 -0
- data/spec/utils/task_argument_filtererer_spec.rb +6 -0
- data/templates/newgem/app/newgem/config/initializers/boot.rb +10 -0
- data/templates/newgem/lib/newgem.rb.tt +13 -0
- data/templates/project/Gemfile.tt +3 -0
- data/templates/project/app/main/lib/.empty_directory +0 -0
- data/volt.gemspec +3 -1
- metadata +24 -25
- data/lib/volt/data_stores/mongo_driver.rb +0 -69
@@ -113,6 +113,26 @@
|
|
113
113
|
</tr>
|
114
114
|
</table>
|
115
115
|
|
116
|
+
<h2>If Bindings</h2>
|
117
|
+
<p id='ifbinding'>
|
118
|
+
{{ if page._show && true }}
|
119
|
+
<span>If _show</span>
|
120
|
+
{{ else }}
|
121
|
+
<span>If false _show</span>
|
122
|
+
{{ end }}
|
123
|
+
</p>
|
124
|
+
|
125
|
+
<h2>Unless Bindings</h2>
|
126
|
+
<p id='unlessbinding'>
|
127
|
+
{{ unless page._show && true }}
|
128
|
+
<span>Unless _show</span>
|
129
|
+
{{ else }}
|
130
|
+
<span>Unless false _show</span>
|
131
|
+
{{ end }}
|
132
|
+
</p>
|
133
|
+
|
134
|
+
<a id='showtrue' e-click='set_show(true)'>set _show true</a>
|
135
|
+
<a id='showfalse' e-click='set_show(false)'>set _show false</a>
|
116
136
|
|
117
137
|
<h2>Content</h2>
|
118
138
|
|
@@ -0,0 +1,73 @@
|
|
1
|
+
<:Title>
|
2
|
+
Form
|
3
|
+
|
4
|
+
<:Body>
|
5
|
+
<h1>Form Example</h1>
|
6
|
+
<h2 id='title'></h2>
|
7
|
+
|
8
|
+
<form role="form">
|
9
|
+
<div class="form-group">
|
10
|
+
<label>Name</label>
|
11
|
+
<span id='name-display'>{{ _name }}</span>
|
12
|
+
<label>Location</label>
|
13
|
+
<span id='location-display'>{{ _location }}</span>
|
14
|
+
</div>
|
15
|
+
<input class="form-control" id="name" type="hidden" value="{{ _name }}" />
|
16
|
+
<div class="form-group">
|
17
|
+
<label>Location</label>
|
18
|
+
<select id='location' value='{{ _location }}'>
|
19
|
+
<option value="">State</option>
|
20
|
+
<option value="AL">Alabama</option>
|
21
|
+
<option value="AK">Alaska</option>
|
22
|
+
<option value="AZ">Arizona</option>
|
23
|
+
<option value="AR">Arkansas</option>
|
24
|
+
<option value="CA">California</option>
|
25
|
+
<option value="CO">Colorado</option>
|
26
|
+
<option value="CT">Connecticut</option>
|
27
|
+
<option value="DE">Delaware</option>
|
28
|
+
<option value="DC">District Of Columbia</option>
|
29
|
+
<option value="FL">Florida</option>
|
30
|
+
<option value="GA">Georgia</option>
|
31
|
+
<option value="HI">Hawaii</option>
|
32
|
+
<option value="ID">Idaho</option>
|
33
|
+
<option value="IL">Illinois</option>
|
34
|
+
<option value="IN">Indiana</option>
|
35
|
+
<option value="IA">Iowa</option>
|
36
|
+
<option value="KS">Kansas</option>
|
37
|
+
<option value="KY">Kentucky</option>
|
38
|
+
<option value="LA">Louisiana</option>
|
39
|
+
<option value="ME">Maine</option>
|
40
|
+
<option value="MD">Maryland</option>
|
41
|
+
<option value="MA">Massachusetts</option>
|
42
|
+
<option value="MI">Michigan</option>
|
43
|
+
<option value="MN">Minnesota</option>
|
44
|
+
<option value="MS">Mississippi</option>
|
45
|
+
<option value="MO">Missouri</option>
|
46
|
+
<option value="MT">Montana</option>
|
47
|
+
<option value="NE">Nebraska</option>
|
48
|
+
<option value="NV">Nevada</option>
|
49
|
+
<option value="NH">New Hampshire</option>
|
50
|
+
<option value="NJ">New Jersey</option>
|
51
|
+
<option value="NM">New Mexico</option>
|
52
|
+
<option value="NY">New York</option>
|
53
|
+
<option value="NC">North Carolina</option>
|
54
|
+
<option value="ND">North Dakota</option>
|
55
|
+
<option value="OH">Ohio</option>
|
56
|
+
<option value="OK">Oklahoma</option>
|
57
|
+
<option value="OR">Oregon</option>
|
58
|
+
<option value="PA">Pennsylvania</option>
|
59
|
+
<option value="RI">Rhode Island</option>
|
60
|
+
<option value="SC">South Carolina</option>
|
61
|
+
<option value="SD">South Dakota</option>
|
62
|
+
<option value="TN">Tennessee</option>
|
63
|
+
<option value="TX">Texas</option>
|
64
|
+
<option value="UT">Utah</option>
|
65
|
+
<option value="VT">Vermont</option>
|
66
|
+
<option value="VA">Virginia</option>
|
67
|
+
<option value="WA">Washington</option>
|
68
|
+
<option value="WV">West Virginia</option>
|
69
|
+
<option value="WI">Wisconsin</option>
|
70
|
+
<option value="WY">Wyoming</option>
|
71
|
+
</select>
|
72
|
+
</div>
|
73
|
+
</form>
|
@@ -186,6 +186,24 @@ describe 'bindings test', type: :feature, sauce: true do
|
|
186
186
|
end
|
187
187
|
end
|
188
188
|
|
189
|
+
describe 'if/unless binding' do
|
190
|
+
it 'should show corret text' do
|
191
|
+
visit '/'
|
192
|
+
|
193
|
+
click_link 'Bindings'
|
194
|
+
|
195
|
+
click_on 'showtrue'
|
196
|
+
|
197
|
+
expect(find('#ifbinding')).to have_content('If _show')
|
198
|
+
expect(find('#unlessbinding')).to have_content('Unless false _show')
|
199
|
+
|
200
|
+
click_on 'showfalse'
|
201
|
+
|
202
|
+
expect(find('#ifbinding')).to have_content('If false _show')
|
203
|
+
expect(find('#unlessbinding')).to have_content('Unless _show')
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
189
207
|
describe 'content escaping' do
|
190
208
|
it 'should escape in a tripple stash' do
|
191
209
|
visit '/'
|
@@ -195,4 +213,19 @@ describe 'bindings test', type: :feature, sauce: true do
|
|
195
213
|
expect(find('#escapeContent')).to have_content('this is {{escaped}}')
|
196
214
|
end
|
197
215
|
end
|
216
|
+
|
217
|
+
if ENV['BROWSER'] != 'phantom'
|
218
|
+
describe 'input hidden and select' do
|
219
|
+
it 'should display binding value' do
|
220
|
+
visit '/'
|
221
|
+
|
222
|
+
click_link 'Form'
|
223
|
+
|
224
|
+
expect(find('body')).to have_content('Form Example')
|
225
|
+
expect(find('#title')).to have_content('form_ready')
|
226
|
+
expect(find('#name-display')).to have_content('Test')
|
227
|
+
expect(find('#location-display')).to have_content('AL')
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
198
231
|
end
|
@@ -19,27 +19,6 @@ describe 'user accounts', type: :feature, sauce: true do
|
|
19
19
|
expect(page).to have_content('Test Account 9550')
|
20
20
|
end
|
21
21
|
|
22
|
-
it 'should login and logout' do
|
23
|
-
visit '/'
|
24
|
-
|
25
|
-
# Add the user
|
26
|
-
store._users! << { email: 'test@test.com', password: 'awes0mesEcRet', name: 'Test Account 9550' }
|
27
|
-
|
28
|
-
click_link 'Login'
|
29
|
-
|
30
|
-
fields = all(:css, 'form .form-control')
|
31
|
-
fields[0].set('test@test.com')
|
32
|
-
fields[1].set('awes0mesEcRet')
|
33
|
-
click_button 'Login'
|
34
|
-
|
35
|
-
expect(page).to have_content('Test Account 9550')
|
36
|
-
|
37
|
-
# Click the logout link
|
38
|
-
click_link 'Test Account 9550'
|
39
|
-
click_link 'Logout'
|
40
|
-
|
41
|
-
expect(page).to_not have_content('Test Account 9550')
|
42
|
-
end
|
43
22
|
|
44
23
|
it 'should fail to create an account without a valid email and password' do
|
45
24
|
visit '/'
|
@@ -60,4 +39,55 @@ describe 'user accounts', type: :feature, sauce: true do
|
|
60
39
|
|
61
40
|
expect(page).to have_content('must be at least 8 characters')
|
62
41
|
end
|
42
|
+
|
43
|
+
describe "with a user" do
|
44
|
+
before do
|
45
|
+
# Add the user
|
46
|
+
store._users! << { email: 'test@test.com', password: 'awes0mesEcRet', name: 'Test Account 9550' }
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should login and logout' do
|
50
|
+
visit '/'
|
51
|
+
|
52
|
+
click_link 'Login'
|
53
|
+
|
54
|
+
fields = all(:css, 'form .form-control')
|
55
|
+
fields[0].set('test@test.com')
|
56
|
+
fields[1].set('awes0mesEcRet')
|
57
|
+
click_button 'Login'
|
58
|
+
|
59
|
+
expect(page).to have_content('Test Account 9550')
|
60
|
+
|
61
|
+
# Click the logout link
|
62
|
+
click_link 'Test Account 9550'
|
63
|
+
click_link 'Logout'
|
64
|
+
|
65
|
+
expect(page).to_not have_content('Test Account 9550')
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should show an error for invalid email' do
|
69
|
+
visit '/'
|
70
|
+
click_link 'Login'
|
71
|
+
|
72
|
+
fields = all(:css, 'form .form-control')
|
73
|
+
fields[0].set('notausersemail@gmail.com')
|
74
|
+
fields[1].set('awes0mesEcRet')
|
75
|
+
click_button 'Login'
|
76
|
+
|
77
|
+
expect(page).to have_content('User could not be found')
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should show an error for an invalid password' do
|
81
|
+
visit '/'
|
82
|
+
click_link 'Login'
|
83
|
+
|
84
|
+
fields = all(:css, 'form .form-control')
|
85
|
+
fields[0].set('test@test.com')
|
86
|
+
fields[1].set('wrongpassword')
|
87
|
+
click_button 'Login'
|
88
|
+
|
89
|
+
expect(page).to have_content('Password did not match')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
63
93
|
end
|
@@ -30,5 +30,13 @@ describe Volt::Associations do
|
|
30
30
|
expect(addresses.size).to eq(2)
|
31
31
|
expect(addresses[0]._city).to eq('Bozeman')
|
32
32
|
end
|
33
|
+
|
34
|
+
it 'warns users if persistor is not a ModelStore' do
|
35
|
+
store = Volt::Model.new({}, persistor: Volt::Persistors::Flash)
|
36
|
+
expect do
|
37
|
+
store.send(:association_with_root_model, :blah)
|
38
|
+
end.to raise_error("blah currently only works on the store collection "\
|
39
|
+
"(support for other collections coming soon)")
|
40
|
+
end
|
33
41
|
end
|
34
42
|
end
|
data/spec/models/model_spec.rb
CHANGED
@@ -13,6 +13,13 @@ class TestAssignsMethod < Volt::Model
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe Volt::Model do
|
16
|
+
it 'delegates unary operator to its attributes' do
|
17
|
+
model = Volt::Model.new
|
18
|
+
expect(!model).to eq(!model.attributes)
|
19
|
+
model = Volt::Model.new(has: 'attrs')
|
20
|
+
expect(!model).to eq(!model.attributes)
|
21
|
+
end
|
22
|
+
|
16
23
|
it 'should allow _ methods to be used to store values without predefining them' do
|
17
24
|
a = Volt::Model.new
|
18
25
|
a._stash = 'yes'
|
data/spec/models/user_spec.rb
CHANGED
@@ -60,8 +60,28 @@ describe Volt::User do
|
|
60
60
|
expect(user._hashed_password).to eq 'hashed-password'
|
61
61
|
end
|
62
62
|
end
|
63
|
+
|
64
|
+
it 'should allow updates without validating the password' do
|
65
|
+
bob = store._users.buffer(name: 'Bob', email: 'bob@bob.com', password: '39sdjkdf932jklsd')
|
66
|
+
bob.save!
|
67
|
+
|
68
|
+
expect(bob._password).to eq(nil)
|
69
|
+
|
70
|
+
bob_buf = bob.buffer
|
71
|
+
|
72
|
+
bob_buf._name = 'Jimmy'
|
73
|
+
|
74
|
+
saved = false
|
75
|
+
bob_buf.save! do
|
76
|
+
saved = true
|
77
|
+
end
|
78
|
+
|
79
|
+
expect(saved).to eq(true)
|
80
|
+
end
|
63
81
|
end
|
64
82
|
|
83
|
+
|
84
|
+
|
65
85
|
describe 'when it is not a Volt server' do
|
66
86
|
before do
|
67
87
|
allow(Volt).to receive(:server?).and_return false
|
@@ -15,6 +15,7 @@ describe Volt::Model do
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
|
18
19
|
let(:test_model_with_promises) do
|
19
20
|
Class.new(Volt::Model) do
|
20
21
|
attr_accessor :ran_promise
|
@@ -41,7 +42,6 @@ describe Volt::Model do
|
|
41
42
|
|
42
43
|
it 'should show all fields in marked errors once saved' do
|
43
44
|
buffer = model.buffer
|
44
|
-
|
45
45
|
buffer.save!
|
46
46
|
|
47
47
|
expect(buffer.marked_errors.keys).to eq(
|
@@ -164,4 +164,5 @@ describe Volt::Model do
|
|
164
164
|
model._name = 'ok' # fails again
|
165
165
|
expect(model._name).to eq('Jimmy')
|
166
166
|
end
|
167
|
+
|
167
168
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
unless RUBY_PLATFORM == 'opal'
|
4
|
+
describe 'validations block' do
|
5
|
+
let(:model) { test_model_class.new }
|
6
|
+
|
7
|
+
let(:test_model_class) do
|
8
|
+
Class.new(Volt::Model) do
|
9
|
+
validations do
|
10
|
+
if _is_ready == true
|
11
|
+
validate :name, length: 5
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:test_model_action_pass_class) do
|
18
|
+
Class.new(Volt::Model) do
|
19
|
+
validations do |action|
|
20
|
+
# Only validation the name on update
|
21
|
+
if action == :update
|
22
|
+
validate :name, length: 5
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should run conditional validations in the validations block' do
|
29
|
+
a = test_model_class.new(name: 'Jo')
|
30
|
+
|
31
|
+
a.validate!.sync
|
32
|
+
expect(a.errors.size).to eq(0)
|
33
|
+
|
34
|
+
a._is_ready = true
|
35
|
+
a.validate!.sync
|
36
|
+
|
37
|
+
expect(a.errors.size).to eq(1)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should send the action name to the validations block' do
|
41
|
+
jo = test_model_action_pass_class.new(name: 'Jo')
|
42
|
+
|
43
|
+
jo.validate!.sync
|
44
|
+
expect(jo.errors.size).to eq(0)
|
45
|
+
|
46
|
+
store._people << jo
|
47
|
+
|
48
|
+
jo.validate!.sync
|
49
|
+
expect(jo.errors.size).to eq(1)
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -140,4 +140,14 @@ describe Volt::ViewBinding do
|
|
140
140
|
|
141
141
|
expect(@view_lookup.path_for_template('nav', 'title').first).to eq('nav/main/index/title')
|
142
142
|
end
|
143
|
+
|
144
|
+
it 'should return nils when given a non-existant path' do
|
145
|
+
@templates = {
|
146
|
+
'nav/main/index/title' => '',
|
147
|
+
'auth/login/new/title' => ''
|
148
|
+
}
|
149
|
+
|
150
|
+
expect(@view_lookup.path_for_template('not/a/real/item/')).to eq([nil, nil])
|
151
|
+
end
|
152
|
+
|
143
153
|
end
|
@@ -18,5 +18,11 @@ unless RUBY_PLATFORM == 'opal'
|
|
18
18
|
html = Volt::PathStringRenderer.new('main/mailers/welcome/html', { name: 'Jimmy' }, @page).html
|
19
19
|
expect(html).to eq("\n <h1>Welcome Jimmy</h1>\n\n <p>Glad you signed up!</p>\n\n")
|
20
20
|
end
|
21
|
+
|
22
|
+
it 'Raises raises ViewLookupException if full_path is nil' do
|
23
|
+
expect do
|
24
|
+
Volt::PathStringRenderer.new('', { name: 'Jimmy' }, Volt::Page.new).html
|
25
|
+
end.to raise_error(Volt::ViewLookupException)
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
@@ -3,6 +3,15 @@ require 'volt/reactive/eventable'
|
|
3
3
|
|
4
4
|
class TestEventable
|
5
5
|
include Volt::Eventable
|
6
|
+
attr_reader :events_removed
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@events_removed = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def event_removed(event, last, last_for_event)
|
13
|
+
@events_removed.push(event => [last, last_for_event])
|
14
|
+
end
|
6
15
|
|
7
16
|
def trigger_works_event!
|
8
17
|
trigger!('works', 20)
|
@@ -10,9 +19,9 @@ class TestEventable
|
|
10
19
|
end
|
11
20
|
|
12
21
|
describe Volt::Eventable do
|
13
|
-
|
14
|
-
test_eventable = TestEventable.new
|
22
|
+
let(:test_eventable) { TestEventable.new }
|
15
23
|
|
24
|
+
it 'should allow events to be bound with on' do
|
16
25
|
count = 0
|
17
26
|
test_eventable.on('works') do |val|
|
18
27
|
count += 1
|
@@ -25,8 +34,6 @@ describe Volt::Eventable do
|
|
25
34
|
end
|
26
35
|
|
27
36
|
it 'should allow events to be removed with .remove' do
|
28
|
-
test_eventable = TestEventable.new
|
29
|
-
|
30
37
|
count = 0
|
31
38
|
listener = test_eventable.on('works') do
|
32
39
|
count += 1
|
@@ -47,8 +54,6 @@ describe Volt::Eventable do
|
|
47
54
|
end
|
48
55
|
|
49
56
|
it 'should allow multiple events' do
|
50
|
-
test_eventable = TestEventable.new
|
51
|
-
|
52
57
|
called = false
|
53
58
|
listener = test_eventable.on(:broken, :works) do |arg|
|
54
59
|
expect(arg).to eq(20)
|
@@ -66,4 +71,17 @@ describe Volt::Eventable do
|
|
66
71
|
test_eventable.trigger_works_event!
|
67
72
|
expect(called).to eq(false)
|
68
73
|
end
|
74
|
+
|
75
|
+
it 'Shows object ID and events when inspected' do
|
76
|
+
tested = TestEventable.new.on("test") { nil }
|
77
|
+
inspected = tested.inspect
|
78
|
+
expect(inspected).to include(tested.object_id.to_s)
|
79
|
+
expect(inspected).to include(tested.events.first.to_s)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'calls event_removed on the class included on removal of event' do
|
83
|
+
listener = test_eventable.on("test") { nil }
|
84
|
+
listener.remove
|
85
|
+
expect(test_eventable.events_removed).to include(test: [true, true])
|
86
|
+
end
|
69
87
|
end
|