luca 0.6.6

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.
Files changed (233) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +17 -0
  3. data/Gemfile.lock +77 -0
  4. data/Guardfile +22 -0
  5. data/README.md +291 -0
  6. data/Rakefile +28 -0
  7. data/app.rb +46 -0
  8. data/assets/images/glyphicons-halflings-white.png +0 -0
  9. data/assets/images/glyphicons-halflings.png +0 -0
  10. data/assets/javascripts/dependencies/backbone-min.js +37 -0
  11. data/assets/javascripts/dependencies/backbone-query.min.js +1 -0
  12. data/assets/javascripts/dependencies/bootstrap.min.js +1 -0
  13. data/assets/javascripts/dependencies/jasmine-html.js +190 -0
  14. data/assets/javascripts/dependencies/jasmine.js +2476 -0
  15. data/assets/javascripts/dependencies/jquery.js +4 -0
  16. data/assets/javascripts/dependencies/modal.js +698 -0
  17. data/assets/javascripts/dependencies/modernizr.min.js +30 -0
  18. data/assets/javascripts/dependencies/prettify.js +28 -0
  19. data/assets/javascripts/dependencies/sinon.js +3469 -0
  20. data/assets/javascripts/dependencies/spin-min.js +2 -0
  21. data/assets/javascripts/dependencies/underscore-min.js +31 -0
  22. data/assets/javascripts/dependencies/underscore-string.min.js +14 -0
  23. data/assets/javascripts/dependencies.coffee +7 -0
  24. data/assets/javascripts/luca-ui-base.coffee +12 -0
  25. data/assets/javascripts/luca-ui-spec.coffee +2 -0
  26. data/assets/javascripts/luca-ui.coffee +3 -0
  27. data/assets/javascripts/sandbox/collections/sample.coffee +0 -0
  28. data/assets/javascripts/sandbox/config.coffee +7 -0
  29. data/assets/javascripts/sandbox/sandbox.coffee +16 -0
  30. data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +33 -0
  31. data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +48 -0
  32. data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +24 -0
  33. data/assets/javascripts/sandbox/templates/features/introduction.luca +11 -0
  34. data/assets/javascripts/sandbox/templates/features/view_helpers.luca +43 -0
  35. data/assets/javascripts/sandbox/templates/navigation.luca +8 -0
  36. data/assets/javascripts/sandbox/views/form_demo.coffee +47 -0
  37. data/assets/javascripts/sandbox/views/grid_demo.coffee +23 -0
  38. data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +1 -0
  39. data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +28 -0
  40. data/assets/javascripts/sandbox.coffee +4 -0
  41. data/assets/javascripts/spec-dependencies.coffee +4 -0
  42. data/assets/stylesheets/bootstrap-responsive.min.css +3 -0
  43. data/assets/stylesheets/bootstrap.min.css +610 -0
  44. data/assets/stylesheets/jasmine.css +166 -0
  45. data/assets/stylesheets/luca-ui-bootstrap.css +5 -0
  46. data/assets/stylesheets/luca-ui-spec.css +3 -0
  47. data/assets/stylesheets/luca-ui.css +3 -0
  48. data/assets/stylesheets/prettify.css +40 -0
  49. data/assets/stylesheets/sandbox/sandbox.scss +4 -0
  50. data/assets/stylesheets/sandbox.css +3 -0
  51. data/config.ru +11 -0
  52. data/lib/luca/command_line.rb +69 -0
  53. data/lib/luca/rails/engine.rb +12 -0
  54. data/lib/luca/rails/version.rb +6 -0
  55. data/lib/luca/rails.rb +9 -0
  56. data/lib/luca/template.rb +51 -0
  57. data/lib/luca/test_harness.rb +106 -0
  58. data/lib/luca.rb +1 -0
  59. data/lib/sprockets/luca_template.rb +49 -0
  60. data/lib/templates/spec_manifest_javascripts.erb +7 -0
  61. data/lib/templates/spec_manifest_stylesheets.erb +11 -0
  62. data/luca.gemspec +26 -0
  63. data/public/jasmine/index.html +26 -0
  64. data/public/sandbox/api.js +1 -0
  65. data/spec/components/application_spec.coffee +0 -0
  66. data/spec/components/collection_loader_view_spec.coffee +0 -0
  67. data/spec/components/controller_spec.coffee +0 -0
  68. data/spec/components/form_view_spec.coffee +13 -0
  69. data/spec/components/grid_view_spec.coffee +0 -0
  70. data/spec/components/record_manager_spec.coffee +0 -0
  71. data/spec/components/template_spec.coffee +0 -0
  72. data/spec/containers/card_view_spec.coffee +1 -0
  73. data/spec/containers/column_view_spec.coffee +0 -0
  74. data/spec/containers/modal_view_spec.coffee +0 -0
  75. data/spec/containers/panel_view_spec.coffee +0 -0
  76. data/spec/containers/split_view_spec.coffee +0 -0
  77. data/spec/containers/tab_view_spec.coffee +0 -0
  78. data/spec/containers/viewport_spec.coffee +0 -0
  79. data/spec/core/collection_spec.coffee +215 -0
  80. data/spec/core/container_spec.coffee +0 -0
  81. data/spec/core/field_spec.coffee +0 -0
  82. data/spec/core/observer_spec.coffee +0 -0
  83. data/spec/core/view_spec.coffee +87 -0
  84. data/spec/framework_spec.coffee +48 -0
  85. data/spec/helper.coffee +120 -0
  86. data/spec/managers/collection_manager_spec.coffee +95 -0
  87. data/spec/managers/socket_manager_spec.coffee +0 -0
  88. data/src/components/application.coffee +83 -0
  89. data/src/components/base_toolbar.coffee +16 -0
  90. data/src/components/collection_loader_view.coffee +37 -0
  91. data/src/components/controller.coffee +41 -0
  92. data/src/components/fields/button_field.coffee +40 -0
  93. data/src/components/fields/checkbox_field.coffee +41 -0
  94. data/src/components/fields/file_upload_field.coffee +15 -0
  95. data/src/components/fields/hidden_field.coffee +18 -0
  96. data/src/components/fields/select_field.coffee +100 -0
  97. data/src/components/fields/text_area_field.coffee +43 -0
  98. data/src/components/fields/text_field.coffee +42 -0
  99. data/src/components/fields/type_ahead_field.coffee +10 -0
  100. data/src/components/form_button_toolbar.coffee +26 -0
  101. data/src/components/form_view.coffee +205 -0
  102. data/src/components/grid_view.coffee +208 -0
  103. data/src/components/record_manager.coffee +215 -0
  104. data/src/components/router.coffee +34 -0
  105. data/src/components/template.coffee +19 -0
  106. data/src/containers/card_view.coffee +89 -0
  107. data/src/containers/column_view.coffee +48 -0
  108. data/src/containers/modal_view.coffee +85 -0
  109. data/src/containers/panel_view.coffee +24 -0
  110. data/src/containers/split_view.coffee +12 -0
  111. data/src/containers/tab_view.coffee +77 -0
  112. data/src/containers/viewport.coffee +16 -0
  113. data/src/core/collection.coffee +319 -0
  114. data/src/core/container.coffee +256 -0
  115. data/src/core/field.coffee +68 -0
  116. data/src/core/observer.coffee +17 -0
  117. data/src/core/view.coffee +190 -0
  118. data/src/framework.coffee +110 -0
  119. data/src/index.coffee +255 -0
  120. data/src/managers/collection_manager.coffee +168 -0
  121. data/src/managers/socket_manager.coffee +54 -0
  122. data/src/modules/deferrable.coffee +18 -0
  123. data/src/modules/local_storage.coffee +50 -0
  124. data/src/stylesheets/base.scss +78 -0
  125. data/src/stylesheets/components/form_view.scss +54 -0
  126. data/src/stylesheets/components/grid_view.scss +111 -0
  127. data/src/stylesheets/components/toolbar.scss +15 -0
  128. data/src/stylesheets/containers/container.scss +7 -0
  129. data/src/stylesheets/containers/modal_view.scss +0 -0
  130. data/src/stylesheets/containers/tab_view.scss +33 -0
  131. data/src/stylesheets/normalize.scss +430 -0
  132. data/src/templates/components/bootstrap_form_controls.luca +7 -0
  133. data/src/templates/components/collection_loader_view.luca +5 -0
  134. data/src/templates/components/form_view.luca +15 -0
  135. data/src/templates/components/grid_view.luca +9 -0
  136. data/src/templates/components/grid_view_empty_text.luca +3 -0
  137. data/src/templates/containers/basic.luca +1 -0
  138. data/src/templates/containers/tab_selector_container.luca +8 -0
  139. data/src/templates/containers/tab_view.luca +1 -0
  140. data/src/templates/containers/toolbar_wrapper.luca +1 -0
  141. data/src/templates/fields/button_field.luca +2 -0
  142. data/src/templates/fields/button_field_link.luca +5 -0
  143. data/src/templates/fields/checkbox_field.luca +9 -0
  144. data/src/templates/fields/file_upload_field.luca +8 -0
  145. data/src/templates/fields/hidden_field.luca +1 -0
  146. data/src/templates/fields/select_field.luca +7 -0
  147. data/src/templates/fields/text_area_field.luca +8 -0
  148. data/src/templates/fields/text_field.luca +13 -0
  149. data/src/templates/sample/contents.luca +1 -0
  150. data/src/templates/sample/welcome.luca +1 -0
  151. data/vendor/assets/images/glyphicons-halflings-white.png +0 -0
  152. data/vendor/assets/images/glyphicons-halflings.png +0 -0
  153. data/vendor/assets/javascripts/luca-spec-dependencies.js +6135 -0
  154. data/vendor/assets/javascripts/luca-ui-base.js +1527 -0
  155. data/vendor/assets/javascripts/luca-ui-spec.js +3654 -0
  156. data/vendor/assets/javascripts/luca-ui.js +2763 -0
  157. data/vendor/assets/luca-ui/base.css +85 -0
  158. data/vendor/assets/luca-ui/components/application.js +91 -0
  159. data/vendor/assets/luca-ui/components/base_toolbar.js +23 -0
  160. data/vendor/assets/luca-ui/components/controller.js +38 -0
  161. data/vendor/assets/luca-ui/components/fields/button_field.js +45 -0
  162. data/vendor/assets/luca-ui/components/fields/checkbox_field.js +43 -0
  163. data/vendor/assets/luca-ui/components/fields/file_upload_field.js +20 -0
  164. data/vendor/assets/luca-ui/components/fields/hidden_field.js +20 -0
  165. data/vendor/assets/luca-ui/components/fields/select_field.js +97 -0
  166. data/vendor/assets/luca-ui/components/fields/text_area_field.js +48 -0
  167. data/vendor/assets/luca-ui/components/fields/text_field.js +46 -0
  168. data/vendor/assets/luca-ui/components/fields/type_ahead_field.js +13 -0
  169. data/vendor/assets/luca-ui/components/form_button_toolbar.js +32 -0
  170. data/vendor/assets/luca-ui/components/form_view.css +32 -0
  171. data/vendor/assets/luca-ui/components/form_view.js +207 -0
  172. data/vendor/assets/luca-ui/components/grid_view.css +76 -0
  173. data/vendor/assets/luca-ui/components/grid_view.js +202 -0
  174. data/vendor/assets/luca-ui/components/record_manager.js +207 -0
  175. data/vendor/assets/luca-ui/components/router.js +36 -0
  176. data/vendor/assets/luca-ui/components/template.js +26 -0
  177. data/vendor/assets/luca-ui/components/toolbar.css +11 -0
  178. data/vendor/assets/luca-ui/containers/card_view.js +98 -0
  179. data/vendor/assets/luca-ui/containers/column_view.js +52 -0
  180. data/vendor/assets/luca-ui/containers/container.css +3 -0
  181. data/vendor/assets/luca-ui/containers/modal_view.css +0 -0
  182. data/vendor/assets/luca-ui/containers/modal_view.js +87 -0
  183. data/vendor/assets/luca-ui/containers/panel_view.js +34 -0
  184. data/vendor/assets/luca-ui/containers/split_view.js +13 -0
  185. data/vendor/assets/luca-ui/containers/tab_view.css +16 -0
  186. data/vendor/assets/luca-ui/containers/tab_view.js +80 -0
  187. data/vendor/assets/luca-ui/containers/viewport.js +18 -0
  188. data/vendor/assets/luca-ui/core/collection.js +221 -0
  189. data/vendor/assets/luca-ui/core/container.js +205 -0
  190. data/vendor/assets/luca-ui/core/field.js +59 -0
  191. data/vendor/assets/luca-ui/core/observer.js +42 -0
  192. data/vendor/assets/luca-ui/core/view.js +127 -0
  193. data/vendor/assets/luca-ui/framework.js +110 -0
  194. data/vendor/assets/luca-ui/index.js +5 -0
  195. data/vendor/assets/luca-ui/managers/collection_manager.js +98 -0
  196. data/vendor/assets/luca-ui/managers/socket_manager.js +52 -0
  197. data/vendor/assets/luca-ui/modules/deferrable.js +21 -0
  198. data/vendor/assets/luca-ui/modules/local_storage.js +81 -0
  199. data/vendor/assets/luca-ui/normalize.css +359 -0
  200. data/vendor/assets/luca-ui/stylesheets/base.css +85 -0
  201. data/vendor/assets/luca-ui/stylesheets/components/form_view.css +32 -0
  202. data/vendor/assets/luca-ui/stylesheets/components/grid_view.css +76 -0
  203. data/vendor/assets/luca-ui/stylesheets/components/toolbar.css +11 -0
  204. data/vendor/assets/luca-ui/stylesheets/containers/container.css +3 -0
  205. data/vendor/assets/luca-ui/stylesheets/containers/modal_view.css +0 -0
  206. data/vendor/assets/luca-ui/stylesheets/containers/tab_view.css +16 -0
  207. data/vendor/assets/luca-ui/stylesheets/normalize.css +359 -0
  208. data/vendor/assets/luca-ui/templates/components/bootstrap_form_controls.js +4 -0
  209. data/vendor/assets/luca-ui/templates/components/form_view.js +4 -0
  210. data/vendor/assets/luca-ui/templates/components/grid_view.js +4 -0
  211. data/vendor/assets/luca-ui/templates/components/grid_view_empty_text.js +4 -0
  212. data/vendor/assets/luca-ui/templates/containers/basic.js +4 -0
  213. data/vendor/assets/luca-ui/templates/containers/tab_selector_container.js +4 -0
  214. data/vendor/assets/luca-ui/templates/containers/tab_view.js +4 -0
  215. data/vendor/assets/luca-ui/templates/containers/toolbar_wrapper.js +4 -0
  216. data/vendor/assets/luca-ui/templates/fields/button_field.js +4 -0
  217. data/vendor/assets/luca-ui/templates/fields/button_field_link.js +4 -0
  218. data/vendor/assets/luca-ui/templates/fields/checkbox_field.js +4 -0
  219. data/vendor/assets/luca-ui/templates/fields/file_upload_field.js +4 -0
  220. data/vendor/assets/luca-ui/templates/fields/hidden_field.js +4 -0
  221. data/vendor/assets/luca-ui/templates/fields/select_field.js +4 -0
  222. data/vendor/assets/luca-ui/templates/fields/text_area_field.js +4 -0
  223. data/vendor/assets/luca-ui/templates/fields/text_field.js +4 -0
  224. data/vendor/assets/luca-ui/templates/sample/contents.js +4 -0
  225. data/vendor/assets/luca-ui/templates/sample/welcome.js +4 -0
  226. data/vendor/assets/stylesheets/luca-spec-dependencies.css +166 -0
  227. data/vendor/assets/stylesheets/luca-ui-bootstrap.css +1201 -0
  228. data/vendor/assets/stylesheets/luca-ui-spec.css +586 -0
  229. data/vendor/assets/stylesheets/luca-ui.css +586 -0
  230. data/views/index.erb +20 -0
  231. data/views/jasmine.erb +22 -0
  232. data/views/spec_harness.erb +29 -0
  233. metadata +361 -0
