lanes 0.5.6 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -2
  3. data/client/lanes/Config.coffee +6 -5
  4. data/client/lanes/access/LoginDialog.cjsx +4 -2
  5. data/client/lanes/access/Roles.coffee +3 -0
  6. data/client/lanes/access/screens/user-management/Editor.cjsx +1 -1
  7. data/client/lanes/components/grid/Body.cjsx +4 -3
  8. data/client/lanes/components/grid/Grid.cjsx +4 -3
  9. data/client/lanes/components/grid/Header.cjsx +1 -1
  10. data/client/lanes/components/grid/PopOverMixin.cjsx +6 -6
  11. data/client/lanes/components/grid/Selections.cjsx +16 -6
  12. data/client/lanes/components/grid/Toolbar.cjsx +1 -1
  13. data/client/lanes/components/grid/styles.scss +21 -5
  14. data/client/lanes/components/modal/Modal.cjsx +18 -9
  15. data/client/lanes/components/record-finder/Clause.cjsx +1 -2
  16. data/client/lanes/components/record-finder/Dialog.cjsx +11 -3
  17. data/client/lanes/components/record-finder/RecordFinder.cjsx +14 -7
  18. data/client/lanes/components/record-finder/styles.scss +1 -0
  19. data/client/lanes/components/select-field/SelectField.cjsx +36 -10
  20. data/client/lanes/components/select-field/styles.scss +7 -0
  21. data/client/lanes/components/shared/Checkbox.cjsx +34 -0
  22. data/client/lanes/components/shared/DateTime.cjsx +3 -2
  23. data/client/lanes/components/shared/ErrorDisplay.cjsx +1 -1
  24. data/client/lanes/components/shared/FieldMixin.cjsx +26 -15
  25. data/client/lanes/components/shared/FieldSet.cjsx +1 -1
  26. data/client/lanes/components/shared/FieldWrapper.cjsx +2 -2
  27. data/client/lanes/components/shared/FormGroup.cjsx +2 -2
  28. data/client/lanes/components/shared/Icon.cjsx +31 -4
  29. data/client/lanes/components/shared/IconButton.cjsx +8 -0
  30. data/client/lanes/components/shared/ImageAsset.cjsx +8 -5
  31. data/client/lanes/components/shared/IndeterminateCheckbox.cjsx +19 -0
  32. data/client/lanes/components/shared/InputFieldMixin.cjsx +6 -0
  33. data/client/lanes/components/shared/JobProgress.cjsx +4 -3
  34. data/client/lanes/components/shared/NetworkActivityOverlay.cjsx +1 -1
  35. data/client/lanes/components/shared/ScreenWrapper.cjsx +1 -1
  36. data/client/lanes/components/shared/ToggleField.cjsx +2 -1
  37. data/client/lanes/components/shared/Tooltip.cjsx +10 -2
  38. data/client/lanes/components/shared/fields.scss +7 -2
  39. data/client/lanes/components/toolbar/RemoteChangeSets.cjsx +10 -7
  40. data/client/lanes/components/toolbar/SaveButton.cjsx +5 -4
  41. data/client/lanes/components/toolbar/Toolbar.cjsx +18 -19
  42. data/client/lanes/components/toolbar/changes-notification.scss +3 -1
  43. data/client/lanes/components/toolbar/styles.scss +6 -3
  44. data/client/lanes/lib/HotReload.coffee +1 -1
  45. data/client/lanes/lib/all.js +1 -1
  46. data/client/lanes/lib/dom.coffee +14 -1
  47. data/client/lanes/lib/format.coffee +3 -0
  48. data/client/lanes/lib/loader.coffee +0 -2
  49. data/client/lanes/lib/{dom-polyfills.coffee → polyfills.coffee} +3 -0
  50. data/client/lanes/lib/utilFunctions.coffee +5 -7
  51. data/client/lanes/models/Asset.coffee +33 -20
  52. data/client/lanes/models/AssociationMap.coffee +5 -6
  53. data/client/lanes/models/Base.coffee +5 -2
  54. data/client/lanes/models/Collection.coffee +23 -2
  55. data/client/lanes/models/PubSub.coffee +51 -13
  56. data/client/lanes/models/Query.coffee +53 -42
  57. data/client/lanes/models/State.coffee +5 -4
  58. data/client/lanes/models/Sync.coffee +5 -3
  59. data/client/lanes/models/index.js +1 -1
  60. data/client/lanes/models/mixins/TrackCollectionRemovals.coffee +17 -0
  61. data/client/lanes/models/query/ArrayResult.coffee +16 -17
  62. data/client/lanes/models/query/CollectionResult.coffee +4 -4
  63. data/client/lanes/react/Component.coffee +14 -13
  64. data/client/lanes/react/Root.cjsx +1 -1
  65. data/client/lanes/react/Screen.coffee +1 -0
  66. data/client/lanes/react/Viewport.coffee +52 -16
  67. data/client/lanes/react/mixins/Access.coffee +5 -0
  68. data/client/lanes/react/mixins/Data.coffee +52 -144
  69. data/client/lanes/react/mixins/MonitorSize.coffee +1 -1
  70. data/client/lanes/react/mixins/ReadEditingState.coffee +3 -0
  71. data/client/lanes/screens/Commands.coffee +1 -1
  72. data/client/lanes/screens/CommonComponents.cjsx +2 -2
  73. data/client/lanes/screens/Definitions.coffee +3 -1
  74. data/client/lanes/screens/SystemSettings.cjsx +13 -18
  75. data/client/lanes/screens/UserPreferences.cjsx +1 -1
  76. data/client/lanes/styles/fonts.scss +2 -3
  77. data/client/lanes/styles/global/styles.scss +2 -1
  78. data/client/lanes/testing/TestObjects.coffee +6 -2
  79. data/client/lanes/vendor/action_cable.js +590 -0
  80. data/client/lanes/vendor/development/calendar.js +56 -56
  81. data/client/lanes/vendor/development/commons.js +7819 -6690
  82. data/client/lanes/vendor/development/data.js +1877 -1455
  83. data/client/lanes/vendor/development/helpers.js +39 -82
  84. data/client/lanes/vendor/development/toggle.js +20 -20
  85. data/client/lanes/vendor/development/ui.js +14629 -14261
  86. data/client/lanes/vendor/development/widgets.js +3146 -2173
  87. data/client/lanes/vendor/index.js +1 -2
  88. data/client/lanes/vendor/production/calendar.js +56 -56
  89. data/client/lanes/vendor/production/commons.js +6352 -6185
  90. data/client/lanes/vendor/production/data.js +1871 -1456
  91. data/client/lanes/vendor/production/toggle.js +20 -20
  92. data/client/lanes/vendor/production/ui.js +14694 -14286
  93. data/client/lanes/vendor/production/widgets.js +3139 -2166
  94. data/client/lanes/vendor/standalone/index.js +5666 -4586
  95. data/client/lanes/vendor/styles/widgets.scss +5 -5
  96. data/client/lanes/workspace/Layout.cjsx +1 -10
  97. data/client/lanes/workspace/Navbar.cjsx +8 -13
  98. data/client/lanes/workspace/ScreenView.cjsx +3 -4
  99. data/client/lanes/workspace/ScreensMenu.cjsx +8 -19
  100. data/client/lanes/workspace/Tabs.cjsx +6 -14
  101. data/db/migrate/02_create_assets.rb +1 -3
  102. data/lanes.gemspec +16 -11
  103. data/lib/lanes/access/test_fixture_extensions.rb +6 -10
  104. data/lib/lanes/access/track_modifications.rb +24 -0
  105. data/lib/lanes/api/cable.rb +49 -0
  106. data/lib/lanes/api/controller_base.rb +52 -9
  107. data/lib/lanes/api/default_routes.rb +9 -0
  108. data/lib/lanes/api/generic_controller.rb +2 -9
  109. data/lib/lanes/api/handlers/asset.rb +5 -6
  110. data/lib/lanes/api/helper_methods.rb +3 -2
  111. data/lib/lanes/api/javascript_processor.rb +6 -5
  112. data/lib/lanes/api/pub_sub.rb +14 -32
  113. data/lib/lanes/api/request_wrapper.rb +1 -1
  114. data/lib/lanes/api/root.rb +4 -7
  115. data/lib/lanes/api/routing.rb +3 -3
  116. data/lib/lanes/api/sprockets_extension.rb +1 -1
  117. data/lib/lanes/api.rb +4 -0
  118. data/lib/lanes/asset.rb +25 -25
  119. data/lib/lanes/concerns/asset_uploader.rb +25 -47
  120. data/lib/lanes/concerns/export_scope.rb +5 -7
  121. data/lib/lanes/concerns/queries.rb +7 -3
  122. data/lib/lanes/concerns/set_attribute_data.rb +12 -6
  123. data/lib/lanes/configuration.rb +4 -7
  124. data/lib/lanes/db.rb +3 -1
  125. data/lib/lanes/guard_tasks.rb +2 -1
  126. data/lib/lanes/hot_reload_plugin.rb +2 -1
  127. data/lib/lanes/job.rb +0 -1
  128. data/lib/lanes/logger.rb +3 -3
  129. data/lib/lanes/model.rb +0 -3
  130. data/lib/lanes/spec_helper.rb +1 -1
  131. data/lib/lanes/system_settings.rb +8 -14
  132. data/lib/lanes/version.rb +1 -1
  133. data/npm-build/data.js +1 -0
  134. data/npm-build/package.json +21 -19
  135. data/npm-build/ui.js +3 -0
  136. data/npm-build/update-dayz +2 -2
  137. data/npm-build/update-model-bindings.js +5 -0
  138. data/spec/command-reference-files/initial/Gemfile +1 -1
  139. data/spec/command-reference-files/initial/config/database.yml +1 -0
  140. data/spec/command-reference-files/initial/config/lanes.rb +3 -3
  141. data/spec/command-reference-files/screen/spec/appy-app/screens/ready-set-go/ReadySetGoSpec.coffee +1 -1
  142. data/spec/lanes/components/grid/GridSpec.coffee +2 -2
  143. data/spec/lanes/components/grid/PopoverEditorSpec.coffee +11 -12
  144. data/spec/lanes/components/select-field/SelectFieldSpec.coffee +6 -4
  145. data/spec/lanes/components/shared/NetworkActivityOverlaySpec.coffee +1 -1
  146. data/spec/lanes/models/PubSubSpec.coffee +6 -8
  147. data/spec/lanes/models/QuerySpec.coffee +19 -0
  148. data/spec/lanes/react/mixins/DataSpec.coffee +18 -16
  149. data/spec/server/api/coffeescript_processor_spec.rb +1 -1
  150. data/spec/server/api/controller_base_spec.rb +77 -0
  151. data/spec/server/api/pub_sub_spec.rb +9 -0
  152. data/spec/server/asset_spec.rb +23 -18
  153. data/spec/server/concerns/export_scope_spec.rb +2 -1
  154. data/spec/server/concerns/exported_limits_spec.rb +14 -9
  155. data/spec/server/concerns/set_attribute_data_spec.rb +17 -0
  156. data/spec/server/spec_helper.rb +29 -11
  157. data/templates/config/database.yml +1 -0
  158. data/templates/spec/client/Screen.coffee +1 -1
  159. data/views/specs.erb +4 -1
  160. metadata +138 -89
  161. data/client/lanes/vendor/message-bus-ajax.js +0 -44
  162. data/client/lanes/vendor/message-bus.js +0 -414
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
3
3
  # For development while Lanes is evolving track master branch
