joosy 1.2.0.alpha.38 → 1.2.0.alpha.41

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gruntfile.coffee +15 -7
  3. data/bower.json +4 -3
  4. data/lib/extensions/resources.js +11 -3
  5. data/lib/joosy.js +235 -300
  6. data/package.json +3 -3
  7. data/spec/helpers/ground.coffee +33 -0
  8. data/spec/helpers/matchers.coffee +65 -0
  9. data/spec/joosy/core/application_spec.coffee +8 -8
  10. data/spec/joosy/core/helpers/view_spec.coffee +9 -5
  11. data/spec/joosy/core/helpers/widgets_spec.coffee +43 -10
  12. data/spec/joosy/core/joosy_spec.coffee +42 -50
  13. data/spec/joosy/core/layout_spec.coffee +30 -34
  14. data/spec/joosy/core/modules/container_spec.coffee +79 -76
  15. data/spec/joosy/core/modules/events_spec.coffee +148 -81
  16. data/spec/joosy/core/modules/filters_spec.coffee +68 -49
  17. data/spec/joosy/core/modules/log_spec.coffee +13 -5
  18. data/spec/joosy/core/modules/module_spec.coffee +24 -14
  19. data/spec/joosy/core/modules/renderer_spec.coffee +95 -89
  20. data/spec/joosy/core/modules/time_manager_spec.coffee +11 -16
  21. data/spec/joosy/core/modules/widget_manager_spec.coffee +89 -71
  22. data/spec/joosy/core/page_spec.coffee +201 -137
  23. data/spec/joosy/core/templaters/jst_spec.coffee +62 -0
  24. data/spec/joosy/core/widget_spec.coffee +25 -29
  25. data/spec/joosy/extensions/form/form_spec.coffee +3 -1
  26. data/spec/joosy/extensions/resources/base_spec.coffee +3 -0
  27. data/spec/joosy/extensions/resources/collection_spec.coffee +3 -0
  28. data/spec/joosy/extensions/resources/rest_collection_spec.coffee +3 -0
  29. data/spec/joosy/extensions/resources/rest_spec.coffee +3 -0
  30. data/src/joosy/core/application.coffee +1 -7
  31. data/src/joosy/core/helpers/view.coffee +12 -0
  32. data/src/joosy/core/helpers/widgets.coffee +19 -9
  33. data/src/joosy/core/joosy.coffee +0 -23
  34. data/src/joosy/core/layout.coffee +7 -5
  35. data/src/joosy/core/module.coffee +24 -4
  36. data/src/joosy/core/modules/container.coffee +29 -28
  37. data/src/joosy/core/modules/events.coffee +85 -72
  38. data/src/joosy/core/modules/filters.coffee +3 -1
  39. data/src/joosy/core/modules/renderer.coffee +91 -74
  40. data/src/joosy/core/modules/widgets_manager.coffee +12 -9
  41. data/src/joosy/core/page.coffee +7 -14
  42. data/src/joosy/core/templaters/{rails_jst.coffee → jst.coffee} +21 -19
  43. data/src/joosy/core/widget.coffee +3 -3
  44. data/src/joosy/extensions/resources/base.coffee +8 -3
  45. data/src/joosy/extensions/resources/rest.coffee +8 -0
  46. data/src/joosy/extensions/resources/rest_collection.coffee +1 -0
  47. data/tasks/joosy.coffee +46 -17
  48. data/templates/application/base/pages/welcome/index.coffee +5 -5
  49. data/templates/application/base/templates/layouts/application.jst.hamlc +2 -2
  50. data/templates/application/base/templates/pages/welcome/index.jst.hamlc +2 -2
  51. data/templates/application/standalone/Gruntfile.coffee +3 -1
  52. metadata +6 -5
  53. data/spec/helpers/helper.coffee +0 -68
  54. data/spec/joosy/core/templaters/rails_jst_spec.coffee +0 -25
