joosy 1.2.0.alpha.41 → 1.2.0.alpha.51

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/Gruntfile.coffee +27 -7
  4. data/bin/joosy +1 -1
  5. data/bower.json +3 -2
  6. data/build/joosy/extensions/preloaders.js +189 -0
  7. data/build/joosy/extensions/resources-form.js +588 -0
  8. data/build/joosy/extensions/resources.js +673 -0
  9. data/build/joosy.js +2395 -0
  10. data/{src/joosy/generators → generators}/base.coffee +2 -2
  11. data/{src/joosy/generators → generators/command}/command.coffee +16 -3
  12. data/generators/command/help.coffee +38 -0
  13. data/{src/joosy/generators → generators}/layout.coffee +0 -0
  14. data/{src/joosy/generators → generators}/page.coffee +0 -0
  15. data/{src/joosy/generators → generators}/project/base.coffee +2 -4
  16. data/{src/joosy/generators → generators}/project/standalone.coffee +4 -3
  17. data/{src/joosy/generators → generators}/project.coffee +0 -0
  18. data/generators/templates/application/base/application.coffee +13 -0
  19. data/{templates → generators/templates}/application/base/helpers/application.coffee +0 -0
  20. data/{templates → generators/templates}/application/base/layouts/application.coffee +0 -0
  21. data/{templates → generators/templates}/application/base/pages/application.coffee +0 -0
  22. data/{templates → generators/templates}/application/base/pages/welcome/index.coffee +0 -0
  23. data/{templates → generators/templates}/application/base/routes.coffee +0 -0
  24. data/{templates → generators/templates}/application/base/templates/layouts/application.jst.hamlc +0 -0
  25. data/{templates → generators/templates}/application/base/templates/pages/welcome/index.jst.hamlc +0 -0
  26. data/{templates → generators/templates}/application/standalone/Gruntfile.coffee +1 -0
  27. data/{templates → generators/templates}/application/standalone/Procfile +0 -0
  28. data/{templates → generators/templates}/application/standalone/_gitignore +0 -0
  29. data/generators/templates/application/standalone/bower.json +17 -0
  30. data/{templates → generators/templates}/application/standalone/package.json +0 -0
  31. data/{templates → generators/templates}/application/standalone/source/haml/index.haml +0 -0
  32. data/{templates → generators/templates}/application/standalone/source/stylesheets/application.styl +0 -0
  33. data/{templates → generators/templates}/layout/basic.coffee +0 -0
  34. data/{templates → generators/templates}/layout/namespaced.coffee +0 -0
  35. data/{templates → generators/templates}/page/basic.coffee +0 -0
  36. data/{templates → generators/templates}/page/namespaced.coffee +0 -0
  37. data/{templates → generators/templates}/widget/basic.coffee +0 -0
  38. data/{templates → generators/templates}/widget/namespaced.coffee +0 -0
  39. data/{src/joosy/generators → generators}/widget.coffee +0 -0
  40. data/lib/joosy.rb +3 -3
  41. data/package.json +2 -3
  42. data/source/joosy/application.coffee +95 -0
  43. data/source/joosy/events/namespace.coffee +24 -0
  44. data/{src → source}/joosy/extensions/preloaders/caching.coffee +0 -0
  45. data/{src → source}/joosy/extensions/preloaders/index.coffee +0 -0
  46. data/{src → source}/joosy/extensions/preloaders/inline.coffee +0 -0
  47. data/{src → source}/joosy/extensions/resources/base.coffee +16 -8
  48. data/{src → source}/joosy/extensions/resources/collection.coffee +0 -0
  49. data/{src → source}/joosy/extensions/resources/index.coffee +0 -0
  50. data/{src → source}/joosy/extensions/resources/rest.coffee +0 -0
  51. data/{src → source}/joosy/extensions/resources/rest_collection.coffee +0 -0
  52. data/{src → source}/joosy/extensions/resources-form/form.coffee +18 -18
  53. data/{src → source}/joosy/extensions/resources-form/helpers/form.coffee +6 -6
  54. data/{src → source}/joosy/extensions/resources-form/index.coffee +0 -0
  55. data/source/joosy/helpers/routes.coffee +10 -0
  56. data/source/joosy/helpers/view.coffee +115 -0
  57. data/{src/joosy/core → source/joosy}/helpers/widgets.coffee +1 -1
  58. data/{src/joosy/core → source/joosy}/joosy.coffee +59 -19
  59. data/source/joosy/layout.coffee +73 -0
  60. data/{src/joosy/core → source/joosy}/module.coffee +7 -2
  61. data/{src/joosy/core/modules/container.coffee → source/joosy/modules/dom.coffee} +24 -17
  62. data/source/joosy/modules/events.coffee +156 -0
  63. data/source/joosy/modules/filters.coffee +67 -0
  64. data/{src/joosy/core → source/joosy}/modules/log.coffee +7 -3
  65. data/source/joosy/modules/page/scrolling.coffee +51 -0
  66. data/source/joosy/modules/page/title.coffee +18 -0
  67. data/{src/joosy/core → source/joosy}/modules/renderer.coffee +12 -13
  68. data/{src/joosy/core → source/joosy}/modules/time_manager.coffee +5 -1
  69. data/{src/joosy/core → source/joosy}/modules/widgets_manager.coffee +9 -5
  70. data/source/joosy/page.coffee +68 -0
  71. data/{src/joosy/core → source/joosy}/resources/watcher.coffee +5 -1
  72. data/source/joosy/router.coffee +305 -0
  73. data/{src/joosy/core → source/joosy}/templaters/jst.coffee +10 -7
  74. data/source/joosy/widget.coffee +385 -0
  75. data/source/joosy.coffee +1 -0
  76. data/{src/vendor → source}/metamorph.coffee +0 -0
  77. data/spec/helpers/matchers.coffee +8 -1
  78. data/spec/joosy/core/application_spec.coffee +121 -20
  79. data/spec/joosy/core/helpers/view_spec.coffee +3 -3
  80. data/spec/joosy/core/helpers/widgets_spec.coffee +3 -6
  81. data/spec/joosy/core/joosy_spec.coffee +0 -5
  82. data/spec/joosy/core/layout_spec.coffee +2 -28
  83. data/spec/joosy/core/modules/dom_spec.coffee +133 -0
  84. data/spec/joosy/core/modules/events_spec.coffee +16 -9
  85. data/spec/joosy/core/modules/filters_spec.coffee +232 -89
  86. data/spec/joosy/core/modules/log_spec.coffee +2 -2
  87. data/spec/joosy/core/modules/renderer_spec.coffee +8 -4
  88. data/spec/joosy/core/page_spec.coffee +2 -201
  89. data/spec/joosy/core/router_spec.coffee +295 -233
  90. data/spec/joosy/core/templaters/jst_spec.coffee +1 -1
  91. data/spec/joosy/core/widget_spec.coffee +373 -34
  92. data/spec/joosy/environments/amd_spec.coffee +38 -0
  93. data/spec/joosy/environments/global_spec.coffee +21 -0
  94. data/spec/joosy/extensions/form/form_spec.coffee +18 -18
  95. data/spec/joosy/extensions/form/helpers/forms_spec.coffee +1 -1
  96. data/spec/joosy/extensions/resources/base_spec.coffee +23 -11
  97. data/tasks/joosy.coffee +6 -9
  98. metadata +75 -69
  99. data/lib/extensions/preloaders.js +0 -193
  100. data/lib/extensions/resources-form.js +0 -592
  101. data/lib/extensions/resources.js +0 -675
  102. data/lib/joosy.js +0 -2199
  103. data/spec/joosy/core/modules/container_spec.coffee +0 -153
  104. data/spec/joosy/core/modules/widget_manager_spec.coffee +0 -96
  105. data/src/joosy/core/application.coffee +0 -59
  106. data/src/joosy/core/helpers/view.coffee +0 -52
  107. data/src/joosy/core/layout.coffee +0 -174
  108. data/src/joosy/core/modules/events.coffee +0 -188
  109. data/src/joosy/core/modules/filters.coffee +0 -42
  110. data/src/joosy/core/page.coffee +0 -383
  111. data/src/joosy/core/router.coffee +0 -313
  112. data/src/joosy/core/widget.coffee +0 -88
  113. data/src/joosy.coffee +0 -1
  114. data/templates/application/base/application.coffee +0 -9
  115. data/templates/application/standalone/bower.json +0 -7