File without changes
@@ -0,0 +1,13 @@
1
+ describe 'The Form View', ->
2
+ describe 'Generating a form from a model', ->
3
+ beforeEach ->
4
+ Model = Backbone.Model.extend
5
+ schema:
6
+ field0: "hidden"
7
+ field1: "text"
8
+ field3: "boolean"
9
+ field4: "blob"
10
+ field5:
11
+ collection: "sample"
12
+
13
+ @model = new Model(field0:1,field1:"jonathan",field3:true,field4:"what up player?")
File without changes
File without changes
File without changes
@@ -0,0 +1 @@
1
+ describe "The Card View", ->
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,215 @@
1
+ #### Luca.Collection
2
+
3
+ describe "Luca.Collection", ->
4
+ it "should accept a name and collection manager", ->
5
+ mgr = new Luca.CollectionManager()
6
+ collection = new Luca.Collection([], name:"booya",manager:mgr)
7
+ expect( collection.name ).toEqual("booya")
8
+ expect( collection.manager ).toEqual(mgr)
9
+
10
+ it "should allow me to specify my own fetch method on a per collection basis", ->
11
+ spy = sinon.spy()
12
+ collection = new Luca.Collection([],fetch:spy)
13
+ collection.fetch()
14
+
15
+ expect( spy.called ).toBeTruthy()
16
+
17
+ it "should trigger before:fetch", ->
18
+ collection = new Luca.Collection([], url:"/models")
19
+ spy = sinon.spy()
20
+ collection.bind "before:fetch", spy
21
+ collection.fetch()
22
+ expect( spy.called ).toBeTruthy()
23
+
24
+ it "should automatically parse a response with a root in it", ->
25
+ collection = new Luca.Collection([], root:"root",url:"/rooted/models")
26
+ collection.fetch()
27
+ @server.respond()
28
+ expect( collection.length ).toEqual(2)
29
+
30
+ it "should attempt to register with a collection manager", ->
31
+ registerSpy = sinon.spy()
32
+
33
+ collection = new Luca.Collection [],
34
+ name:"registered"
35
+ register: registerSpy
36
+
37
+ expect( registerSpy ).toHaveBeenCalled()
38
+
39
+ describe "The ifLoaded helper", ->
40
+ it "should fire the passed callback automatically if there are models", ->
41
+ spy = sinon.spy()
42
+ collection = new Luca.Collection([{attr:"value"}])
43
+ collection.ifLoaded(spy)
44
+ expect( spy.callCount ).toEqual(1)
45
+
46
+ it "should fire the passed callback any time the collection resets", ->
47
+ spy = sinon.spy()
48
+
49
+ collection = new Luca.Collection([{attr:"value"}], url:"/models")
50
+
51
+ collection.ifLoaded ()->
52
+ spy.call()
53
+
54
+ collection.fetch()
55
+ @server.respond()
56
+
57
+ expect( spy.callCount ).toEqual(2)
58
+
59
+ it "should not fire the callback if there are no models", ->
60
+ spy = sinon.spy()
61
+ collection = new Luca.Collection()
62
+ collection.ifLoaded(spy)
63
+ expect( spy.called ).toBeFalsy()
64
+
65
+ it "should automatically call fetch on the collection", ->
66
+ spy = sinon.spy()
67
+ collection = new Luca.Collection([],url:"/models",blah:true)
68
+ collection.ifLoaded(spy)
69
+ @server.respond()
70
+ expect( spy.called ).toBeTruthy()
71
+
72
+ it "should allow me to not automatically call fetch on the collection", ->
73
+ collection = new Luca.Collection([],url:"/models")
74
+ spy = sinon.spy( collection.fetch )
75
+ fn = ()-> true
76
+ collection.ifLoaded(fn, autoFetch:false)
77
+ expect( spy.called ).toBeFalsy()
78
+
79
+ describe "The onceLoaded helper", ->
80
+ it "should fire the passed callback once if there are models", ->
81
+ spy = sinon.spy()
82
+ collection = new Luca.Collection([{attr:"value"}])
83
+ collection.onceLoaded(spy)
84
+ expect( spy.callCount ).toEqual(1)
85
+
86
+ it "should fire the passed callback only once", ->
87
+ spy = sinon.spy()
88
+ collection = new Luca.Collection([{attr:"value"}],url:"/models")
89
+ collection.onceLoaded(spy)
90
+ expect( spy.callCount ).toEqual(1)
91
+
92
+ collection.fetch()
93
+ @server.respond()
94
+ expect( spy.callCount ).toEqual(1)
95
+
96
+ it "should not fire the callback if there are no models", ->
97
+ spy = sinon.spy()
98
+ collection = new Luca.Collection()
99
+ collection.onceLoaded(spy)
100
+ expect( spy.called ).toBeFalsy()
101
+
102
+ it "should automatically call fetch on the collection", ->
103
+ spy = sinon.spy()
104
+ collection = new Luca.Collection([],url:"/models")
105
+ collection.onceLoaded(spy)
106
+ @server.respond()
107
+ expect( spy.called ).toBeTruthy()
108
+
109
+ it "should allow me to not automatically call fetch on the collection", ->
110
+ collection = new Luca.Collection([],url:"/models")
111
+ spy = sinon.spy( collection.fetch )
112
+ fn = ()-> true
113
+ collection.onceLoaded(fn, autoFetch:false)
114
+ expect( spy.called ).toBeFalsy()
115
+
116
+ describe "Registering with the collection manager", ->
117
+
118
+ it "should be able to find a default collection manager", ->
119
+ mgr = new Luca.CollectionManager()
120
+ expect( Luca.CollectionManager.get() ).toEqual(mgr)
121
+
122
+ it "should automatically register with the manager if I specify a name", ->
123
+ mgr = new Luca.CollectionManager()
124
+ collection = new Luca.Collection([],name:"auto_register")
125
+ expect( mgr.get("auto_register") ).toEqual(collection)
126
+
127
+ it "should register with a specific manager", ->
128
+ window.other_manager = new Luca.CollectionManager()
129
+
130
+ collection = new Luca.Collection [],
131
+ name: "other_collection"
132
+ manager: window.other_manager
133
+
134
+ expect( window.other_manager.get("other_collection") ).toEqual(collection)
135
+
136
+ it "should find a collection manager by string", ->
137
+ window.find_mgr_by_string = new Luca.CollectionManager()
138
+
139
+ collection = new Luca.Collection [],
140
+ name: "biggie"
141
+ manager: "find_mgr_by_string"
142
+
143
+ expect( collection.manager ).toBeDefined()
144
+
145
+ it "should not register with a collection manager if it is marked as private", ->
146
+ manager = new Luca.CollectionManager()
147
+
148
+ registerSpy = sinon.spy()
149
+
150
+ private = new Luca.Collection [],
151
+ name: "private"
152
+ manager: manager
153
+ private: true
154
+ register: registerSpy
155
+
156
+ expect( registerSpy ).not.toHaveBeenCalled()
157
+
158
+
159
+ describe "The Model Bootstrap", ->
160
+ window.ModelBootstrap =
161
+ sample: []
162
+
163
+ _(5).times (n)->
164
+ window.ModelBootstrap.sample.push
165
+ id: n
166
+ key: "value"
167
+
168
+ it "should add an object into the models cache", ->
169
+ Luca.Collection.bootstrap( window.ModelBootstrap )
170
+ expect( Luca.Collection.cache("sample").length ).toEqual(5)
171
+
172
+ it "should fetch the cached models from the bootstrap", ->
173
+ collection = new Luca.Collection [],
174
+ cached: ()-> "sample"
175
+
176
+ collection.fetch()
177
+
178
+ expect( collection.length ).toEqual(5)
179
+ expect( collection.pluck('id') ).toEqual([0,1,2,3,4])
180
+
181
+ it "should reference the cached models", ->
182
+ collection = new Luca.Collection [],
183
+ cached: ()-> "sample"
184
+
185
+ expect( collection.cached_models().length ).toEqual(5)
186
+
187
+ it "should avoid making an API call", ->
188
+ spy = sinon.spy( Backbone.Collection.prototype.fetch )
189
+ collection = new Luca.Collection [],
190
+ cached: ()-> "sample"
191
+
192
+ collection.fetch()
193
+ expect( spy.called ).toBeFalsy()
194
+
195
+ it "should make an API call if specifically asked", ->
196
+ spy = sinon.spy()
197
+
198
+ collection = new Luca.Collection [],
199
+ cached: ()-> "sample"
200
+ url: ()-> "/models"
201
+
202
+ collection.bind "after:response", spy
203
+ collection.fetch(refresh:true)
204
+ @server.respond()
205
+
206
+ expect( spy.called ).toBeTruthy()
207
+
208
+
209
+
210
+
211
+
212
+
213
+
214
+
215
+
File without changes
File without changes
File without changes
@@ -0,0 +1,87 @@
1
+ describe "Luca.View", ->
2
+ Custom = Luca.View.extend
3
+ clickHandler: sinon.spy()
4
+ autoBindEventHandlers: true
5
+
6
+ it "should be defined", ->
7
+ expect(Luca.View).toBeDefined()
8
+
9
+ it "should extend itself with the passed options", ->
10
+ view = new Luca.View(name:"custom")
11
+ expect(view.name).toEqual("custom")
12
+
13
+ it "should create a unique id based on the name", ->
14
+ view = new Luca.View(name:"boom")
15
+ expect( view.cid ).toContain 'boom'
16
+
17
+ it "should register the view in the cache", ->
18
+ view = new Luca.View(name:"cached")
19
+ expect( Luca.cache("cached") ).toBeDefined()
20
+
21
+ it "should trigger after initialize", ->
22
+ view = new Luca.View()
23
+ expect( view ).toHaveTriggered("after:initialize")
24
+
25
+ it "should auto-bind event handlers", ->
26
+ # pending
27
+
28
+
29
+
30
+ describe "Hooks", ->
31
+ it "should have before and after render hooks", ->
32
+ Custom = Luca.View.extend
33
+ beforeRender: sinon.spy()
34
+ afterRender: sinon.spy()
35
+
36
+ view = new Custom()
37
+
38
+ view.render()
39
+
40
+ expect( view.beforeRender ).toHaveBeenCalled()
41
+ expect( view.afterRender ).toHaveBeenCalled()
42
+
43
+ it "should call custom hooks in addition to framework hooks", ->
44
+ Custom = Luca.View.extend
45
+ hooks:["custom:hook"]
46
+ afterRender: ()-> @trigger("custom:hook")
47
+ customHook: sinon.spy()
48
+
49
+ view = new Custom()
50
+
51
+ view.render()
52
+
53
+ expect( view.customHook ).toHaveBeenCalled()
54
+
55
+ describe "The Collection Events API", ->
56
+ App =
57
+ collections : {}
58
+
59
+ App.collections.Sample = Luca.Collection.extend
60
+ name: "sample"
61
+
62
+ SampleView = Luca.View.extend
63
+ resetHandler: sinon.spy()
64
+ collectionEvents:
65
+ "sample reset" : "resetHandler"
66
+
67
+ class SampleManager extends Luca.CollectionManager
68
+ collectionNamespace: App.collections
69
+ name: "collectionEvents"
70
+
71
+ beforeEach ()->
72
+ @manager ||= new SampleManager()
73
+ @collection = @manager.getOrCreate("sample")
74
+
75
+ it "should know which collection manager to use", ->
76
+ view = new SampleView()
77
+ expect( view.getCollectionManager().name ).toEqual( "collectionEvents" )
78
+
79
+ it "should create a reference to the collection", ->
80
+ view = new SampleView()
81
+ expect( view.sampleCollection ).toBeDefined()
82
+
83
+ it "should call the resetHandler callback on the view", ->
84
+ view = new SampleView()
85
+ collection = @manager.get("sample")
86
+ collection.reset([])
87
+ expect( view.resetHandler ).toHaveBeenCalled()
@@ -0,0 +1,48 @@
1
+ #= require "./helper"
2
+
3
+ describe "The Luca Framework", ->
4
+ it "should specify a version", ->
5
+ expect(Luca.VERSION).toBeDefined()
6
+
7
+ it "should define Luca in the global space", ->
8
+ expect(Luca).toBeDefined()
9
+
10
+ it "should enable bootstrap by default", ->
11
+ expect(Luca.enableBootstrap).toBeTruthy()
12
+
13
+ it "should have classes in the registry", ->
14
+ expect( Luca.registry.classes ).toBeDefined()
15
+
16
+ it "should be able to lookup classes in the registry by ctype", ->
17
+ expect( Luca.registry.lookup("form_view") ).toBeTruthy()
18
+
19
+ it "should allow me to add view namespaces to the registry", ->
20
+ Luca.registry.addNamespace("Test.namespace")
21
+ expect( Luca.registry.namespaces ).toContain("Test.namespace")
22
+
23
+ it "should resolve a value.string to the object", ->
24
+ window.nested =
25
+ value:
26
+ string: "haha"
27
+
28
+ value = Luca.util.nestedValue("nested.value.string", window)
29
+
30
+ expect(value).toEqual("haha")
31
+
32
+ it "should create an instance of a class by ctype", ->
33
+ object =
34
+ ctype: "template"
35
+ template: "components/form_view"
36
+
37
+ component = Luca.util.lazyComponent(object)
38
+ expect( _.isFunction(component.render) ).toBeTruthy()
39
+
40
+ it "should find a created view in the cache", ->
41
+ template = new Luca.components.Template
42
+ template: "components/form_view"
43
+ name: 'test_template'
44
+
45
+ expect(Luca.cache("test_template")).toBeDefined()
46
+
47
+
48
+ describe
@@ -0,0 +1,120 @@
1
+ # thanks player
2
+ # https://github.com/thefrontside/jasmine.backbone.js
3
+
4
+ json = (object) ->
5
+ JSON.stringify object
6
+
7
+ msg = (list) ->
8
+ (if list.length isnt 0 then list.join(";") else "")
9
+
10
+ eventBucket = (model, eventName) ->
11
+ spiedEvents = model.spiedEvents
12
+ spiedEvents = model.spiedEvents = {} unless spiedEvents
13
+ bucket = spiedEvents[eventName]
14
+ bucket = spiedEvents[eventName] = [] unless bucket
15
+ bucket
16
+
17
+ triggerSpy = (constructor) ->
18
+ trigger = constructor::trigger
19
+ constructor::trigger = (eventName) ->
20
+ bucket = eventBucket(this, eventName)
21
+ bucket.push Array::slice.call(arguments, 1)
22
+ trigger.apply this, arguments
23
+
24
+ triggerSpy Backbone.Model
25
+ triggerSpy Backbone.Collection
26
+ triggerSpy Backbone.View
27
+
28
+ EventMatchers =
29
+ toHaveTriggered: (eventName) ->
30
+ bucket = eventBucket(@actual, eventName)
31
+ triggeredWith = Array::slice.call(arguments, 1)
32
+ @message = ->
33
+ [ "expected model or collection to have received '" + eventName + "' with " + json(triggeredWith), "expected model not to have received event '" + eventName + "', but it did" ]
34
+
35
+ _.detect bucket, (args) ->
36
+ if triggeredWith.length is 0
37
+ true
38
+ else
39
+ jasmine.getEnv().equals_ triggeredWith, args
40
+
41
+ ModelMatchers =
42
+ toHaveAttributes: (attributes) ->
43
+ keys = []
44
+ values = []
45
+ jasmine.getEnv().equals_ @actual.attributes, attributes, keys, values
46
+ missing = []
47
+ i = 0
48
+
49
+ while i < keys.length
50
+ message = keys[i]
51
+ missing.push keys[i] if message.match(/but missing from/)
52
+ i++
53
+ @message = ->
54
+ [ "model should have at least these attributes(" + json(attributes) + ") " + msg(missing) + " " + msg(values), "model should have none of the following attributes(" + json(attributes) + ") " + msg(keys) + " " + msg(values) ]
55
+
56
+ missing.length is 0 and values.length is 0
57
+
58
+ toHaveExactlyTheseAttributes: (attributes) ->
59
+ keys = []
60
+ values = []
61
+ equal = jasmine.getEnv().equals_(@actual.attributes, attributes, keys, values)
62
+ @message = ->
63
+ [ "model should match exact attributes, but does not. " + msg(keys) + " " + msg(values), "model has exactly these attributes, but shouldn't :" + json(attributes) ]
64
+
65
+ equal
66
+
67
+ createFakeServer = ->
68
+ server = sinon.fakeServer.create()
69
+ server.respondWith("GET", "/models", [
70
+ 200,
71
+ {"Content-Type":"application/json"},
72
+ '[{"id":1,"attr1":"value1","attr2":"value2"},{"id":2,"attr1":"value1","attr2":"value2"}]'
73
+ ])
74
+ server.respondWith("GET", "/rooted/models", [
75
+ 200,
76
+ {"Content-Type":"application/json"},
77
+ '{"root":[{"id":1,"attr1":"value1","attr2":"value2"},{"id":2,"attr1":"value1","attr2":"value2"}]}'
78
+ ])
79
+ server.respondWith("GET", "/empty", [
80
+ 200,
81
+ {"Content-Type":"application/json"},
82
+ '[]'
83
+ ])
84
+ server
85
+
86
+ spyMatchers = "called calledOnce calledTwice calledThrice calledBefore calledAfter calledOn alwaysCalledOn calledWith alwaysCalledWith calledWithExactly alwaysCalledWithExactly".split(" ")
87
+ i = spyMatchers.length
88
+ spyMatcherHash = {}
89
+ unusualMatchers =
90
+ returned: "toHaveReturned"
91
+ alwaysReturned: "toHaveAlwaysReturned"
92
+ threw: "toHaveThrown"
93
+ alwaysThrew: "toHaveAlwaysThrown"
94
+
95
+ getMatcherFunction = (sinonName) ->
96
+ ->
97
+ sinonProperty = @actual[sinonName]
98
+ (if (typeof sinonProperty is "function") then sinonProperty.apply(@actual, arguments) else sinonProperty)
99
+
100
+ while i--
101
+ sinonName = spyMatchers[i]
102
+ matcherName = "toHaveBeen" + sinonName.charAt(0).toUpperCase() + sinonName.slice(1)
103
+ spyMatcherHash[matcherName] = getMatcherFunction(sinonName)
104
+ for j of unusualMatchers
105
+ spyMatcherHash[unusualMatchers[j]] = getMatcherFunction(j)
106
+
107
+ window.sinonJasmine =
108
+ getMatchers: ->
109
+ spyMatcherHash
110
+
111
+ #### Loadup Jasmine
112
+ beforeEach ->
113
+ @server = createFakeServer()
114
+
115
+ @addMatchers ModelMatchers
116
+ @addMatchers EventMatchers
117
+ @addMatchers sinonJasmine.getMatchers()
118
+
119
+ afterEach ->
120
+ @server.restore()
@@ -0,0 +1,95 @@
1
+ describe "The Collection Manager", ->
2
+ App = collections: {}
3
+
4
+ App.collections.SampleCollection = Luca.Collection.extend
5
+ url: "/models"
6
+
7
+ beforeEach ()->
8
+ @manager = new Luca.CollectionManager(name:"manager",collectionNamespace: App.collections)
9
+
10
+ it "should be defined", ->
11
+ expect( Luca.CollectionManager ).toBeDefined()
12
+
13
+ it "should make the latest instance accessible by class function", ->
14
+ expect( Luca.CollectionManager.get().name ).toEqual("manager")
15
+
16
+ it "should be able to guess a collection constructor class", ->
17
+ base = @manager.guessCollectionClass("sample_collection")
18
+ expect( base ).toEqual(App.collections.SampleCollection)
19
+
20
+ it "should create a collection on demand", ->
21
+ collection = @manager.getOrCreate("sample_collection")
22
+ expect( collection.url ).toEqual "/models"
23
+
24
+ describe "Adding Collections", ->
25
+ manager = new Luca.CollectionManager
26
+ first = new Luca.Collection([],name:"added",prop:"val2")
27
+ second = new Luca.Collection([],name:"added",prop:"val1")
28
+
29
+ manager.add("added", first)
30
+ manager.add("added", second)
31
+
32
+ expect( manager.get("added") ).toEqual( first )
33
+
34
+ describe "The Scope Functionality", ->
35
+ scope = "one"
36
+
37
+ manager = new Luca.CollectionManager
38
+ getScope: ()-> scope
39
+
40
+ babyone = new Luca.Collection([{id:1},{id:2}],name:"baby")
41
+
42
+ manager.add("baby", babyone)
43
+
44
+ expect( manager.get("baby").pluck('id') ).toEqual([1,2])
45
+ expect( manager.get("baby") ).toBeDefined()
46
+ expect( manager.get("baby") ).toEqual( babyone )
47
+ expect( manager.allCollections().length ).toEqual(1)
48
+
49
+ scope = "two"
50
+
51
+ babytwo = new Luca.Collection([{id:3},{id:4}],name:"baby")
52
+
53
+ expect( manager.get("baby").pluck('id') ).toEqual([3,4])
54
+ expect( manager.get("baby") ).toBeDefined()
55
+ expect( manager.get("baby") ).toEqual( babytwo )
56
+ expect( manager.allCollections().length ).toEqual(1)
57
+
58
+ scope = "one"
59
+ expect( manager.get("baby").pluck('id') ).toEqual([1,2])
60
+
61
+ describe "Loading collections", ->
62
+ App = collections: {}
63
+
64
+ exampleSpy = sinon.spy()
65
+ sampleSpy = sinon.spy()
66
+
67
+ App.collections.ExampleCollection = Luca.Collection.extend
68
+ name: "example"
69
+ url: "/example_models"
70
+ fetch: ()->
71
+ exampleSpy.call()
72
+ @reset([{id: 1}])
73
+
74
+ App.collections.SampleCollection = Luca.Collection.extend
75
+ name: "sample"
76
+ url: "/sample_models"
77
+ fetch: ()->
78
+ sampleSpy.call()
79
+ @reset([{id: 4}])
80
+
81
+ manager = new Luca.CollectionManager(name:"manager",collectionNamespace: App.collections, collectionNames: ["example", "sample"])
82
+
83
+ it "should have example collection created", ->
84
+ collection = manager.get("example")
85
+ expect(collection.url).toEqual ("/example_models")
86
+
87
+ it "should have example collection fetched", ->
88
+ expect(exampleSpy).toHaveBeenCalled()
89
+
90
+ it "should have sample collection created", ->
91
+ collection = manager.get("sample")
92
+ expect(collection.url).toEqual ("/sample_models")
93
+
94
+ it "should have sample collection loaded", ->
95
+ expect(sampleSpy).toHaveBeenCalled()
File without changes