4
4
  gem "lanes", github: 'argosity/lanes', branch: 'master'
5
5
 
6
- # gem "lanes", '0.4.0'
6
+ # gem "lanes", '0.5.6'
7
7
 
8
8
  gem "rake"
9
9
  gem 'puma'
@@ -2,6 +2,7 @@ development:
2
2
  adapter: postgresql
3
3
  database: appy-app_dev
4
4
  host: /tmp
5
+ pool: <%= ENV["DB_POOL"] || 12 %>
5
6
 
6
7
  test:
7
8
  adapter: postgresql
@@ -1,7 +1,7 @@
1
- # This file will be loaded if the current extension is the
2
- # one controlling Lanes.
1
+ # This file will be loaded as part of Lanes startup.
3
2
  #
4
- # It will not be evaluated if another extension is loading this one
3
+ # Extensions are called in load order, so be aware latter extensions may
4
+ # override config options specified
5
5
  Lanes.configure do | config |
6
6
  # You can specify a different initial vew by setting it here
7
7
  # It must be set if the "Workspace" extension is disabled in
@@ -2,4 +2,4 @@ describe "AppyApp.Screens.ReadySetGo", ->
2
2
 
3
3
  it "can be rendered", ->
4
4
  screen = LT.renderComponent(AppyApp.Screens.ReadySetGo)