@@ -1,36 +1,375 @@
1
1
  describe "Joosy.Widget", ->
2
2
 
3
- beforeEach ->
4
- class @Widget extends Joosy.Widget
5
- @widget = new @Widget
6
-
7
- it "integrates with Router", ->
8
- target = sinon.stub Joosy.Router, 'navigate'
9
- @widget.navigate 'there'
10
- expect(target.callCount).toEqual 1
11
- expect(target.alwaysCalledWithExactly 'there').toBeTruthy()
12
- Joosy.Router.navigate.restore()
13
-
14
- it "loads", ->
15
- spies = []
16
- spies.push sinon.spy()
17
- spies.push sinon.spy(@widget, '__assignElements')
18
- spies.push sinon.spy(@widget, '__delegateEvents')
19
- spies.push sinon.spy(@widget, '__runAfterLoads')
20
-
21
- @widget.data = tested: true
22
- @Widget.view spies[0]
23
- @parent = new Joosy.Layout
24
-
25
- target = @widget.__load @parent, @$ground
26
-
27
- expect(target).toBe @widget
28
- expect(spies[0].getCall(0).calledOn()).toBeFalsy()
29
- expect(spies[0].getCall(0).args[0].tested).toBe true
30
- expect(spies).toBeSequenced()
31
-
32
- it "unloads", ->
33
- sinon.spy @widget, '__runAfterUnloads'
34
- @widget.__unload()
35
- expect(@widget.__runAfterUnloads.callCount).toEqual 1
36
- expect(@widget.__runAfterUnloads.getCall(0).calledOn()).toBeFalsy()
3
+ @beforeEach ->
4
+ Joosy.templater
5
+ resolveTemplate: (section, template) -> template
6
+ buildView: (template) -> (-> template) # ಠ_ಠ
7
+
8
+ describe 'callback caller', ->
9
+ beforeEach ->
10
+ @spies = spies = {}
11
+ entries = ['a', 'b', 'c', 'd']
12
+
13
+ for instance in entries
14
+ for filter in ['paint', 'beforePaint', 'erase', 'fetch']
15
+ spies[instance+'/'+filter] = sinon.spy()
16
+
17
+ class @A extends Joosy.Widget
18
+ @view """
19
+ <div id="content"></div>
20
+ """
21
+
22
+ @paint (done) -> spies['a/paint'](); done()
23
+ @beforePaint (done) -> spies['a/beforePaint'](); done()
24
+ @erase (done) -> spies['a/erase'](); done()
25
+ @fetch (done) -> spies['a/fetch'](); done()
26
+
27
+ class @B extends Joosy.Widget
28
+ @view """
29
+ <div id="subcontent"></div>
30
+ """
31
+
32
+ @paint (done) -> spies['b/paint'](); done()
33
+ @beforePaint (done) -> spies['b/beforePaint'](); done()
34
+ @erase (done) -> spies['b/erase'](); done()
35
+ @fetch (done) -> spies['b/fetch'](); done()
36
+
37
+ class @C extends Joosy.Widget
38
+ @paint (done) -> spies['c/paint'](); done()
39
+ @beforePaint (done) -> spies['c/beforePaint'](); done()
40
+ @erase (done) -> spies['c/erase'](); done()
41
+ @fetch (done) -> spies['c/fetch'](); done()
42
+
43
+ class @D extends Joosy.Widget
44
+ @paint (done) -> spies['d/paint'](); done()
45
+ @beforePaint (done) -> spies['d/beforePaint'](); done()
46
+ @erase (done) -> spies['d/erase'](); done()
47
+ @fetch (done) -> spies['d/fetch'](); done()
48
+
49
+ @a = new @A
50
+ @b = new @B
51
+ @c = new @C 'params', @b
52
+ @d = new @D
53
+
54
+ for instance in entries
55
+ sinon.spy @[instance], '__load'
56
+ sinon.spy @[instance], '__unload'
57
+
58
+ @nestingMap =
59
+ '#content':
60
+ instance: @b
61
+ nested:
62
+ '#subcontent': {instance: @d}
63
+
64
+ it 'calls paint callbacks', ->
65
+ @a.__bootstrap @nestingMap, @$ground
66
+
67
+ expect(@spies["a/paint"].callCount).toEqual 1
68
+ expect(@spies["b/paint"].callCount).toEqual 0
69
+ expect(@spies["c/paint"].callCount).toEqual 0
70
+ expect(@spies["a/beforePaint"].callCount).toEqual 1
71
+ expect(@spies["b/beforePaint"].callCount).toEqual 0
72
+ expect(@spies["c/beforePaint"].callCount).toEqual 0
73
+ expect(@spies['a/fetch'].callCount).toEqual 1
74
+ expect(@spies['b/fetch'].callCount).toEqual 1
75
+ expect(@spies['c/fetch'].callCount).toEqual 0
76
+ expect(@spies['a/erase'].callCount).toEqual 0
77
+ expect(@spies['b/erase'].callCount).toEqual 0
78
+ expect(@spies['c/erase'].callCount).toEqual 0
79
+
80
+ @c.__bootstrap {}, $('#content', @$ground)
81
+
82
+ ['paint', 'beforePaint'].each (filter) =>
83
+ expect(@spies["a/#{filter}"].callCount).toEqual 1
84
+ expect(@spies["b/#{filter}"].callCount).toEqual 0
85
+ expect(@spies["c/#{filter}"].callCount).toEqual 1
86
+
87
+ expect(@spies['a/fetch'].callCount).toEqual 1
88
+ expect(@spies['b/fetch'].callCount).toEqual 1
89
+ expect(@spies['c/fetch'].callCount).toEqual 1
90
+ expect(@spies['a/erase'].callCount).toEqual 0
91
+ expect(@spies['b/erase'].callCount).toEqual 1
92
+ expect(@spies['c/erase'].callCount).toEqual 0
93
+
94
+ it 'calls load/unload callbacks', ->
95
+ @a.__bootstrap @nestingMap, @$ground
96
+
97
+ expect(@a.__load.callCount).toEqual 1
98
+ expect(@b.__load.callCount).toEqual 1
99
+ expect(@c.__load.callCount).toEqual 0
100
+ expect(@d.__load.callCount).toEqual 1
101
+ expect(@a.__unload.callCount).toEqual 0
102
+ expect(@b.__unload.callCount).toEqual 0
103
+ expect(@c.__unload.callCount).toEqual 0
104
+ expect(@d.__unload.callCount).toEqual 0
105
+
106
+ @c.__bootstrap {}, $('#content', @$ground)
107
+
108
+ expect(@a.__load.callCount).toEqual 1
109
+ expect(@b.__load.callCount).toEqual 1
110
+ expect(@c.__load.callCount).toEqual 1
111
+ expect(@d.__load.callCount).toEqual 1
112
+ expect(@a.__unload.callCount).toEqual 0
113
+ expect(@b.__unload.callCount).toEqual 1
114
+ expect(@c.__unload.callCount).toEqual 0
115
+ expect(@d.__unload.callCount).toEqual 1
116
+
117
+ describe 'widgets manager', ->
118
+
119
+ @beforeEach ->
120
+
121
+ D = class @D extends Joosy.Widget
122
+ @view "D"
123
+
124
+ C = class @C extends Joosy.Widget
125
+ @view "C"
126
+
127
+ B = class @B extends Joosy.Widget
128
+ @view """
129
+ <div id="c"></div>
130
+ """
131
+
132
+ @mapWidgets
133
+ '#c': -> C
134
+
135
+ class @A extends Joosy.Widget
136
+ @view """
137
+ <div id="b"></div>
138
+ """
139
+
140
+ @mapWidgets
141
+ '#b': B
142
+
143
+ it 'bootstraps registered widgets', ->
144
+ (new @A).__bootstrapDefault @$ground
145
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c">C</div></div>'
146
+
147
+ it 'bootstraps registered independent widgets', ->
148
+ @C.fetch (complete) -> setTimeout complete, 0
149
+ @C.independent()
150
+
151
+ runs ->
152
+ (new @A).__bootstrapDefault @$ground
153
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c"></div></div>'
154
+
155
+ waits 0
156
+
157
+ runs ->
158
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c">C</div></div>'
159
+
160
+ it 'registeres widgets on the fly', ->
161
+ a = new @A
162
+ a.__bootstrapDefault @$ground
163
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c">C</div></div>'
164
+
165
+ a.registerWidget '#b', @D
166
+
167
+ expect(@$ground.html()).toEqualHTML '<div id="b">D</div>'
168
+
169
+ it 'replaces widget', ->
170
+ a = new @A
171
+ a.__bootstrapDefault @$ground
172
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c">C</div></div>'
173
+
174
+ d = a.registerWidget '#b', @D
175
+ sinon.spy d, '__unload'
176
+
177
+ a.replaceWidget d, @C
178
+ expect(@$ground.html()).toEqualHTML '<div id="b">C</div>'
179
+ expect(d.__unload.callCount).toEqual 1
180
+
181
+ describe 'synchronizer', ->
182
+
183
+ @beforeEach ->
184
+ class @A extends Joosy.Widget
185
+ @view """
186
+ <div id="b"></div>
187
+ """
188
+
189
+ class @B extends Joosy.Widget
190
+ @view """
191
+ <div id="c"></div>
192
+ <div id="d"></div>
193
+ """
194
+
195
+ class @C extends Joosy.Widget
196
+ @view """
197
+ <div id="e"></div>
198
+ <div id="f"></div>
199
+ """
200
+
201
+ class @D extends Joosy.Widget
202
+ @view "D"
203
+
204
+ class @E extends Joosy.Widget
205
+ @view "E"
206
+
207
+ class @F extends Joosy.Widget
208
+ @view "F"
209
+
210
+ ['a', 'b', 'c', 'd', 'e', 'f'].each (instance) =>
211
+ @[instance] = new @[instance.toUpperCase()] 'params'
212
+
213
+ @nestingMap =
214
+ '#b':
215
+ instance: @b
216
+ nested:
217
+ '#d': {instance: @d}
218
+ '#c':
219
+ instance: @c
220
+ nested:
221
+ '#e': {instance: @e}
222
+ '#f': {instance: @f}
223
+
224
+ describe 'fetcher', ->
225
+
226
+ it 'triggers when no nesting defined', ->
227
+ @f.__fetch(@nestingMap)
228
+ expect(@f.__triggeredEvents?['section:fetched']).toEqual true
229
+
230
+ it 'triggers whole dependency tree synchronously', ->
231
+ @a.__fetch(@nestingMap)
232
+ expect(@a.__triggeredEvents?['section:fetched']).toEqual true
233
+ expect(@b.__triggeredEvents?['section:fetched']).toEqual true
234
+ expect(@c.__triggeredEvents?['section:fetched']).toEqual true
235
+ expect(@d.__triggeredEvents?['section:fetched']).toEqual true
236
+ expect(@e.__triggeredEvents?['section:fetched']).toEqual true
237
+ expect(@f.__triggeredEvents?['section:fetched']).toEqual true
238
+
239
+ it 'triggers whole dependency tree asynchronously', ->
240
+ @F.fetch (complete) -> setTimeout complete, 0
241
+ @B.fetch (complete) -> setTimeout complete, 100
242
+
243
+ runs ->
244
+ @a.__fetch(@nestingMap)
245
+ expect(@a.__triggeredEvents?['section:fetched']).toBeUndefined()
246
+ expect(@b.__triggeredEvents?['section:fetched']).toBeUndefined()
247
+ expect(@c.__triggeredEvents?['section:fetched']).toBeUndefined()
248
+ expect(@d.__triggeredEvents?['section:fetched']).toEqual true
249
+ expect(@e.__triggeredEvents?['section:fetched']).toEqual true
250
+ expect(@f.__triggeredEvents?['section:fetched']).toBeUndefined()
251
+
252
+ waits 0
253
+
254
+ runs ->
255
+ expect(@a.__triggeredEvents?['section:fetched']).toBeUndefined()
256
+ expect(@b.__triggeredEvents?['section:fetched']).toBeUndefined()
257
+ expect(@c.__triggeredEvents?['section:fetched']).toEqual true
258
+ expect(@d.__triggeredEvents?['section:fetched']).toEqual true
259
+ expect(@e.__triggeredEvents?['section:fetched']).toEqual true
260
+ expect(@f.__triggeredEvents?['section:fetched']).toEqual true
261
+
262
+ waits 100
263
+
264
+ runs ->
265
+ expect(@a.__triggeredEvents?['section:fetched']).toEqual true
266
+ expect(@b.__triggeredEvents?['section:fetched']).toEqual true
267
+ expect(@c.__triggeredEvents?['section:fetched']).toEqual true
268
+ expect(@d.__triggeredEvents?['section:fetched']).toEqual true
269
+ expect(@e.__triggeredEvents?['section:fetched']).toEqual true
270
+ expect(@f.__triggeredEvents?['section:fetched']).toEqual true
271
+
272
+ it 'skips independent nestings within tree', ->
273
+ @C.fetch (complete) -> setTimeout complete, 0
274
+ @C.independent()
275
+
276
+ runs ->
277
+ @a.__fetch(@nestingMap)
278
+ expect(@a.__triggeredEvents?['section:fetched']).toEqual true
279
+ expect(@d.__triggeredEvents?['section:fetched']).toEqual true
280
+
281
+ describe 'bootstrap', ->
282
+
283
+ describe 'dependent', ->
284
+
285
+ it 'loads when no nesting defined', ->
286
+ @f.__bootstrap @nestingMap, @$ground
287
+ expect(@$ground.html()).toEqual 'F'
288
+
289
+ it 'loads whole dependency tree synchronously', ->
290
+ @a.__bootstrap @nestingMap, @$ground
291
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c"><div id="e">E</div><div id="f">F</div></div><div id="d">D</div></div>'
292
+
293
+ it 'loads whole dependency tree asynchronously', ->
294
+ @F.fetch (complete) -> setTimeout complete, 0
295
+ @B.fetch (complete) -> setTimeout complete, 100
296
+
297
+ runs ->
298
+ @a.__bootstrap @nestingMap, @$ground
299
+ expect(@$ground.html()).toEqualHTML ''
300
+
301
+ waits 0
302
+
303
+ runs ->
304
+ expect(@$ground.html()).toEqualHTML ''
305
+
306
+ waits 100
307
+
308
+ runs ->
309
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c"><div id="e">E</div><div id="f">F</div></div><div id="d">D</div></div>'
310
+
311
+ it 'skips independent nestings within tree', ->
312
+ @C.fetch (complete) -> setTimeout complete, 0
313
+ @C.independent()
314
+
315
+ @a.__bootstrap @nestingMap, @$ground
316
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c"></div><div id="d">D</div></div>'
317
+
318
+ describe 'independent', ->
319
+
320
+ it 'loads independent children synchronously if they managed to fetch', ->
321
+ @A.fetch (complete) -> setTimeout complete, 100
322
+
323
+ @C.fetch (complete) -> setTimeout complete, 0
324
+ @C.independent()
325
+
326
+ runs ->
327
+ @a.__bootstrap @nestingMap, @$ground
328
+
329
+ waits 100
330
+
331
+ runs ->
332
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c"><div id="e">E</div><div id="f">F</div></div><div id="d">D</div></div>'
333
+
334
+ it 'loads whole dependency tree', ->
335
+ @C.fetch (complete) -> setTimeout complete, 0
336
+ @C.independent()
337
+
338
+ @E.fetch (complete) -> setTimeout complete, 100
339
+ @E.independent()
340
+
341
+ runs ->
342
+ @a.__bootstrap @nestingMap, @$ground
343
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c"></div><div id="d">D</div></div>'
344
+
345
+ waits 0
346
+
347
+ runs ->
348
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c"><div id="e"></div><div id="f">F</div></div><div id="d">D</div></div>'
349
+
350
+ waits 100
351
+
352
+ runs ->
353
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c"><div id="e">E</div><div id="f">F</div></div><div id="d">D</div></div>'
354
+
355
+ describe 'mixed', ->
356
+
357
+ it 'loads whole dependency tree', ->
358
+ @B.fetch (complete) -> setTimeout complete, 0
359
+ @B.independent()
360
+
361
+ @E.fetch (complete) -> setTimeout complete, 100
362
+
363
+ runs ->
364
+ @a.__bootstrap @nestingMap, @$ground
365
+ expect(@$ground.html()).toEqualHTML '<div id="b"></div>'
366
+
367
+ waits 0
368
+
369
+ runs ->
370
+ expect(@$ground.html()).toEqualHTML '<div id="b"></div>'
371
+
372
+ waits 100
373
+
374
+ runs ->
375
+ expect(@$ground.html()).toEqualHTML '<div id="b"><div id="c"><div id="e">E</div><div id="f">F</div></div><div id="d">D</div></div>'
@@ -0,0 +1,38 @@
1
+ describe "Joosy", ->
2
+
3
+ it "loads", ->
4
+ result = false
5
+
6
+ runs ->
7
+ requirejs ['joosy'], (joosy) ->
8
+ result = true
9
+ expect(joosy.Application).toBeDefined()
10
+
11
+ waitsFor (-> result), 'Unable to download Joosy', 1000
12
+
13
+ it "allows for separate module inclusion", ->
14
+ result = false
15
+
16
+ runs ->
17
+ requirejs ['joosy/module'], (module) ->
18
+ result = true
19
+ expect(Object.isFunction module.hasAncestor).toBeTruthy()
20
+
21
+ waitsFor (-> result), 'Unable to download Joosy', 1000
22
+
23
+ it "registers internal components as modules", ->
24
+ expect(Object.keys(require.s.contexts._.registry).sortBy()).toEqual [
25
+ 'joosy/application',
26
+ 'joosy/layout',
27
+ 'joosy/modules/dom',
28
+ 'joosy/modules/events',
29
+ 'joosy/modules/filters',
30
+ 'joosy/modules/log',
31
+ 'joosy/modules/renderer',
32
+ 'joosy/modules/time_manager',
33
+ 'joosy/page',
34
+ 'joosy/resources/watcher',
35
+ 'joosy/router',
36
+ 'joosy/templaters/jst',
37
+ 'joosy/widget'
38
+ ]
@@ -0,0 +1,21 @@
1
+ describe "Joosy", ->
2
+
3
+ it "loads", ->
4
+ expect(Joosy).toBeDefined()
5
+
6
+ it "keeps environment clean", ->
7
+ result = false
8
+ ghetto = {}
9
+
10
+ runs ->
11
+ $.ajax
12
+ url: '../build/joosy.js'
13
+ dataType: 'text'
14
+ success: (script) ->
15
+ (new Function( "with(this) { " + script + "}")).call(ghetto)
16
+ result = true
17
+
18
+ waitsFor (-> result), 'Unable to download Joosy', 1000
19
+
20
+ runs ->
21
+ expect(Object.keys ghetto).toEqual ['Joosy', 'Metamorph']
@@ -54,7 +54,7 @@ describe "Joosy.Form", ->
54
54
 