@@ -1,178 +1,242 @@
1
1
  describe "Joosy.Page", ->
2
2
 
3
- beforeEach ->
4
- window.JST = 'app/templates/layouts/default': (->)
5
- class window.ApplicationLayout extends Joosy.Layout
6
- class @TestPage extends Joosy.Page
3
+ describe "manager", ->
7
4
 
5
+ beforeEach ->
6
+ @Layout = class Layout extends Joosy.Layout
8
7
 
9
- describe "not rendered page", ->
8
+ class @Page extends Joosy.Page
9
+ @layout Layout
10
10
 
11
- beforeEach ->
12
- sinon.stub @TestPage.prototype, '__bootstrap'
13
- sinon.stub @TestPage.prototype, '__bootstrapLayout'
14
- @box = new @TestPage()
15
- expect(@TestPage::__bootstrap.callCount).toEqual 0
16
- expect(@TestPage::__bootstrapLayout.callCount).toEqual 1
17
-
18
-
19
- it "should have appropriate accessors", ->
20
- callback_names = ['beforePaint', 'paint', 'afterPaint', 'erase']
21
- callback_names.each (func) =>
22
- @TestPage[func] 'callback'
23
- expect(@TestPage::['__' + func]).toEqual 'callback'
24
-
25
- @TestPage.scroll '#here'
26
- expect(@TestPage::__scrollElement).toEqual '#here'
27
- expect(@TestPage::__scrollSpeed).toEqual 500
28
- expect(@TestPage::__scrollMargin).toEqual 0
29
-
30
- @TestPage.scroll '#there', speed: 1000, margin: -5
31
- expect(@TestPage::__scrollElement).toEqual '#there'
32
- expect(@TestPage::__scrollSpeed).toEqual 1000
33
- expect(@TestPage::__scrollMargin).toEqual -5
34
-
35
- @TestPage.layout 'test'
36
- expect(@TestPage::__layoutClass).toEqual 'test'
37
-
38
- it "should not render layout if it not changes", ->
39
- @box.layout = new ApplicationLayout()
40
- @box.layout.yield()
41
- new @TestPage {}, @box
42
- expect(@TestPage::__bootstrap.callCount).toEqual 1
43
- expect(@TestPage::__bootstrapLayout.callCount).toEqual 1
44
-
45
- it "should render layout if it changes", ->
46
- class SubLayout extends Joosy.Layout
47
- @box = new @TestPage()
48
- new @TestPage {}, @box
49
- expect(@TestPage::__bootstrap.callCount).toEqual 0
50
- expect(@TestPage::__bootstrapLayout.callCount).toEqual 3
51
-
52
- it "should stop render on beforeFilter result", ->
53
- sinon.stub @TestPage.prototype, '__runBeforeLoads'
54
- @TestPage::__runBeforeLoads.returns(false)
55
- new @TestPage()
56
- expect(@TestPage::__bootstrap.callCount).toEqual 0
57
- expect(@TestPage::__bootstrapLayout.callCount).toEqual 1
58
-
59
- it "should use Router", ->
11
+ sinon.stub @Page.prototype, '__bootstrap'
12
+ sinon.stub @Page.prototype, '__bootstrapLayout'
13
+
14
+ afterEach ->
15
+ @Page::__bootstrap.restore()
16
+ @Page::__bootstrapLayout.restore()
17
+
18
+ it "has appropriate accessors", ->
19
+ callbackNames = ['beforePaint', 'paint', 'afterPaint', 'erase']
20
+ callbackNames.each (callbackName) =>
21
+ @Page[callbackName] 'callback'
22
+ expect(@Page::['__' + callbackName]).toEqual 'callback'
23
+
24
+ @Page.scroll '#here'
25
+ expect(@Page::__scrollElement).toEqual '#here'
26
+ expect(@Page::__scrollSpeed).toEqual 500
27
+ expect(@Page::__scrollMargin).toEqual 0
28
+
29
+ @Page.scroll '#there', speed: 1000, margin: -5
30
+ expect(@Page::__scrollElement).toEqual '#there'
31
+ expect(@Page::__scrollSpeed).toEqual 1000
32
+ expect(@Page::__scrollMargin).toEqual -5
33
+
34
+ @Page.layout 'test'
35
+ expect(@Page::__layoutClass).toEqual 'test'
36
+
37
+ it "integrates with Router", ->
60
38
  target = sinon.stub Joosy.Router, 'navigate'