5
- expect(_.dom(screen).text).toMatch("Hello")
5
+ expect(_.dom(screen).text).toBeTruthy()
@@ -15,10 +15,10 @@ renderGrid = (q, done) ->
15
15
  grid = LT.renderComponent(LC.Grid, props: query: q)
16
16
  expect(loaded).toHaveBeenCalled()
17
17
  _.defer ->
18
- expect(_.dom(grid).qsa('.r').length)
19
- .toEqual( q.results.length )
18
+ expect(_.dom(grid).qs('.r').el).not.toBeNull()
20
19
  done()
21
20
 
21
+
22
22
  describe "Lanes.Components.Grid", ->
23
23
 
24
24
  beforeEach (done) ->
@@ -1,11 +1,10 @@
1
1
  #= require lanes/components/grid
2
2
 
3
- COLLECTION_DATA = [
4
- {id:1, code:'TEST1', name: 'Nathan Stitt', notes: 'swell guy'}
5
- {id:2, code:'TEST2', name: 'Nathan Stitt', notes: 'Dupe of id #1'}
6
- ]
7
3
 
8
- ROW_DATA = _.map COLLECTION_DATA, (r) -> _.values(r)
4
+ DATA = {total:2, success:true, message:"Retrieve succeeded", data:[
5
+ [1, "TEST1", "Nathan Stitt", "swell guy"]
6
+ [2, "TEST2", "Nathan Stitt", "Dupe of id #1"]
7
+ ]}
9
8
 