55
55
  it "should properly act with options", ->
56
56
  formWithProperties = new Joosy.Form @nudeForm, invalidationClass: 'fluffy'
57
- expect(formWithProperties.container).toEqual @nudeForm
57
+ expect(formWithProperties.$container).toEqual @nudeForm
58
58
  expect(formWithProperties.invalidationClass).toEqual 'fluffy'
59
59
  expect(formWithProperties.$fields().length).toEqual 5
60
60
 
@@ -62,7 +62,7 @@ describe "Joosy.Form", ->
62
62
 
63
63
  it "should properly act with callback", ->
64
64
  formWithCallback = new Joosy.Form @putForm, callback=sinon.spy()
65
- expect(formWithCallback.container).toEqual @putForm
65
+ expect(formWithCallback.$container).toEqual @putForm
66
66
  expect(formWithCallback.invalidationClass).toEqual 'field_with_errors'
67
67
  expect(formWithCallback.success).toBe callback
68
68
  expect(formWithCallback.$fields().length).toEqual 2
@@ -107,15 +107,15 @@ describe "Joosy.Form", ->
107
107
  expect(@nudeForm.$fields()[3].checked).toEqual false
108
108
  expect(@nudeForm.$fields()[4].value).toEqual 'zxc'
109
109
  expect(@nudeForm.$fields()[4].checked).toEqual true