61
- @box.navigate 'there'
39
+ (new @Page).navigate 'there'
62
40
  expect(target.callCount).toEqual 1
63
41
  expect(target.alwaysCalledWithExactly 'there').toBeTruthy()
64
42
  Joosy.Router.navigate.restore()
65
43
 
66
- it "should load itself", ->
44
+ it "respects beforeFilters cancelation", ->
45
+ sinon.stub @Page.prototype, '__runBeforeLoads'
46
+ @Page::__runBeforeLoads.returns(false)
47
+
48
+ new @Page
49
+
50
+ expect(@Page::__bootstrap.callCount).toEqual 0
51
+ expect(@Page::__bootstrapLayout.callCount).toEqual 0
52
+
53
+ describe "layout switcher", ->
54
+
55
+ beforeEach ->
56
+ @page = new @Page
57
+ @page.layout = new @Layout
58
+
59
+ it "does not render when previous layout is the same", ->
60
+ new @Page {}, @page
61
+
62
+ expect(@Page::__bootstrap.callCount).toEqual 1
63
+ expect(@Page::__bootstrapLayout.callCount).toEqual 1
64
+
65
+ it "renders when previous layout is another class", ->
66
+ class Layout extends Joosy.Layout
67
+ class Page extends Joosy.Page
68
+ @layout Layout
69
+
70
+ sinon.stub Page.prototype, '__bootstrap'
71
+ sinon.stub Page.prototype, '__bootstrapLayout'
72
+
73
+ new Page {}, @page
74
+
75
+ expect(@Page::__bootstrap.callCount).toEqual 0
76
+ expect(@Page::__bootstrapLayout.callCount).toEqual 1
77
+ expect(Page::__bootstrap.callCount).toEqual 0
78
+ expect(Page::__bootstrapLayout.callCount).toEqual 1
79
+
80
+ it "loads", ->
81
+ page = new @Page
82
+
67
83
  spies = []
68
- spies.push sinon.spy(@box, '__assignElements')
69
- spies.push sinon.spy(@box, '__delegateEvents')
70
- spies.push sinon.spy(@box, '__setupWidgets')
71
- spies.push sinon.spy(@box, '__runAfterLoads')
72
- @box.__load()
84
+ spies.push sinon.spy(page, '__assignElements')
85
+ spies.push sinon.spy(page, '__delegateEvents')
86
+ spies.push sinon.spy(page, '__setupWidgets')
87
+ spies.push sinon.spy(page, '__runAfterLoads')
88
+ page.__load()
73
89
  expect(spies).toBeSequenced()
74
90
 
75
- it "should unload itself", ->
91
+ it "unloads", ->
92
+ page = new @Page
93
+
76
94
  spies = []
77
- spies.push sinon.spy(@box, '__clearTime')
78
- spies.push sinon.spy(@box, '__unloadWidgets')
79
- spies.push sinon.spy(@box, '__removeMetamorphs')
80
- spies.push sinon.spy(@box, '__runAfterUnloads')
81
- @box.__unload()
95
+ spies.push sinon.spy(page, '__clearTime')
96
+ spies.push sinon.spy(page, '__unloadWidgets')
97
+ spies.push sinon.spy(page, '__removeMetamorphs')
98
+ spies.push sinon.spy(page, '__runAfterUnloads')
99
+ page.__unload()
82
100
  expect(spies).toBeSequenced()