10
9
  Model = Lanes.Test.defineModel(
11
10
  props: {id: 'integer', code: 'string', name: 'string', notes: 'string'}
@@ -17,15 +16,15 @@ ADD_ROW_SELECTOR = 'button.add-row'
17
16
  describe "Lanes.Components.Grid.PopoverEditor", ->
18
17
 
19
18
  beforeEach (done) ->
19
+ LT.syncRespondWith(DATA)
20
20
  @query = new Lanes.Models.Query(
21
- fields: [ 'id', 'code', 'name', 'notes' ], src: Model
21
+ src: Model, fields: [ 'id', 'code', 'name', 'notes' ]
22
22
  )
23
- Lanes.Test.syncSucceedWith(ROW_DATA)
24
- @query.ensureLoaded().then(done)
25
- @grid = LT.renderComponent(LC.Grid, props: {
26
- editor: Lanes.Components.Grid.PopoverEditor
27
- query: @query, allowCreate: true
28
- })
23
+ @query.ensureLoaded().then =>
24
+ @grid = LT.renderComponent(LC.Grid, props: {
25
+ allowCreate: true, editor: Lanes.Components.Grid.PopoverEditor, query: @query
26
+ })
27
+ done()
29
28
 
30
29
  it "edits", (done) ->
31
30
  _.dom(@grid).qs(LAST_ROW_SELECTOR).click(clientX: 5)
@@ -10,6 +10,8 @@ BRAND_DATA = {total:3, success:true, message:"Retrieve succeeded", data:[
10
10
  {id: 3, code: "DODGE", name: "Chrysler/Dodge"}
11
11
  ]}
12
12
 
13
+ VALUE_CLASS = '.form-control-static'
14
+
13
15
  Car = Lanes.Test.defineModel(
14
16
  props: {id: 'integer', code: 'string', brand_id: 'integer'}
15
17
  session:
@@ -29,10 +31,10 @@ describe "Lanes.Components.SelectField", ->
29
31
  it "renders read only", (done) ->
30
32
  sf = LT.renderComponent(LC.SelectField,
31
33
  props:{model: @car, name: 'brand', labelField: 'name'})
32
- expect(_.dom(sf).qs('.value').text).toBe('')
34
+ expect(_.dom(sf).qs(VALUE_CLASS).text).toBe('')
33
35
  @car.set(brand: @brands.at(0))
34
36
  _.defer ->
35
- expect(_.dom(sf).qs('.value').text).toBe('General Motors')
37
+ expect(_.dom(sf).qs(VALUE_CLASS).text).toBe('General Motors')
36
38
  done()
37
39
 
38
40
  it "renders as edit", ->
@@ -83,7 +85,7 @@ describe "Lanes.Components.SelectField", ->
83
85
  model: @car, name: 'brand', labelField: 'name',
84
86
  choices: @brands.models
85
87
  })
86
- expect(_.dom(sf).qs('.value').text).toEqual('Chrysler/Dodge')
88
+ expect(_.dom(sf).qs(VALUE_CLASS).text).toEqual('Chrysler/Dodge')
87
89
 
88
90
  it 'renders label for multiple values', ->
89
91
  @car.carTypes = [ @brands.at(0), @brands.at(2) ]
@@ -91,7 +93,7 @@ describe "Lanes.Components.SelectField", ->
91
93
  queryModel: Car, multiSelect: true, model: @car, name: 'carTypes'
92
94
  labelField: 'name', choices: @brands.models
93
95
  })
94
- expect(_.dom(sf).qs('.value').text).toEqual('General Motors and Chrysler/Dodge')
96
+ expect(_.dom(sf).qs(VALUE_CLASS).text).toEqual('General Motors and Chrysler/Dodge')
95
97
 
96
98
 
97
99
  it "renders all choices", ->
@@ -26,7 +26,7 @@ describe "Lanes.Components.NetworkActivityOverlay", ->
26
26
  model = new Model
27
27
  na = LT.renderComponent(LC.NetworkActivityOverlay, props:{
28
28
  errorTimeout: 2, model:model})
29
- na.setDataState(hasError: true)
29
+ na.setModelState(hasError: true)
30
30
  expect(_.dom(na).qs('.message').text).toBe('Error')
31
31
  _.delay( ->
32
32
  expect(_.dom(na).el).toBe(null)
@@ -8,13 +8,15 @@ describe "Lanes.Model.PubSub", ->
8
8
  @getModelConfig = ->
9
9
  Lanes.Models.PubSub.types.get('/s').records[1]
10
10
 
11
- it "checks in/out a model when it binds to a view", ->
11
+ it "checks in/out a model when it binds to a view", (done) ->
12
12
  spyOn(Lanes.Models.PubSub, 'add').and.callThrough()
13
13
  spyOn(Lanes.Models.PubSub, 'remove')
14
14
  component = Lanes.Test.makeComponent({}, model: @model)
15
- expect(Lanes.Models.PubSub.add).toHaveBeenCalledWith(@model)
16
- component.data.destroy()
17
- expect(Lanes.Models.PubSub.remove).toHaveBeenCalledWith(@model)
15
+ _.defer =>
16
+ expect(Lanes.Models.PubSub.add).toHaveBeenCalledWith(@model)
17
+ component.modelBindings.destroy()
18
+ expect(Lanes.Models.PubSub.remove).toHaveBeenCalledWith(@model)
19
+ done()
18
20
 
19
21
  it "can retrieve a model after checkin", ->
20
22
  record = new @Model(id: 11, foo: 'bar')
@@ -34,12 +36,10 @@ describe "Lanes.Model.PubSub", ->
34
36
  Lanes.Models.PubSub.remove(@model)
35
37
  ).not.toThrowError()