110
- expect(@nudeForm.container.attr('method').toLowerCase()).toEqual 'post'
111
- expect(@nudeForm.container.attr 'action').toEqual '/tests/1'
110
+ expect(@nudeForm.$container.attr('method').toLowerCase()).toEqual 'post'
111
+ expect(@nudeForm.$container.attr 'action').toEqual '/tests/1'
112
112
  expect(@nudeForm.__resource).toEqual @resource
113
113
 
114
114
  it "should fill form with camelized properties", ->
115
115
  @putForm.fill @resource
116
116
  expect(@putForm.$fields()[0].value).toEqual 'baz'
117
- expect(@putForm.container.attr('method').toLowerCase()).toEqual 'post'
118
- expect(@putForm.container.attr 'action').toEqual '/tests/1'
117
+ expect(@putForm.$container.attr('method').toLowerCase()).toEqual 'post'
118
+ expect(@putForm.$container.attr 'action').toEqual '/tests/1'
119
119
 
120
120
  it "should fill form with any properties", ->
121
121
  @exactForm.fill @resource
@@ -133,13 +133,13 @@ describe "Joosy.Form", ->
133
133
  action: @resource.memberPath(from: 'calculate')
134
134
  expect(@nudeForm.$fields()[0].value).toEqual 'foo'