83
101
 
84
- describe "rendered page", ->
102
+ describe "rendering", ->
85
103
 
86
- beforeEach ->
87
- @box.previous = new @TestPage()
88
- @box.previous.layout = new @box.previous.__layoutClass
89
- @box.__renderer = sinon.spy()
90
- @box.__layoutClass.prototype.__renderer = sinon.spy()
91
- @TestPage::__bootstrap.restore()
92
- @TestPage::__bootstrapLayout.restore()
104
+ beforeEach ->
105
+ # Layouts inject themselves into `Joosy.Application.content`
106
+ # so let's make them inject where we want
107
+ sinon.stub Joosy.Application, 'content'
108
+ Joosy.Application.content.returns @$ground
93
109
 
110
+ # We test every module separately so there's no need to run all those
111
+ sinon.stub Joosy.Page.prototype, '__load'
112
+ sinon.stub Joosy.Page.prototype, '__unload'
113
+ sinon.stub Joosy.Layout.prototype, '__load'
114
+ sinon.stub Joosy.Layout.prototype, '__unload'
94
115
 
95
- it "should wait stageClear and dataReceived event to start render", ->
96
- spies = []
116
+ afterEach ->
117
+ Joosy.Application.content.restore()
118
+ Joosy.Page::__load.restore()
119
+ Joosy.Page::__unload.restore()
120
+ Joosy.Layout::__load.restore()
121
+ Joosy.Layout::__unload.restore()
97
122
 
98
- spies.push @box.previous.__erase = sinon.spy (stage, callback) ->
99
- expect(stage.selector).toEqual @layout.content().selector
100
- callback()
123
+ it "renders", ->
124
+ class Layout extends Joosy.Layout
125
+ @view (locals) -> locals.page 'div', class: 'layout'
101
126
 
102
- spies.push sinon.spy(@box.previous, '__unload')
127
+ class Page extends Joosy.Page
128
+ @layout Layout
129
+ @view (locals) -> 'page'
103
130
 
104
- spies.push @box.__beforePaint = sinon.spy (stage, callback) ->
105
- expect(stage.selector).toEqual @layout.content().selector
106
- expect(@__oneShotEvents[0][0]).toEqual ['stageClear', 'dataReceived']
107
- callback()
108
- expect(@__oneShotEvents[0][0]).toEqual ['dataReceived']
131
+ page = new Page
132
+ expect(@$ground.html()).toMatch /<div class\=\"layout\" id=\"__joosy\d+\">page<\/div>/
109
133
 
110
- spies.push @box.__fetch = sinon.spy (callback) ->
111
- expect(@__oneShotEvents[0][0]).toEqual ['dataReceived']
112
- callback()
113
- expect(@__oneShotEvents).toEqual {}
134
+ it "changes page", ->
135
+ class Layout extends Joosy.Layout
136
+ @view (locals) -> locals.page 'div'
114
137
 
115
- spies.push @box.__paint = sinon.spy (stage, callback) ->
116
- expect(stage.selector).toEqual @layout.content().selector
117
- expect(typeof callback).toEqual 'function'
118
- # callback() - start rendering
138
+ class PageA extends Joosy.Page
139
+ @layout Layout
140
+ @view (locals) -> 'page a'
119
141
 
120
- @box.__bootstrap()
142
+ class PageB extends Joosy.Page
143
+ @layout Layout
144
+ @view (locals) -> 'page b'
121
145
 
122
- expect(spies).toBeSequenced()
146
+ page = new PageA
147
+ expect(@$ground.html()).toMatch /<div id=\"__joosy\d+\">page a<\/div>/
123
148
 
124
- it "should render page", ->
125
- spies = []
149
+ page = new PageB {}, page
150
+ expect(@$ground.html()).toMatch /<div id=\"__joosy\d+\">page b<\/div>/
126
151
 