36
38
 
37
-
38
39
  it 'removes models', ->
39
40
  Lanes.Models.PubSub.add(@model)
40
41
  configs = Lanes.Models.PubSub.types.get('/s').records[1].models
41
42
  expect(configs.length).toEqual(1)
42
-
43
43
  Lanes.Models.PubSub.remove(@model)
44
44
  expect(configs[0].count).toEqual(1)
45
45
  Lanes.Models.PubSub.remove(@model)
@@ -66,8 +66,6 @@ describe "Lanes.Model.PubSub", ->
66
66
  expect(Lanes.Models.PubSub.mb.subscribe.calls.count()).toEqual(1)
67
67
  expect(Lanes.Models.PubSub.mb.unsubscribe.calls.count()).toEqual(0)
68
68
  Lanes.Models.PubSub.remove(newModel)
69
-
70
69
  Lanes.Models.PubSub.remove(newModel)
71
-
72
70
  expect(@getModelConfig()).toBeUndefined()
73
71
  expect(Lanes.Models.PubSub.mb.unsubscribe.calls.count()).toEqual(1)
@@ -0,0 +1,19 @@
1
+ describe "Lanes.Models.Query", ->
2
+
3
+ beforeEach ->
4
+ @query =
5
+ new Lanes.Models.Query({
6
+ syncOptions: @syncOptions
7
+ src: Lanes.Models.User, fields: [
8
+ {id:'id', visible: false}
9
+ {id:'email', fixedWidth: 130 },
10
+ {id:'login', },
11
+ {id:'name', flex: 1}
12
+ ]
13
+ })
14
+
15
+
16
+ it "can be cloned unsaved attributes", ->
17
+ newQuery = @query.clone()
18
+ expect(newQuery).toBeDefined()
19
+ expect(newQuery.fields.pluck('id')).toEqual(@query.fields.pluck('id'))
@@ -1,21 +1,21 @@
1
1
  describe "Lanes.React.DataMixin", ->
2
2
 
3
- it "fires setState for a model", ->
3
+ it "fires forceUpdate for a model", ->
4
4
  model = Lanes.Test.makeModel
5
5
  props:
6
6
  id: 'integer'
7
7
  foo: 'string'
8
8
  comp = Lanes.Test.makeComponent({}, model: model)
9
- spyOn(comp, 'setState')
9
+ spyOn(comp, 'forceUpdate')
10
10
  model.foo = "bar"
11
- expect(comp.setState).toHaveBeenCalledWith( model: model )
11
+ expect(comp.forceUpdate).toHaveBeenCalled()
12
12
 
13
- it "fires setState for a collection", ->
13
+ it "fires forceUpdate for a collection", ->
14
14
  collection = Lanes.Test.makeCollection()
15
15
  comp = Lanes.Test.makeComponent({}, collection: collection)
16
- spyOn(comp, 'setState')
16
+ spyOn(comp, 'forceUpdate')
17
17
  collection.add([{}])
18
- expect(comp.setState).toHaveBeenCalledWith( collection: collection )
18
+ expect(comp.forceUpdate).toHaveBeenCalled()
19
19
 
20
20
  it "obeys global pubsub settings", ->
21
21
  spyOn(Lanes.Models.PubSub, 'add').and.callThrough()
@@ -39,17 +39,18 @@ describe "Lanes.React.DataMixin", ->
39
39
  props:
40
40
  foo: 'string'
41
41
  bar: 'string'
42
+
42
43
  comp = Lanes.Test.makeComponent({
43
- bindDataEvents:
44
+ bindEvents:
44
45
  model: 'change:bar'
45
46
  }, {
46
47
  model: model
47
48
  })
48
- spyOn(comp, 'setState')
49
+ spyOn(comp, 'forceUpdate')
49
50
  model.foo = "bar"
50
- expect(comp.setState).not.toHaveBeenCalled()
51
+ expect(comp.forceUpdate).not.toHaveBeenCalled()
51
52
  model.bar = "foo"
52
- expect(comp.setState).toHaveBeenCalledWith( model: model )
53
+ expect(comp.forceUpdate).toHaveBeenCalled()
53
54
 
54
55
  it "can rebind events", ->
55
56
  Model = Lanes.Test.defineModel
@@ -60,13 +61,14 @@ describe "Lanes.React.DataMixin", ->
60
61
  comp = Lanes.Test.makeComponent({}, {
61
62
  model: m1
62
63
  })
63
- spyOn(comp, 'setState')
64
+ spyOn(comp, 'forceUpdate')
64
65
  m1.foo = "bar"