135
135
  expect(@nudeForm.$fields()[1].value).toEqual 'bar'
136
- expect(@nudeForm.container.attr 'action').toEqual '/tests/1/calculate'
136
+ expect(@nudeForm.$container.attr 'action').toEqual '/tests/1/calculate'
137
137
 
138
138
  resource = @Test.build 'someId'
139
139
 
140
140
  @nudeForm.fill resource,
141
141
  action: resource.memberPath(from: 'calculate')
142
- expect(@nudeForm.container.attr 'action').toEqual '/tests/someId/calculate'
142
+ expect(@nudeForm.$container.attr 'action').toEqual '/tests/someId/calculate'
143
143
 
144
144
  it "should handle field name properly", ->
145
145
  expect(@nudeForm.concatFieldName 'resource', 'key').toEqual 'resource[key]'
@@ -189,14 +189,14 @@ describe "Joosy.Form", ->
189
189
  it 'should allow multiple submit', ->
190
190
  @nudeForm = new Joosy.Form @nudeForm
191
191
  3.times =>
192
- @nudeForm.container.submit()
192
+ @nudeForm.$container.submit()
193
193
  expect(@requests.length).toEqual 3
194
194
 
195
195
  it 'should optionally prevent multiple submit', ->
196
196
  @nudeForm = new Joosy.Form @nudeForm, debounce: true
