volt 0.8.27.beta6 → 0.8.27.beta7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -3
  3. data/VERSION +1 -1
  4. data/app/volt/models/user.rb +1 -1
  5. data/app/volt/tasks/query_tasks.rb +2 -2
  6. data/app/volt/tasks/store_tasks.rb +14 -4
  7. data/app/volt/tasks/user_tasks.rb +1 -1
  8. data/lib/volt/controllers/http_controller.rb +60 -0
  9. data/lib/volt/controllers/model_controller.rb +5 -1
  10. data/lib/volt/extra_core/string.rb +6 -0
  11. data/lib/volt/models/array_model.rb +6 -2
  12. data/lib/volt/models/associations.rb +1 -1
  13. data/lib/volt/models/buffer.rb +14 -3
  14. data/lib/volt/models/model.rb +28 -60
  15. data/lib/volt/models/permissions.rb +4 -4
  16. data/lib/volt/reactive/computation.rb +15 -15
  17. data/lib/volt/reactive/reactive_array.rb +1 -0
  18. data/lib/volt/router/routes.rb +67 -27
  19. data/lib/volt/server.rb +37 -6
  20. data/lib/volt/server/component_templates.rb +2 -2
  21. data/lib/volt/server/rack/http_request.rb +50 -0
  22. data/lib/volt/server/rack/http_resource.rb +41 -0
  23. data/lib/volt/server/rack/http_response_header.rb +33 -0
  24. data/lib/volt/server/rack/http_response_renderer.rb +41 -0
  25. data/lib/volt/spec/setup.rb +4 -2
  26. data/lib/volt/tasks/dispatcher.rb +7 -7
  27. data/lib/volt/tasks/task_handler.rb +1 -1
  28. data/lib/volt/volt/users.rb +12 -6
  29. data/spec/apps/kitchen_sink/app/main/config/routes.rb +18 -10
  30. data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +2 -2
  31. data/spec/apps/kitchen_sink/app/main/controllers/server/simple_http_controller.rb +15 -0
  32. data/spec/apps/kitchen_sink/app/main/controllers/upload_controller.rb +22 -0
  33. data/spec/apps/kitchen_sink/app/main/views/main/yield.html +2 -2
  34. data/spec/apps/kitchen_sink/app/main/views/upload/index.html +15 -0
  35. data/spec/controllers/http_controller_spec.rb +130 -0
  36. data/spec/extra_core/string_transformation_test_cases.rb +8 -0
  37. data/spec/extra_core/string_transformations_spec.rb +12 -0
  38. data/spec/integration/http_endpoints_spec.rb +29 -0
  39. data/spec/integration/user_spec.rb +42 -42
  40. data/spec/models/associations_spec.rb +4 -4
  41. data/spec/models/buffer_spec.rb +15 -0
  42. data/spec/models/model_spec.rb +70 -25
  43. data/spec/models/model_state_spec.rb +1 -1
  44. data/spec/models/permissions_spec.rb +64 -2
  45. data/spec/models/persistors/params_spec.rb +8 -8
  46. data/spec/models/persistors/store_spec.rb +1 -1
  47. data/spec/models/user_validation_spec.rb +1 -1
  48. data/spec/router/routes_spec.rb +111 -43
  49. data/spec/server/rack/http_request_spec.rb +50 -0
  50. data/spec/server/rack/http_resource_spec.rb +59 -0
  51. data/spec/server/rack/http_response_header_spec.rb +34 -0
  52. data/spec/server/rack/http_response_renderer_spec.rb +33 -0
  53. data/spec/tasks/dispatcher_spec.rb +2 -2
  54. data/templates/component/config/routes.rb +2 -2
  55. data/templates/project/Gemfile.tt +3 -5
  56. data/templates/project/app/main/config/routes.rb +4 -4
  57. data/volt.gemspec +2 -2
  58. 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
- # it 'should login and logout' do
38
- # visit '/'
39
- #
40
- # # Add the user
41
- # $page.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
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.fetch_first.sync
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.fetch_first.sync
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
@@ -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 a nil model for an underscore value that doesn't exist" do
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.attributes).to eq(nil)
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._name = 'Test'
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._green).to eq(50)
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._text).to eq('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.path).to eq([: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._name = 'Test'
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.path).to eq([:lists, :[], :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.buffer.class).to eq(Item)
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.loaded_state).to eq(:not_loaded)
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.buffer
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.buffer
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