volt 0.8.27.beta6 → 0.8.27.beta7
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/CHANGELOG.md +16 -3
- data/VERSION +1 -1
- data/app/volt/models/user.rb +1 -1
- data/app/volt/tasks/query_tasks.rb +2 -2
- data/app/volt/tasks/store_tasks.rb +14 -4
- data/app/volt/tasks/user_tasks.rb +1 -1
- data/lib/volt/controllers/http_controller.rb +60 -0
- data/lib/volt/controllers/model_controller.rb +5 -1
- data/lib/volt/extra_core/string.rb +6 -0
- data/lib/volt/models/array_model.rb +6 -2
- data/lib/volt/models/associations.rb +1 -1
- data/lib/volt/models/buffer.rb +14 -3
- data/lib/volt/models/model.rb +28 -60
- data/lib/volt/models/permissions.rb +4 -4
- data/lib/volt/reactive/computation.rb +15 -15
- data/lib/volt/reactive/reactive_array.rb +1 -0
- data/lib/volt/router/routes.rb +67 -27
- data/lib/volt/server.rb +37 -6
- data/lib/volt/server/component_templates.rb +2 -2
- data/lib/volt/server/rack/http_request.rb +50 -0
- data/lib/volt/server/rack/http_resource.rb +41 -0
- data/lib/volt/server/rack/http_response_header.rb +33 -0
- data/lib/volt/server/rack/http_response_renderer.rb +41 -0
- data/lib/volt/spec/setup.rb +4 -2
- data/lib/volt/tasks/dispatcher.rb +7 -7
- data/lib/volt/tasks/task_handler.rb +1 -1
- data/lib/volt/volt/users.rb +12 -6
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +18 -10
- data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +2 -2
- data/spec/apps/kitchen_sink/app/main/controllers/server/simple_http_controller.rb +15 -0
- data/spec/apps/kitchen_sink/app/main/controllers/upload_controller.rb +22 -0
- data/spec/apps/kitchen_sink/app/main/views/main/yield.html +2 -2
- data/spec/apps/kitchen_sink/app/main/views/upload/index.html +15 -0
- data/spec/controllers/http_controller_spec.rb +130 -0
- data/spec/extra_core/string_transformation_test_cases.rb +8 -0
- data/spec/extra_core/string_transformations_spec.rb +12 -0
- data/spec/integration/http_endpoints_spec.rb +29 -0
- data/spec/integration/user_spec.rb +42 -42
- data/spec/models/associations_spec.rb +4 -4
- data/spec/models/buffer_spec.rb +15 -0
- data/spec/models/model_spec.rb +70 -25
- data/spec/models/model_state_spec.rb +1 -1
- data/spec/models/permissions_spec.rb +64 -2
- data/spec/models/persistors/params_spec.rb +8 -8
- data/spec/models/persistors/store_spec.rb +1 -1
- data/spec/models/user_validation_spec.rb +1 -1
- data/spec/router/routes_spec.rb +111 -43
- data/spec/server/rack/http_request_spec.rb +50 -0
- data/spec/server/rack/http_resource_spec.rb +59 -0
- data/spec/server/rack/http_response_header_spec.rb +34 -0
- data/spec/server/rack/http_response_renderer_spec.rb +33 -0
- data/spec/tasks/dispatcher_spec.rb +2 -2
- data/templates/component/config/routes.rb +2 -2
- data/templates/project/Gemfile.tt +3 -5
- data/templates/project/app/main/config/routes.rb +4 -4
- data/volt.gemspec +2 -2
- metadata +33 -8
@@ -33,48 +33,48 @@ if ENV['BROWSER']
|
|
33
33
|
|
34
34
|
expect(page).to have_content('Test Account 9550')
|
35
35
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
36
|
+
|
37
|
+
it 'should login and logout' do
|
38
|
+
visit '/'
|
39
|
+
|
40
|
+
# Add the user
|
41
|
+
store._users! << { email: 'test@test.com', password: 'awes0mesEcRet', name: 'Test Account 9550' }
|
42
|
+
|
43
|
+
click_link 'Login'
|
44
|
+
|
45
|
+
fields = all(:css, 'form .form-control')
|
46
|
+
fields[0].set('test@test.com')
|
47
|
+
fields[1].set('awes0mesEcRet')
|
48
|
+
click_button 'Login'
|
49
|
+
|
50
|
+
expect(page).to have_content('Test Account 9550')
|
51
|
+
|
52
|
+
# Click the logout link
|
53
|
+
click_link 'Test Account 9550'
|
54
|
+
click_link 'Logout'
|
55
|
+
|
56
|
+
expect(page).to_not have_content('Test Account 9550')
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should fail to create an account without a valid email and password' do
|
60
|
+
visit '/'
|
61
|
+
|
62
|
+
click_link 'Login'
|
63
|
+
click_link 'Signup here'
|
64
|
+
|
65
|
+
expect(page).to_not have_content('must be at least 8 characters')
|
66
|
+
|
67
|
+
fields = all(:css, 'form .form-control')
|
68
|
+
|
69
|
+
fields[0].set('test')
|
70
|
+
fields[1].set('awe')
|
71
|
+
fields[2].set('Tes')
|
72
|
+
|
73
|
+
# some capybara drivers don't trigger blur correctly
|
74
|
+
page.execute_script("$('.form-control').blur()")
|
75
|
+
|
76
|
+
expect(page).to have_content('must be at least 8 characters')
|
77
|
+
end
|
78
78
|
end
|
79
79
|
|
80
80
|
end
|
@@ -14,20 +14,20 @@ describe Volt::Associations do
|
|
14
14
|
# DataStore.new.drop_database
|
15
15
|
# $page.instance_variable_set('@store', nil)
|
16
16
|
|
17
|
-
store._people << {name: 'Jimmy'}
|
17
|
+
store._people! << {name: 'Jimmy'}
|
18
18
|
@person = store._people[0]
|
19
|
-
@person._addresses << {city: 'Bozeman'}
|
19
|
+
@person._addresses! << {city: 'Bozeman'}
|
20
20
|
@person._addresses << {city: 'Portland'}
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'should associate via belongs_to' do
|
24
|
-
address = store._addresses
|
24
|
+
address = store._addresses!.fetch_first.sync
|
25
25
|
|
26
26
|
expect(address.person.sync._id).to eq(@person._id)
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'should associate via has_many' do
|
30
|
-
person = store._people
|
30
|
+
person = store._people!.fetch_first.sync
|
31
31
|
|
32
32
|
addresses = person.addresses.fetch.sync
|
33
33
|
expect(addresses.size).to eq(2)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Volt::Buffer do
|
4
|
+
it 'should let you pass a block that evaluates to the then of the promise' do
|
5
|
+
buffer = the_page._items!.buffer
|
6
|
+
|
7
|
+
count = 0
|
8
|
+
result = buffer.save! do
|
9
|
+
count += 1
|
10
|
+
end
|
11
|
+
|
12
|
+
expect(count).to eq(1)
|
13
|
+
expect(result.class).to eq(Promise)
|
14
|
+
end
|
15
|
+
end
|
data/spec/models/model_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'volt/models'
|
3
2
|
|
4
3
|
class TestItem < Volt::Model
|
5
4
|
end
|
@@ -53,9 +52,9 @@ describe Volt::Model do
|
|
53
52
|
expect(!a._false1).to eq(true)
|
54
53
|
end
|
55
54
|
|
56
|
-
it "should return
|
55
|
+
it "should return an empty model for an underscore value that doesn't exist" do
|
57
56
|
a = Volt::Model.new
|
58
|
-
expect(a._something
|
57
|
+
expect(a._something!.attributes).to eq({})
|
59
58
|
end
|
60
59
|
|
61
60
|
it 'should trigger changed once when a new value is assigned.' do
|
@@ -141,7 +140,7 @@ describe Volt::Model do
|
|
141
140
|
it 'should trigger changed for any indicies after a deleted index' do
|
142
141
|
model = Volt::Model.new
|
143
142
|
|
144
|
-
model._items << { _name: 'One' }
|
143
|
+
model._items! << { _name: 'One' }
|
145
144
|
model._items << { _name: 'Two' }
|
146
145
|
model._items << { _name: 'Three' }
|
147
146
|
|
@@ -157,7 +156,7 @@ describe Volt::Model do
|
|
157
156
|
it 'should change the size and length when an item gets added' do
|
158
157
|
model = Volt::Model.new
|
159
158
|
|
160
|
-
model._items << { _name: 'One' }
|
159
|
+
model._items! << { _name: 'One' }
|
161
160
|
size = model._items.size
|
162
161
|
length = model._items.length
|
163
162
|
|
@@ -178,30 +177,73 @@ describe Volt::Model do
|
|
178
177
|
it 'should add doubly nested arrays' do
|
179
178
|
model = Volt::Model.new
|
180
179
|
|
181
|
-
model._items << { name: 'Cool', lists: [] }
|
182
|
-
model._items[0]._lists << { name: 'worked' }
|
180
|
+
model._items! << { name: 'Cool', lists: [] }
|
181
|
+
model._items[0]._lists! << { name: 'worked' }
|
183
182
|
expect(model._items[0]._lists[0]._name).to eq('worked')
|
184
183
|
end
|
185
184
|
|
186
185
|
it 'should make pushed subarrays into ArrayModels' do
|
187
186
|
model = Volt::Model.new
|
188
187
|
|
189
|
-
model._items << { _name: 'Test', _lists: [] }
|
188
|
+
model._items! << { _name: 'Test', _lists: [] }
|
190
189
|
expect(model._items[0]._lists.class).to eq(Volt::ArrayModel)
|
191
190
|
end
|
192
191
|
|
193
192
|
it 'should make assigned subarrays into ArrayModels' do
|
194
193
|
model = Volt::Model.new
|
195
194
|
|
196
|
-
model._item
|
195
|
+
model._item!._name = 'Test'
|
197
196
|
model._item._lists = []
|
198
197
|
expect(model._item._lists.class).to eq(Volt::ArrayModel)
|
199
198
|
end
|
200
199
|
|
200
|
+
it 'should call changed when an expanded reference changes' do
|
201
|
+
a = Volt::Model.new
|
202
|
+
|
203
|
+
count = 0
|
204
|
+
-> { a._blue ; count += 1 }.watch!
|
205
|
+
|
206
|
+
expect(count).to eq(1)
|
207
|
+
|
208
|
+
a._blue!
|
209
|
+
Volt::Computation.flush!
|
210
|
+
|
211
|
+
expect(count).to eq(2)
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'should call size changed when adding to an ArrayModel' do
|
215
|
+
a = Volt::Model.new
|
216
|
+
|
217
|
+
count = 0
|
218
|
+
-> { count = a._todos.size }.watch!
|
219
|
+
|
220
|
+
expect(count).to eq(0)
|
221
|
+
|
222
|
+
a._todos << {label: 'Be active'}
|
223
|
+
Volt::Computation.flush!
|
224
|
+
|
225
|
+
expect(count).to eq(1)
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'should track changes through an expansion' do
|
229
|
+
a = Volt::Model.new
|
230
|
+
|
231
|
+
last_count = 0
|
232
|
+
-> { last_count = a._todos.count(&:_checked) }.watch!
|
233
|
+
|
234
|
+
expect(last_count).to eq(0)
|
235
|
+
|
236
|
+
a._todos! << {checked: true}
|
237
|
+
Volt::Computation.flush!
|
238
|
+
|
239
|
+
expect(last_count).to eq(1)
|
240
|
+
end
|
241
|
+
|
201
242
|
it 'should call changed when a the reference to a submodel is assigned to another value' do
|
202
243
|
a = Volt::Model.new
|
203
244
|
|
204
245
|
count = 0
|
246
|
+
a._blue!
|
205
247
|
-> { a._blue && a._blue.respond_to?(:_green) && a._blue._green; count += 1 }.watch!
|
206
248
|
expect(count).to eq(1)
|
207
249
|
|
@@ -215,7 +257,7 @@ describe Volt::Model do
|
|
215
257
|
expect(count).to eq(3)
|
216
258
|
|
217
259
|
a._blue = { green: 50 }
|
218
|
-
expect(a._blue
|
260
|
+
expect(a._blue!._green).to eq(50)
|
219
261
|
Volt::Computation.flush!
|
220
262
|
expect(count).to eq(4)
|
221
263
|
end
|
@@ -239,14 +281,14 @@ describe Volt::Model do
|
|
239
281
|
it 'should let you append nested hashes' do
|
240
282
|
a = Volt::Model.new
|
241
283
|
|
242
|
-
a._items << { name: { text: 'Name' } }
|
284
|
+
a._items! << { name: { text: 'Name' } }
|
243
285
|
|
244
|
-
expect(a._items[0]._name
|
286
|
+
expect(a._items[0]._name!._text).to eq('Name')
|
245
287
|
end
|
246
288
|
|
247
289
|
it 'should not call added too many times' do
|
248
290
|
a = Volt::Model.new
|
249
|
-
a._lists << 1
|
291
|
+
a._lists! << 1
|
250
292
|
|
251
293
|
count = 0
|
252
294
|
a._lists.on('added') { count += 1 }
|
@@ -258,6 +300,9 @@ describe Volt::Model do
|
|
258
300
|
|
259
301
|
it 'should propigate to different branches' do
|
260
302
|
a = Volt::Model.new
|
303
|
+
|
304
|
+
# Expand first
|
305
|
+
a._new_item!
|
261
306
|
count = 0
|
262
307
|
-> do
|
263
308
|
count += 1
|
@@ -273,11 +318,11 @@ describe Volt::Model do
|
|
273
318
|
describe 'paths' do
|
274
319
|
it 'should store the path' do
|
275
320
|
a = Volt::Model.new
|
276
|
-
expect(a._test
|
321
|
+
expect(a._test!.path).to eq([:test])
|
277
322
|
a._test = { _name: 'Yes' }
|
278
323
|
expect(a._test.path).to eq([:test])
|
279
324
|
|
280
|
-
a._items << { _name: 'Yes' }
|
325
|
+
a._items! << { _name: 'Yes' }
|
281
326
|
expect(a._items.path).to eq([:items])
|
282
327
|
expect(a._items[0].path).to eq([:items, :[]])
|
283
328
|
end
|
@@ -294,7 +339,7 @@ describe Volt::Model do
|
|
294
339
|
it 'should handle nested paths' do
|
295
340
|
a = Volt::Model.new
|
296
341
|
|
297
|
-
a._items << { name: 'Cool', lists: [{ name: 'One' }, { name: 'Two' }] }
|
342
|
+
a._items! << { name: 'Cool', lists: [{ name: 'One' }, { name: 'Two' }] }
|
298
343
|
|
299
344
|
expect(a._items[0]._lists.path).to eq([:items, :[], :lists])
|
300
345
|
expect(a._items[0]._lists[1].path).to eq([:items, :[], :lists, :[]])
|
@@ -303,7 +348,7 @@ describe Volt::Model do
|
|
303
348
|
it 'should trigger added when added' do
|
304
349
|
a = Volt::Model.new
|
305
350
|
count = 0
|
306
|
-
b = a._items
|
351
|
+
b = a._items!
|
307
352
|
|
308
353
|
b.on('added') { count += 1 }
|
309
354
|
expect(count).to eq(0)
|
@@ -360,7 +405,7 @@ describe Volt::Model do
|
|
360
405
|
|
361
406
|
it 'should convert to a hash, and unwrap all of the way down' do
|
362
407
|
a = Volt::Model.new
|
363
|
-
a._items << { name: 'Test1', other: { time: 'Now' } }
|
408
|
+
a._items! << { name: 'Test1', other: { time: 'Now' } }
|
364
409
|
a._items << { name: 'Test2', other: { time: 'Later' } }
|
365
410
|
|
366
411
|
item1 = a._items[0].to_h
|
@@ -382,25 +427,25 @@ describe Volt::Model do
|
|
382
427
|
end
|
383
428
|
|
384
429
|
it 'should set the model path' do
|
385
|
-
@model._object
|
430
|
+
@model._object!._name = 'Test'
|
386
431
|
expect(@model._object.path).to eq([:object])
|
387
432
|
end
|
388
433
|
|
389
434
|
it 'should set the model path for a sub array' do
|
390
|
-
@model._items << { name: 'Bob' }
|
435
|
+
@model._items! << { name: 'Bob' }
|
391
436
|
expect(@model._items.path).to eq([:items])
|
392
437
|
expect(@model._items[0].path).to eq([:items, :[]])
|
393
438
|
end
|
394
439
|
|
395
440
|
it 'should set the model path for sub sub arrays' do
|
396
|
-
@model._lists << { name: 'List 1', items: [] }
|
397
|
-
expect(@model._lists[0]._items
|
441
|
+
@model._lists! << { name: 'List 1', items: [] }
|
442
|
+
expect(@model._lists[0]._items!.path).to eq([:lists, :[], :items])
|
398
443
|
end
|
399
444
|
|
400
445
|
it 'should update the path when added from a model instance to a collection' do
|
401
446
|
test_item = TestItem.new
|
402
447
|
|
403
|
-
@model._items << test_item
|
448
|
+
@model._items! << test_item
|
404
449
|
expect(@model._items[0].path).to eq([:items, :[]])
|
405
450
|
end
|
406
451
|
end
|
@@ -440,7 +485,7 @@ describe Volt::Model do
|
|
440
485
|
@model = Volt::Model.new
|
441
486
|
|
442
487
|
# Should return a buffer of the right type
|
443
|
-
expect(@model._items
|
488
|
+
expect(@model._items!.buffer.class).to eq(Item)
|
444
489
|
|
445
490
|
# Should insert as the right type
|
446
491
|
@model._items << { _name: 'Item 1' }
|
@@ -482,7 +527,7 @@ describe Volt::Model do
|
|
482
527
|
|
483
528
|
if RUBY_PLATFORM != 'opal'
|
484
529
|
it 'should update other queries on the server when a new model is created' do
|
485
|
-
query1 = store._todos
|
530
|
+
query1 = store._todos!
|
486
531
|
query2 = store._todos.limit(1)
|
487
532
|
|
488
533
|
count = 0
|
@@ -5,7 +5,7 @@ if RUBY_PLATFORM != 'opal'
|
|
5
5
|
|
6
6
|
describe Volt::Model do
|
7
7
|
it 'should stay loaded while a computaiton is watching some data' do
|
8
|
-
expect(store._items
|
8
|
+
expect(store._items!.loaded_state).to eq(:not_loaded)
|
9
9
|
|
10
10
|
comp = -> { store._items.size }.watch!
|
11
11
|
|
@@ -28,6 +28,25 @@ class ::TestDenyReadName < Volt::Model
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
class ::TestUpdateReadCheck < Volt::Model
|
32
|
+
attr_accessor :create_check, :update_check, :read_check
|
33
|
+
|
34
|
+
permissions(:create) do
|
35
|
+
self.create_check = true
|
36
|
+
allow
|
37
|
+
end
|
38
|
+
|
39
|
+
permissions(:update) do
|
40
|
+
self.update_check = true
|
41
|
+
allow
|
42
|
+
end
|
43
|
+
|
44
|
+
permissions(:read) do
|
45
|
+
self.read_check = true
|
46
|
+
allow
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
31
50
|
describe "model permissions" do
|
32
51
|
it 'should follow CRUD states when checking permissions' do
|
33
52
|
todo = TestUserTodoWithCrudStates.new.buffer
|
@@ -61,7 +80,7 @@ describe "model permissions" do
|
|
61
80
|
if RUBY_PLATFORM != 'opal'
|
62
81
|
describe "read permissions" do
|
63
82
|
it 'should deny read on a field' do
|
64
|
-
model = store._test_deny_read_names
|
83
|
+
model = store._test_deny_read_names!.buffer
|
65
84
|
model._name = 'Jimmy'
|
66
85
|
model._other = 'should be visible'
|
67
86
|
|
@@ -78,7 +97,7 @@ describe "model permissions" do
|
|
78
97
|
end
|
79
98
|
|
80
99
|
it 'should prevent delete if denied' do
|
81
|
-
model = store._test_deny_deletes
|
100
|
+
model = store._test_deny_deletes!.buffer
|
82
101
|
|
83
102
|
model.save!.then do
|
84
103
|
# Saved
|
@@ -92,5 +111,48 @@ describe "model permissions" do
|
|
92
111
|
expect(count).to eq(1)
|
93
112
|
end
|
94
113
|
end
|
114
|
+
|
115
|
+
it 'should not check the read permissions when updating (so that all fields are present for the permissions check)' do
|
116
|
+
model = store._test_update_read_checks!.append({name: 'Ryan'}).sync
|
117
|
+
|
118
|
+
expect(model.create_check).to eq(true)
|
119
|
+
expect(model.read_check).to eq(nil)
|
120
|
+
|
121
|
+
# Update
|
122
|
+
model._name = 'Jimmy'
|
123
|
+
|
124
|
+
expect(model.read_check).to eq(nil)
|
125
|
+
expect(model.update_check).to eq(true)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should not check read permissions on buffer save on server' do
|
129
|
+
model = store._test_update_read_checks!.buffer
|
130
|
+
|
131
|
+
model._name = 'Ryan'
|
132
|
+
|
133
|
+
# Create
|
134
|
+
model.save!
|
135
|
+
|
136
|
+
# Create happens on the save_to, not the buffer
|
137
|
+
expect(model.save_to.create_check).to eq(true)
|
138
|
+
expect(model.save_to.read_check).to eq(nil)
|
139
|
+
|
140
|
+
# Update
|
141
|
+
model._name = 'Jimmy'
|
142
|
+
model.save!
|
143
|
+
|
144
|
+
expect(model.save_to.read_check).to eq(nil)
|
145
|
+
expect(model.save_to.update_check).to eq(true)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should not check read on delete, so all fields are available to the permissions block' do
|
149
|
+
model = store._test_update_read_checks!.append({name: 'Ryan'}).sync
|
150
|
+
|
151
|
+
expect(model.read_check).to eq(nil)
|
152
|
+
|
153
|
+
model.destroy
|
154
|
+
|
155
|
+
expect(model.read_check).to eq(nil)
|
156
|
+
end
|
95
157
|
end
|
96
158
|
end
|