127
- spies.push @box.__renderer
128
- spies.push sinon.spy(@box, 'swapContainer')
129
- spies.push sinon.spy(@box, '__load')
152
+ it "changes layout", ->
153
+ class LayoutA extends Joosy.Layout
154
+ @view (locals) -> locals.page 'div'
130
155
 
131
- @box.__bootstrap()
132
- expect(spies).toBeSequenced()
156
+ class PageA extends Joosy.Page
157
+ @layout LayoutA
158
+ @view (locals) -> ''
133
159
 
134
- it "should wait stageClear and dataReceived event to start layout render", ->
135
- spies = []
160
+ class LayoutB extends Joosy.Layout
161
+ @view (locals) -> locals.page 'div'
136
162
 
137
- spies.push ApplicationLayout::__erase = sinon.spy (stage, page, callback) ->
138
- expect(stage.selector).toEqual Joosy.Application.content().selector
139
- callback()
163
+ class PageB extends Joosy.Page
164
+ @layout LayoutB
165
+ @view (locals) -> ''
140
166
 
141
- spies.push sinon.spy(@box.previous.layout, '__unload')
142
- spies.push sinon.spy(@box.previous, '__unload')
167
+ page = new PageA
168
+ html = @$ground.html()
169
+ expect(html).toMatch /<div id=\"__joosy\d+\"><\/div>/
143
170
 
144
- spies.push ApplicationLayout::__beforePaint = sinon.spy (stage, page, callback) =>
145
- expect(stage.selector).toEqual Joosy.Application.content().selector
146
- expect(@box.__oneShotEvents[0][0]).toEqual ['stageClear', 'dataReceived']
147
- callback()
148
- expect(@box.__oneShotEvents[0][0]).toEqual ['dataReceived']
171
+ page = new PageB {}, page
172
+ expect(@$ground.html()).toMatch /<div id=\"__joosy\d+\"><\/div>/
173
+ expect(@$ground.html()).not.toEqual html
149
174
 
150
- spies.push @box.__fetch = sinon.spy (callback) ->
151
- expect(@__oneShotEvents[0][0]).toEqual ['dataReceived']
152
- callback()
153
- expect(@__oneShotEvents).toEqual {}
175
+ it "proxies @params to layout", ->
176
+ class Layout extends Joosy.Layout
177
+ @view (locals) -> locals.page 'div', class: 'layout'
154
178
 
155
- spies.push ApplicationLayout::__paint = sinon.spy (stage, page, callback) ->
156
- expect(stage.selector).toEqual Joosy.Application.content().selector
157
- expect(typeof callback).toEqual 'function'
158
- # callback() - start rendering
179
+ constructor: (@params) ->
180
+ expect(@params).toEqual foo: 'bar'
181
+ super
159
182
 
160
- @box.__bootstrapLayout()
183
+ class Page extends Joosy.Page
184
+ @layout Layout
185
+ @view (locals) -> 'page'
161
186
 
162
- expect(spies).toBeSequenced()
187
+ page = new Page foo: 'bar'
163
188
 
164
- it "should render layout and page", ->
165
- spies = []
189
+ it "passes @data to @view", ->
190
+ class Layout extends Joosy.Layout
191
+ @fetch (complete) ->
192
+ expect(@data).toEqual {}
193
+ @data.foo = 'bar'
194
+ complete()
166
195
 
167
- @box.params = {tested: true}
196
+ @view (locals) ->
197
+ expect(locals.foo).toEqual 'bar'
168
198
 