197
197
  [200, 404, 500].each (code) =>
198
198
  3.times =>
199
- @nudeForm.container.submit()
199
+ @nudeForm.$container.submit()
200
200
  expect(@requests.length).toEqual 1
201
201
  @requests[0].respond(code, {}, '{}')
202
202
  expect(@requests.length).toEqual 1
@@ -205,21 +205,21 @@ describe "Joosy.Form", ->
205
205
  describe 'Global debouncing enabled', ->
206
206
 
207
207
  beforeEach ->
208
- Joosy.Application.debounceForms = true
208
+ Joosy.Form.debounceForms = true
209
209
 
210
210
  afterEach ->
211
- Joosy.Application.debounceForms = false
211
+ Joosy.Form.debounceForms = false
212
212
 
213
213
  it 'should optionally allow multiple submit', ->
214
214
  @nudeForm = new Joosy.Form @nudeForm, debounce: false
215
215
  3.times =>
216
- @nudeForm.container.submit()
216
+ @nudeForm.$container.submit()
217
217
  expect(@requests.length).toEqual 3
218
218
 
219
219
  it 'should prevent multiple submit', ->
220
220
  @nudeForm = new Joosy.Form @nudeForm
221
221
  3.times =>
222
- @nudeForm.container.submit()
222
+ @nudeForm.$container.submit()
223
223
  expect(@requests.length).toEqual 1