65
- expect(comp.setState).toHaveBeenCalled()
66
+ expect(comp.forceUpdate).toHaveBeenCalled()
67
+
68
+ comp.modelBindings.reset(model: m2)
69
+ comp.forceUpdate.calls.reset()
66
70
 
67
- comp.data.rebind(model: m2)
68
- comp.setState.calls.reset()
69
71
  m1.foo = "a different bar"
70
- expect(comp.setState).not.toHaveBeenCalled()
72
+ expect(comp.forceUpdate).not.toHaveBeenCalled()
71
73
  m2.foo = "bar"
72
- expect(comp.setState).toHaveBeenCalled()
74
+ expect(comp.forceUpdate).toHaveBeenCalled()
@@ -101,7 +101,7 @@ Foo = (function() {
101
101
 
102
102
  Bar.extend(Foo);
103
103
 
104
- })(window.Lanes,(window.Lanes ? window.Lanes['Foo'] : null),window.Lanes.Vendor.ld,window.Lanes.Components,window.Lanes.Vendor.React,window.Lanes.Vendor.ReactBootstrap,{namespace:window.Lanes['Foo'],extension:{name:'Foo',identifier:'foo'},path:[\"foo\",\"bar\",\"baz\"]},window);
104
+ })((window.Lanes = (window.Lanes || {})),(window.Lanes ? window.Lanes['Foo'] : null),(window.Lanes.Vendor = (window.Lanes.Vendor || {})).ld,window.Lanes.Components,window.Lanes.Vendor.React,window.Lanes.Vendor.ReactBootstrap,{namespace:window.Lanes['Foo'],extension:{name:'Foo',identifier:'foo'},path:[\"foo\",\"bar\",\"baz\"]},window);
105
105
  EOS
106
106
 
107
107
  Scope = Struct.new(:logical_path)
@@ -0,0 +1,77 @@
1
+ require_relative "../spec_helper"
2
+ require 'lanes/access/user'
3
+
4
+ class ControllerBaseSpec < Lanes::TestCase
5
+
6
+ include TestingModels
7
+
8
+ def test_record_retrieval
9
+ 1.upto(10){|i| TestModel.create!(id: i, name:'test') }
10
+ controller = Lanes::API::ControllerBase.new(TestModel,
11
+ Lanes::API::AuthenticationProvider.new({}),
12
+ {id: 1})
13
+ assert_equal(controller.send(:perform_retrieval), {
14
+ :success=>true, :message=>"Retrieve succeeded",
15
+ :data=>{"id"=>1, "bt_id"=>nil, "name"=>"test", "number"=>nil}
16
+ })
17
+ end
18
+
19
+ def test_single_update
20
+ TestModel.create!(id: 1, name:'Joe')
21
+ controller = Lanes::API::ControllerBase.new(TestModel,
22
+ Lanes::API::AuthenticationProvider.new({}),
23
+ {id: 1}, {name:'Bob'})
24
+ assert_equal(controller.send(:perform_single_update), {
25
+ :success=>true, :message=>"Update succeeded",
26
+ :data=>{"id"=>1, "bt_id"=>nil, "name"=>"Bob", "number"=>nil}
27
+ })
28
+ assert_equal TestModel.where(id: 1).first.name, 'Bob'
29
+ end
30
+
31
+ def test_multiple_updates
32
+ TestModel.create!(id: 1, name:'Joe')
33
+ TestModel.create!(id: 2, name:'Bob')
34
+ def TestModel.access_limits_for_query(query, user, params)
35
+ query.where(name:'Joe')
36
+ end
37
+ controller = Lanes::API::ControllerBase.new(TestModel,
38
+ Lanes::API::AuthenticationProvider.new({}),
39
+ {},
40
+ [{'id'=>1}, {'id'=>2}])
41
+
42
+ assert_equal( controller.send(:perform_multiple_updates), {
43
+ :success=>true,
44
+ :message=>"Update succeeded",
45
+ :data=>[{"id"=>1, "bt_id"=>nil, "name"=>"Joe", "number"=>nil}]
46
+ })
47
+ end
48
+
49
+ def test_single_destroy
50
+ TestModel.create!(id: 1, name:'Joe')
51
+ controller = Lanes::API::ControllerBase.new(TestModel,
52
+ Lanes::API::AuthenticationProvider.new({}),
53
+ {id: 1}, {})
54
+ assert_equal( controller.send(:perform_single_destroy), {
55
+ :success=>true, :message=>"Destroy succeeded", :data=>[]
56
+ })
57
+ assert_empty TestModel.where(id: 1).to_a
58
+ end
59
+
60
+
61
+ def test_multiple_destroy
62
+ TestModel.create!(id: 1, name:'Joe')
63
+ TestModel.create!(id: 2, name:'Bob')
64
+
65
+ controller = Lanes::API::ControllerBase.new(TestModel,
66
+ Lanes::API::AuthenticationProvider.new({}),
67
+ {},
68
+ [{'id'=>1}, {'id'=>2}])
69
+ assert_equal( controller.send(:perform_multiple_destroy), {
70
+ :success=>true,
71
+ :message=>"Destroy succeeded",
72
+ :data=>[]
73
+ })
74
+ assert_empty TestModel.all.to_a
75
+ end
76
+
77
+ end
@@ -0,0 +1,9 @@
1
+ require "lanes/spec_helper"
2
+
3
+ class PubSubTest < Lanes::TestCase
4
+
5
+ def test_pub_sub
6
+
7
+ end
8
+
9
+ end
@@ -1,6 +1,6 @@
1
1
  require_relative "spec_helper"
2
- require "lanes/cli"
3
- require "find"
2
+ # require "lanes/cli"
3
+ # require "find"
4
4
 
5
5
  class Lanes::AssetTest < Lanes::TestCase
6
6
 
@@ -8,27 +8,32 @@ class Lanes::AssetTest < Lanes::TestCase
8
8
 
9
9
  def setup
10
10
  TestModel.has_one :asset, as: :owner, :class_name=>'Lanes::Asset'
11
- @model = TestModel.new
12
11
  end
13
12
 
14
13
  def test_saveing_image
15
- @model.build_asset(file: fixtures_path.join('logo.png').open)
16
- assert @model.save
17
- assert_equal @model.asset.as_json['metadata'], {
18
- 'content_type' => 'image/png',
19
- 'width' => 500,
20
- 'height' => 223,
21
- 'size' => 49172
14
+ tm = TestModel.new
15
+ @model = TestModel.new
16
+ asset = @model.build_asset# (file: fixtures_path.join('logo.png').open)
17
+ tf=Tempfile.new
18
+ tf.write fixtures_path.join('logo.png').read
19
+ tf.rewind
20
+ asset.file = {
21
+ type: "image/png", name: "file",
22
+ filename: "Screen Shot 2016-10-28 at 5.15.37 PM.png",
23
+ head: "Content-Disposition: form-data; name=\"file\"; filename=\"Screen Shot 2016-10-28 at 5.15.37 PM.png\"\r\nContent-Type: image/png\r\n",
24
+ tempfile: tf
22
25
  }
23
- end
24
-
25
- def test_saving_blob
26
- @model.build_asset(file: fixtures_path.join('system_settings.yml').open)
27
26
  assert @model.save
28
- assert_equal @model.asset.as_json['metadata'], {
29
- 'content_type' => 'text/x-yaml',
30
- 'size' => 1
31
- }
27
+
28
+ assert_equal(@model.asset.file_data.keys, ["original", "medium", "thumbnail"])
29
+ assert_equal(
30
+ @model.asset.file_data['original']['metadata'].without('filename'), {
31
+ "size"=>42228,
32
+ "mime_type"=>"image/png",
33
+ "width"=>500,
34
+ "height"=>223
35
+ }
36
+ )
32
37
  end
33
38
 
34
39
  end
@@ -5,9 +5,10 @@ class ExportScopeTest < Lanes::TestCase
5
5
 
6
6
  def test_scope_method_creation
7
7
  refute TestModel.respond_to?(:big_query)
8
- TestModel.send( :export_scope, :big_query, ->{} )
8
+ TestModel.send( :scope, :big_query, ->{}, {export: true} )
9
9
  assert TestModel.respond_to?(:big_query)
10
10
  assert TestModel.has_exported_scope?(:big_query,DummyUser.new)
11
11
  end
12
12
 
13
+
13
14
  end
@@ -1,14 +1,21 @@
1
1
  require_relative "../spec_helper"
2
2
 
3
3
  class ExportedLimitsTest < Lanes::TestCase
4
+ module FakeScope
5
+ extend ActiveSupport::Concern
6
+ class_methods do
7
+ def scope(*args) # act like ActiveRecord model
8
+ end
9
+ end
10
+ end
4
11
 
5
- class LimitsTestingModel
6
-
12
+ class Base
13
+ include FakeScope
7
14
  include Lanes::Concerns::ExportScope
8
15
  include Lanes::Concerns::ExportMethods
16
+ end
9
17
 
10
- def self.scope(name, query)# act like ActiveRecord model
11
- end
18
+ class LimitsTestingModel < Base
12
19
 
13
20
  def secret_method( name, query )
14
21
  end
@@ -20,9 +27,9 @@ class ExportedLimitsTest < Lanes::TestCase
20
27
  user == 'anon'
21
28
  }
22
29
 
23
- export_scope :admin_data, lambda{ | param |
30
+ scope :admin_data, lambda { | param |
24
31
  param
25
- }, limit: :only_admins
32
+ }, export: {limit: :only_admins}
26
33
 
27
34
  export_methods :secret_method, limit: :only_admins
28
35
 
@@ -34,11 +41,9 @@ class ExportedLimitsTest < Lanes::TestCase
34
41
  end
35
42
 
36
43
  def test_limits
37
- assert LimitsTestingModel.has_exported_method?( 'test_method', 'anon' ), "anyone can retrieve no_limit data"
38
-
44
+ assert LimitsTestingModel.has_exported_method?( 'test_method', 'anon' ), "anyone can retrieve no_limit data"
39
45
  assert LimitsTestingModel.has_exported_scope?( 'admin_data', 'admin' ), "Admins can retrieve admin data"
40
46
  refute LimitsTestingModel.has_exported_scope?( 'admin_data', 'non-admin' ), "Non-Admin cannot retrieve admin data"
41
-
42
47
  assert LimitsTestingModel.has_exported_method?( 'secret_method', 'admin' ), "Public can retrieve public data"
43
48
  refute LimitsTestingModel.has_exported_method?( 'secret_method', 'unk' ), "User must be admin to retrieve public data"
44
49
  end
@@ -55,4 +55,21 @@ class SetAttributeDataTest < Lanes::TestCase
55
55
  assert_equal 42, tm.instance_variable_get(:@setting)
56
56
  end
57
57
 
58
+ def test_deleting_has_many
59
+ tm = TestModel.create!
60
+ 1.upto(3) { |x| tm.hm.create({description: "description-#{x}"}) }
61
+
62
+ assert_equal tm.hm(true).count, 3
63
+ tm.set_attribute_data({
64
+ hm: [
65
+ { 'id' => 1, 'description' => 'updated' },
66
+ { 'id' => 2, '_delete' => true }
67
+ ]
68
+ }, @user)
69
+ assert_saves tm
70
+ assert_equal tm.hm(true).count, 2
71
+ refute tm.hm.find_by(id: 2)
72
+ assert_equal tm.hm.find(1).description, 'updated'
73
+ end
74
+
58
75
  end
@@ -6,26 +6,44 @@ require 'lanes/command'
6
6
  require 'lanes/workspace/extension'
7
7
  require 'mocha/mini_test'
8
8
 
9
+ require "shrine/storage/memory"
10
+
11
+ # Shrine.storages = {
12
+ # }
13
+ require "shrine"
14
+ require "shrine/storage/file_system"
15
+
16
+ Lanes::Concerns::AssetUploader.storages = {
17
+ cache: Shrine::Storage::Memory.new,
18
+ store: Shrine::Storage::Memory.new,
19
+ }
20
+
9
21
 
10
22
  module TestingModels
11
23
  include ActiveRecordMocks::IncludeMe
12
24
 
13
25
  def around(&block)
14
- cw_root = CarrierWave.root
15
- begin
16
- Dir.mktmpdir('lanes-cw-root') do | dir |
17
- CarrierWave.root = dir
18
- self.with_testing_models(&block)
19
- end
20
- ensure
21
- CarrierWave.root = cw_root
22
- end
26
+ self.with_testing_models(&block)
27
+
28
+ # cw_root = CarrierWave.root
29
+ # begin
30
+ # Dir.mktmpdir('lanes-cw-root') do | dir |
31
+ # # CarrierWave.root = dir
32
+ # self.with_testing_models(&block)
33
+ # end
34
+ # ensure
35
+ # # CarrierWave.root = cw_root
36
+ # end
23
37
  end
24
38
 
25
39
  def with_testing_models
26
- with_mocked_tables do |m|
27
40
 
28
- m.enable_extension "hstore"
41
+ with_mocked_tables do |m|
42
+ [:test_models, :tmbts, :tmhms].each do | table |
43
+ if ActiveRecord::Base.connection.data_source_exists? table
44
+ ActiveRecord::Base.connection.drop_table table
45
+ end
46
+ end
29
47
 
30
48
  m.create_table do |t|
31
49
  t.model_name :TestModel
@@ -2,6 +2,7 @@ development:
2
2
  adapter: postgresql
3
3
  database: <%= name %>_dev
4
4
  host: /tmp
5
+ pool: <%= ENV["DB_POOL"] || 12 %>
5
6
 
6
7
  test:
7
8
  adapter: postgresql
@@ -2,4 +2,4 @@ describe "<%= screen_class %>", ->
2
2
 
3
3
  it "can be rendered", ->
4
4
  screen = LT.renderComponent(<%= screen_class %>)
5
- expect(_.dom(screen).text).toMatch("Hello")
5
+ expect(_.dom(screen).text).toBeTruthy()
data/views/specs.erb CHANGED
@@ -14,7 +14,10 @@
14
14
  <script src="<%= js_file %>" type="text/javascript"></script>
15
15
  <% end %>
16
16
  <script type="text/javascript">
17
- Lanes.config.bootstrap( <%= client_bootstrap_data %> );
17
+ Lanes.config.bootstrap( <%=
18
+ client_bootstrap_data(mergedWith: {
19
+ api_path: 'http://localhost:8888' + Lanes.config.api_path
20
+ }) %> );
18
21
  </script>
19
22
 
20
23
  </head>