169
- spies.push @box.__layoutClass.prototype.__renderer
170
- spies.push @box.__renderer
171
- swapContainer = sinon.spy(@box, 'swapContainer')
172
- spies.push @box.__layoutClass.prototype.__load = sinon.spy()
173
- spies.push sinon.spy(@box, '__load')
199
+ class Page extends Joosy.Page
200
+ @layout Layout
201
+
202
+ @fetch (complete) ->
203
+ expect(@data).toEqual {}
204
+ @data.foo = 'bar'
205
+ complete()
206
+
207
+ @view (locals) ->
208
+ expect(locals.foo).toEqual 'bar'
209
+
210
+ page = new Page
211
+
212
+ it "hooks", ->
213
+ spies = []
214
+ 11.times -> spies.push sinon.spy()
174
215
 
175
- @box.__bootstrapLayout()
176
- expect(spies).toBeSequenced()
177
- expect(swapContainer.callCount).toEqual 2
178
- expect(@box.layout.params).toEqual {tested: true}
216
+ class Layout extends Joosy.Layout
217
+ @beforePaint (container, page, complete) -> spies[0](); complete()
218
+ @fetch (complete) -> spies[1](); complete()
219
+ @paint (container, page, complete) -> spies[3](); complete()
220
+
221
+ @view spies[4]
222
+
223
+ class PageA extends Joosy.Page
224
+ @layout Layout
225
+
226
+ @fetch (complete) -> spies[2](); complete()
227
+ @erase (container, complete) -> spies[6](); complete()
228
+ @view spies[5]
229
+
230
+ class PageB extends Joosy.Page
231
+ @layout Layout
232
+
233
+ @beforePaint (container, complete) -> spies[7](); complete()
234
+ @fetch (complete) -> spies[8](); complete()
235
+ @paint (container, complete) -> spies[9](); complete()
236
+
237
+ @view spies[10]
238
+
239
+ page = new PageA
240
+ page = new PageB {}, page
241
+
242
+ expect(spies).toBeSequenced()
@@ -0,0 +1,62 @@
1
+ describe "Joosy.Templaters.JST", ->
2
+
3
+ describe "builder", ->
4
+
5
+ beforeEach ->
6
+ window.JST = {}
7
+ window.I18n = {locale: 'en'}
8
+
9
+ afterEach ->
10
+ delete window.JST
11
+ delete window.I18n
12
+
13
+ describe "with empty application name", ->
14
+
15
+ beforeEach ->
16
+ @templater = new Joosy.Templaters.JST
17
+
18
+ it "resolves plain template", ->
19
+ JST['templates/test'] = 'template'
20
+ expect(@templater.buildView('test')).toEqual 'template'
21
+
22
+ it "preffers localized template", ->
23
+ JST['templates/test'] = 'error'
24
+ JST['templates/test-en'] = 'template'
25
+ expect(@templater.buildView('test')).toEqual 'template'
26
+
27
+ describe "with set application name", ->
28
+
29
+ beforeEach ->
30
+ @templater = new Joosy.Templaters.JST('application')
31
+
32
+ it "resolves plain template", ->
33
+ JST['application/templates/test'] = 'template'
34
+ expect(@templater.buildView('test')).toEqual 'template'
35
+
36
+ it "preffers localized template", ->
37
+ JST['application/templates/test'] = 'error'
38
+ JST['application/templates/test-en'] = 'template'
39
+ expect(@templater.buildView('test')).toEqual 'template'
40
+
41
+ it "resolves templates correctly", ->
42
+ templater = new Joosy.Templaters.JST
43
+
44
+ class Klass extends Joosy.Module
45
+
46
+ Joosy.namespace 'British.Cities', ->
47
+ class @Klass extends Joosy.Module
48
+
49
+ expect(templater.resolveTemplate(undefined, "/absolute", undefined)).
50
+ toEqual "absolute"
51
+
52
+ expect(templater.resolveTemplate('widgets', 'fuga', {})).
53
+ toEqual 'widgets/fuga'
54
+
55
+ expect(templater.resolveTemplate('widgets', 'fuga', new Klass)).
56
+ toEqual 'widgets/fuga'
57
+
58
+ expect(templater.resolveTemplate('widgets', 'fuga', new British.Cities.Klass)).
59
+ toEqual 'widgets/british/cities/fuga'
60
+
61
+ expect(templater.resolveTemplate('widgets', 'hoge/fuga', new British.Cities.Klass)).
62
+ toEqual 'widgets/british/cities/hoge/fuga'
@@ -1,40 +1,36 @@
1
1
  describe "Joosy.Widget", ->