224
224
 
225
225
  describe "Callbacks", ->
@@ -227,7 +227,7 @@ describe "Joosy.Form", ->
227
227
  beforeEach ->
228
228
  @nudeForm = new Joosy.Form @nudeForm, @spy=sinon.spy()
229
229
  @nudeForm.fill @resource
230
- @nudeForm.container.submit()
230
+ @nudeForm.$container.submit()
231
231
  @target = @server.requests.last()
232
232
 
233
233
  it "should trigger 'success'", ->
@@ -260,7 +260,7 @@ describe "Joosy.Form", ->
260
260
  it "should clear fields before another submit", ->
261
261
  @target.respond 422, 'Content-Type': 'application/json', '{"foo": "error!"}'
262
262
  expect($(@nudeForm.$fields()[0]).attr 'class').toEqual 'field_with_errors'
263
- @nudeForm.container.submit()
263
+ @nudeForm.$container.submit()
264
264
  expect($(@nudeForm.$fields()[0]).attr 'class').toNotEqual 'field_with_errors'
265
265
 
266
266
  it "should trigger 'before' and do default action if it returns true", ->
@@ -268,7 +268,7 @@ describe "Joosy.Form", ->
268
268
  expect($(@nudeForm.$fields()[0]).attr 'class').toEqual 'field_with_errors'
269
269
  @nudeForm.before = sinon.spy ->
270
270
  true
271
- @nudeForm.container.submit()
271
+ @nudeForm.$container.submit()
272
272
  expect($(@nudeForm.$fields()[0]).attr 'class').toNotEqual 'field_with_errors'
273
273
  expect(@nudeForm.before.callCount).toEqual 1
274
274
 
@@ -277,7 +277,7 @@ describe "Joosy.Form", ->
277
277
  expect($(@nudeForm.$fields()[0]).attr 'class').toEqual 'field_with_errors'
278
278
  @nudeForm.before = sinon.spy ->
279
279
  false
280
- @nudeForm.container.submit()
280
+ @nudeForm.$container.submit()
281
281
  expect($(@nudeForm.$fields()[0]).attr 'class').toEqual 'field_with_errors'
282
282
  expect(@nudeForm.before.callCount).toEqual 1
283
283
 
@@ -47,7 +47,7 @@ describe "Joosy.Helpers.Form", ->
47
47
 
48
48
  it "renders formFor", ->
49
49
  callback = sinon.spy()
50
- expect(h.formFor resource, callback).toMatch /<form id=".*"><\/form>/
50
+ expect(h.formFor resource, callback).toBeTag 'form', '', id: /.*/
51
51
  expect(callback.callCount).toEqual 1
52
52
  expect(callback.args[0][0].label?).toBeTruthy()
53
53
 
@@ -51,21 +51,33 @@ describe "Joosy.Resources.Base", ->
51
51
  @resource 'another.deep.value', 'banana strikes back'
52
52
  expect(@resource 'another.deep').toEqual value: 'banana strikes back'
53
53
 
54
- it "handles @at", ->
55
- class Fluffy extends Joosy.Resources.Base
56
- @entity 'fluffy'
54
+ describe '@at', ->
55
+ # clone won't be instanceof Fluffy in IE
56
+ #expect(clone.build({}) instanceof Fluffy).toBeTruthy()
57
57
 
58
- clone = Fluffy.at('rumbas!')
58
+ beforeEach ->
59
+ class @Fluffy extends Joosy.Resources.Base
60
+ @entity 'fluffy'
59
61
 
60
- expect(clone.__source).toEqual 'rumbas!'
61
- expect(Joosy.Module.hasAncestor clone, Fluffy).toBeTruthy()
62
+ it 'returns base class child', ->
63
+ clone = @Fluffy.at 'rumbas'
64
+ expect(Joosy.Module.hasAncestor clone, @Fluffy).toBeTruthy()
62
65
 
63
- clone = Fluffy.at Test.build(1)
66
+ it 'accepts string', ->
67
+ clone = @Fluffy.at 'rumbas'
68
+ expect(clone.__source).toEqual '/rumbas'
64
69
 
65
- expect(clone.__source).toEqual '/tests/1/fluffies'
66
- expect(Joosy.Module.hasAncestor clone, Fluffy).toBeTruthy()
67
- # clone won't be instanceof Fluffy in IE
68
- #expect(clone.build({}) instanceof Fluffy).toBeTruthy()
70
+ it 'accepts another resource instance', ->
71
+ clone = @Fluffy.at Test.build(1)
72
+ expect(clone.__source).toEqual '/tests/1/fluffies'
73
+
74
+ it 'accepts array', ->
75
+ clone = @Fluffy.at ['rumbas', Test.build(1), 'salsas']
76
+ expect(clone.__source).toEqual '/rumbas/tests/1/salsas'
77
+
78
+ it 'accepts sequential attributes', ->
79
+ clone = @Fluffy.at 'rumbas', 'salsas', Test.build(1)
80
+ expect(clone.__source).toEqual '/rumbas/salsas/tests/1/fluffies'
69
81
 
70
82
  it "triggers 'changed' right", ->
71
83
  callback = sinon.spy()