2
2
 
3
3
  beforeEach ->
4
- class @TestWidget extends Joosy.Widget
5
- @box = new @TestWidget()
4
+ class @Widget extends Joosy.Widget
5
+ @widget = new @Widget
6
6
 
7
- it "should have appropriate accessors", ->
8
- test = ->
9
- @TestWidget.view test
10
- expect(@TestWidget::__renderer).toEqual test
11
- @TestWidget.view 'test'
12
- expect(@TestWidget::__renderer instanceof Function).toBeTruthy()
13
-
14
- it "should use Router", ->
7
+ it "integrates with Router", ->
15
8
  target = sinon.stub Joosy.Router, 'navigate'
16
- @box.navigate 'there'
9
+ @widget.navigate 'there'
17
10
  expect(target.callCount).toEqual 1
18
11
  expect(target.alwaysCalledWithExactly 'there').toBeTruthy()
19
12
  Joosy.Router.navigate.restore()
20
13
 
21
- it "should load itself", ->
22
- @box.data = {tested: true}
23
- spies = [sinon.spy()]
24
- @TestWidget.view spies[0]
25
- @parent = new Joosy.Layout()
26
- spies.push sinon.spy(@box, '__assignElements')
27
- spies.push sinon.spy(@box, '__delegateEvents')
28
- spies.push sinon.spy(@box, '__runAfterLoads')
29
- target = @box.__load @parent, @ground
30
- expect(target).toBe @box
31
- expect(@box.__renderer.getCall(0).calledOn()).toBeFalsy()
32
- expect(@box.__renderer.getCall(0).args[0]).toEqual {tested: true}
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
33
30
  expect(spies).toBeSequenced()
34
31
 
35
- it "should unload itself", ->
36
- sinon.spy @box, '__runAfterUnloads'
37
- @box.__unload()
38
- target = @box.__runAfterUnloads
39
- expect(target.callCount).toEqual 1
40
- expect(target.getCall(0).calledOn()).toBeFalsy()
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()
@@ -1,6 +1,8 @@
1
1
  describe "Joosy.Form", ->
2
2
 
3
3
  beforeEach ->
4
+ Joosy.Resources.Base?.resetIdentity()
5
+
4
6
  @server = sinon.fakeServer.create()
5
7
  @seedGround()
6
8
  @nudeForm = "<form id='nude'><input name='test[foo]'/><input name='test[bar]'/><input name='test[bool]' type='checkbox' value='1'/><input name='test[set]' type='radio' value='qwe' /><input name='test[set]' type='radio' value='zxc' /></form>"
@@ -10,7 +12,7 @@ describe "Joosy.Form", ->
10
12
  @exactForm = "<form id='exact'><input name='test[EXact][MATCH]'/></form>"
11
13
  @arrayForm = "<form id='array'><input name='test[arr][1][0][1]'/></form>"
12
14
 
13
- @ground.find('#sidebar').after(@nudeForm).after(@putForm).after(@moreForm).after(@nestedForm).after(@exactForm).after(@arrayForm)
15
+ @$ground.find('#sidebar').after(@nudeForm).after(@putForm).after(@moreForm).after(@nestedForm).after(@exactForm).after(@arrayForm)
14
16
 
15
17
  @nudeForm = $('#nude')
16
18
  @putForm = $('#put')
@@ -1,5 +1,8 @@
1
1
  describe "Joosy.Resources.Base", ->
2
2
 
3
+ beforeEach ->
4
+ Joosy.Resources.Base?.resetIdentity()
5
+
3
6
  class TestInline extends Joosy.Resources.Base
4
7
  @entity 'test_inline'
5
8
 
@@ -1,5 +1,8 @@
1
1
  describe "Joosy.Resources.Collection", ->
2
2
 
3
+ beforeEach ->
4
+ Joosy.Resources.Base?.resetIdentity()
5
+
3
6
  class Test extends Joosy.Resources.Base
4
7
  @entity 'test'
5
8
 
@@ -1,5 +1,8 @@
1
1
  describe "Joosy.Resources.RESTCollection", ->
2
2
 
3
+ beforeEach ->
4
+ Joosy.Resources.Base?.resetIdentity()
5
+
3
6
  class Test extends Joosy.Resources.REST
4
7
  @entity 'test'
5
8
 
@@ -1,5 +1,8 @@
1
1
  describe "Joosy.Resources.REST", ->
2
2
 
3
+ beforeEach ->
4
+ Joosy.Resources.Base?.resetIdentity()
5
+
3
6
  class FluffyInline extends Joosy.Resources.REST
4
7
  @entity 'fluffy_inline'
5
8
 
@@ -31,7 +31,7 @@ Joosy.Application =
31
31
  @mergeConfig(window.JoosyEnvironment) if window.JoosyEnvironment?
32
32
  @mergeConfig(options)
33
33
 
34
- @templater = new Joosy.Templaters.RailsJST @name
34
+ @templater = new Joosy.Templaters.JST @name
35
35
 
36
36
  Joosy.Router.__setupRoutes()
37
37
 
@@ -41,12 +41,6 @@ Joosy.Application =
41
41
  content: ->
42
42
  $(@selector)
43
43
 
44
- #
45
- # Gets current application sandbox node
46
- #
47
- sandbox: ->
48
- $(@sandboxSelector)
49
-
50
44
  #
51
45
  # Switches to given page
52
46
  #
@@ -5,6 +5,18 @@
5
5
  #
6
6
  Joosy.helpers 'Application', ->
7
7
 
8
+ #
9
+ # Generates HTML tag string
10
+ #
11
+ # @param [String] name Tag name
12
+ # @param [Object] options Tag attributes
13
+ # @param [String] content String content to inject
14
+ # @param [Function] content Function that will be evaluated and the result will be taken as a content
15
+ #
16
+ # Example
17
+ # != @tag 'div', {class: 'foo'}, =>
18
+ # != @tag 'hr'
19
+ #
8
20
  @tag = (name, options={}, content='') ->
9
21
  content = content() if Object.isFunction(content)
10
22
 
@@ -5,15 +5,25 @@
5
5
  #
6
6
  Joosy.helpers 'Application', ->
7
7
 
8
- @widget = (element, widget) ->
9
- uuid = Joosy.uuid()
10
- params = id: uuid
11
- parts = element.split '.'
12
- if parts[1]
13
- params.class = parts.from(1).join ' '
8
+ #
9
+ # Injects widget
10
+ #
11
+ # @param [String] tag Tag name to use a widget container
12
+ # @param [Object] options Tag attributes
13
+ # @param [Joosy.Widget] widget Class or instance of {Joosy.Widget} to register
14
+ # @param [Function] widget Function returning class or instance of {Joosy.Widget}
15
+ #
16
+ # @note Widget instance will be generated on the next asynchronous tick
17
+ # so make sure to append resulting string to DOM synchronously
18
+ #
19
+ @widget = (tag, options, widget) ->
20
+ unless widget?
21
+ widget = options
22
+ options = {}
14
23
 
15
- element = @tag parts[0], params
24
+ options.id = Joosy.uid()
16
25
 
17
- @onRefresh -> @registerWidget '#'+uuid, widget
26
+ @__renderer.setTimeout 0, =>
27
+ @__renderer.registerWidget($('#'+options.id), widget)
18
28
 
19
- element
29
+ @tag tag, options