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.
- checksums.yaml +4 -4
- data/Gruntfile.coffee +15 -7
- data/bower.json +4 -3
- data/lib/extensions/resources.js +11 -3
- data/lib/joosy.js +235 -300
- data/package.json +3 -3
- data/spec/helpers/ground.coffee +33 -0
- data/spec/helpers/matchers.coffee +65 -0
- data/spec/joosy/core/application_spec.coffee +8 -8
- data/spec/joosy/core/helpers/view_spec.coffee +9 -5
- data/spec/joosy/core/helpers/widgets_spec.coffee +43 -10
- data/spec/joosy/core/joosy_spec.coffee +42 -50
- data/spec/joosy/core/layout_spec.coffee +30 -34
- data/spec/joosy/core/modules/container_spec.coffee +79 -76
- data/spec/joosy/core/modules/events_spec.coffee +148 -81
- data/spec/joosy/core/modules/filters_spec.coffee +68 -49
- data/spec/joosy/core/modules/log_spec.coffee +13 -5
- data/spec/joosy/core/modules/module_spec.coffee +24 -14
- data/spec/joosy/core/modules/renderer_spec.coffee +95 -89
- data/spec/joosy/core/modules/time_manager_spec.coffee +11 -16
- data/spec/joosy/core/modules/widget_manager_spec.coffee +89 -71
- data/spec/joosy/core/page_spec.coffee +201 -137
- data/spec/joosy/core/templaters/jst_spec.coffee +62 -0
- data/spec/joosy/core/widget_spec.coffee +25 -29
- data/spec/joosy/extensions/form/form_spec.coffee +3 -1
- data/spec/joosy/extensions/resources/base_spec.coffee +3 -0
- data/spec/joosy/extensions/resources/collection_spec.coffee +3 -0
- data/spec/joosy/extensions/resources/rest_collection_spec.coffee +3 -0
- data/spec/joosy/extensions/resources/rest_spec.coffee +3 -0
- data/src/joosy/core/application.coffee +1 -7
- data/src/joosy/core/helpers/view.coffee +12 -0
- data/src/joosy/core/helpers/widgets.coffee +19 -9
- data/src/joosy/core/joosy.coffee +0 -23
- data/src/joosy/core/layout.coffee +7 -5
- data/src/joosy/core/module.coffee +24 -4
- data/src/joosy/core/modules/container.coffee +29 -28
- data/src/joosy/core/modules/events.coffee +85 -72
- data/src/joosy/core/modules/filters.coffee +3 -1
- data/src/joosy/core/modules/renderer.coffee +91 -74
- data/src/joosy/core/modules/widgets_manager.coffee +12 -9
- data/src/joosy/core/page.coffee +7 -14
- data/src/joosy/core/templaters/{rails_jst.coffee → jst.coffee} +21 -19
- data/src/joosy/core/widget.coffee +3 -3
- data/src/joosy/extensions/resources/base.coffee +8 -3
- data/src/joosy/extensions/resources/rest.coffee +8 -0
- data/src/joosy/extensions/resources/rest_collection.coffee +1 -0
- data/tasks/joosy.coffee +46 -17
- data/templates/application/base/pages/welcome/index.coffee +5 -5
- data/templates/application/base/templates/layouts/application.jst.hamlc +2 -2
- data/templates/application/base/templates/pages/welcome/index.jst.hamlc +2 -2
- data/templates/application/standalone/Gruntfile.coffee +3 -1
- metadata +6 -5
- data/spec/helpers/helper.coffee +0 -68
- data/spec/joosy/core/templaters/rails_jst_spec.coffee +0 -25
@@ -1,47 +1,57 @@
|
|
1
1
|
describe "Joosy.Module", ->
|
2
2
|
|
3
|
-
it "
|
3
|
+
it "tracks inheritance", ->
|
4
4
|
class A
|
5
5
|
class B extends A
|
6
6
|
class C extends B
|
7
7
|
class D
|
8
|
+
|
8
9
|
for a in [A, B, C, D]
|
9
10
|
for b in [A, B, C, D]
|
10
11
|
if (a == b) ||
|
11
12
|
((a == B) && (b == A)) ||
|
12
13
|
((a == C) && (b != D))
|
13
|
-
expect(Joosy.Module.hasAncestor
|
14
|
+
expect(Joosy.Module.hasAncestor a, b).toBeTruthy()
|
14
15
|
else
|
15
|
-
expect(Joosy.Module.hasAncestor
|
16
|
+
expect(Joosy.Module.hasAncestor a, b).toBeFalsy()
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
# We need this check to ensure we are not overpolluting the namespace
|
19
|
+
it "has minimal set of properties", ->
|
20
|
+
class Klass extends Joosy.Module
|
21
|
+
|
22
|
+
expect(Object.extended(Klass).keys()).toEqual ['__namespace__', '__className', 'hasAncestor', 'aliasMethodChain', 'aliasStaticMethodChain', 'merge', 'include', 'extend', '__super__']
|
23
|
+
expect(Object.extended(Klass.prototype).keys()).toEqual ['constructor']
|
24
|
+
|
25
|
+
it "includes", ->
|
26
|
+
Module =
|
19
27
|
property: 'value'
|
28
|
+
|
20
29
|
class Klass extends Joosy.Module
|
21
|
-
@include
|
30
|
+
@include Module
|
31
|
+
|
22
32
|
expect(Klass::property).toEqual 'value'
|
23
|
-
expect(
|
33
|
+
expect(Klass.property).toBeUndefined()
|
24
34
|
|
25
|
-
it "
|
35
|
+
it "extends", ->
|
26
36
|
TestModule =
|
27
37
|
property: 'value'
|
38
|
+
|
28
39
|
class Klass extends Joosy.Module
|
29
40
|
@extend TestModule
|
41
|
+
|
30
42
|
expect(Klass.property).toEqual 'value'
|
31
|
-
expect(
|
43
|
+
expect(Klass::property).toBeUndefined()
|
32
44
|
|
33
|
-
it "
|
45
|
+
it "runs callbacks", ->
|
34
46
|
TestModule =
|
35
47
|
property: 'value'
|
36
48
|
included: sinon.spy()
|
37
49
|
extended: sinon.spy()
|
50
|
+
|
38
51
|
class Klass extends Joosy.Module
|
39
52
|
@include TestModule
|
40
53
|
@extend TestModule
|
54
|
+
|
41
55
|
for callback in ['included', 'extended']
|
42
56
|
expect(TestModule[callback].callCount).toEqual 1
|
43
57
|
expect(TestModule[callback].getCall(0).calledOn(Klass)).toBeTruthy()
|
44
|
-
|
45
|
-
it "should have minimal set of properties", ->
|
46
|
-
expect(Object.extended(Joosy.Module).keys()).toEqual ['__namespace__', '__className', 'hasAncestor', 'alias', 'aliasStatic', 'merge', 'include', 'extend']
|
47
|
-
expect(Object.extended(Joosy.Module.prototype).keys()).toEqual []
|
@@ -1,136 +1,142 @@
|
|
1
1
|
describe "Joosy.Modules.Renderer", ->
|
2
2
|
|
3
3
|
beforeEach ->
|
4
|
-
@
|
5
|
-
|
6
|
-
class @TestContainer extends Joosy.Module
|
4
|
+
class @Renderer extends Joosy.Module
|
7
5
|
@include Joosy.Modules.Renderer
|
8
6
|
|
9
|
-
@
|
10
|
-
|
11
|
-
class @TestObject extends Joosy.Module
|
12
|
-
@include Joosy.Modules.Events
|
13
|
-
|
14
|
-
constructor: (@value) ->
|
7
|
+
@renderer = new @Renderer
|
15
8
|
|
16
|
-
|
17
|
-
|
9
|
+
it "renders default template", ->
|
10
|
+
template = sinon.stub()
|
11
|
+
template.returns "result"
|
18
12
|
|
19
|
-
@
|
13
|
+
@Renderer.view template
|
20
14
|
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
expect(@renderer.__renderDefault(foo: 'bar')).toEqual 'result'
|
16
|
+
expect(template.getCall(0).args[0].foo).toEqual 'bar'
|
17
|
+
expect(template.getCall(0).args[0].__renderer).toEqual @renderer
|
24
18
|
|
25
|
-
|
26
|
-
|
27
|
-
template =
|
19
|
+
describe "rendering", ->
|
20
|
+
beforeEach ->
|
21
|
+
@template = (locals) =>
|
22
|
+
expect(locals.foo).toEqual 'bar'
|
23
|
+
expect(locals.__renderer).toEqual @renderer
|
24
|
+
"result"
|
28
25
|
|
29
|
-
|
26
|
+
it "accepts lambda", ->
|
27
|
+
expect(@renderer.render @template, foo: 'bar').toEqual 'result'
|
30
28
|
|
31
|
-
|
32
|
-
|
29
|
+
it "accepts template", ->
|
30
|
+
target = sinon.stub Joosy.Application.templater, 'buildView'
|
31
|
+
target.returns @template
|
33
32
|
|
34
|
-
|
35
|
-
expect(elem.text()).toBe "initial"
|
33
|
+
expect(@renderer.render @template, foo: 'bar').toEqual 'result'
|
36
34
|
|
37
|
-
|
35
|
+
Joosy.Application.templater.buildView.restore()
|
38
36
|
|
39
|
-
|
37
|
+
describe "dynamic rendering", ->
|
38
|
+
beforeEach ->
|
39
|
+
# Instance we are going to use to trigger dynamic rendering
|
40
|
+
class @Entity extends Joosy.Module
|
41
|
+
@include Joosy.Modules.Events
|
40
42
|
|
41
|
-
|
42
|
-
expect(elem.text()).toBe "new"
|
43
|
+
constructor: (@value) ->
|
43
44
|
|
44
|
-
|
45
|
+
update: (@value) ->
|
46
|
+
@trigger 'changed'
|
45
47
|
|
46
|
-
|
47
|
-
@dummyContainer.__removeMetamorphs()
|
48
|
-
@dummyObject.update "afterwards"
|
48
|
+
@entity = new @Entity("initial")
|
49
49
|
|
50
|
-
|
50
|
+
it "updates content", ->
|
51
|
+
template = (locals) -> locals.entity.value
|
51
52
|
|
52
|
-
|
53
|
-
|
53
|
+
runs ->
|
54
|
+
@$ground.html @renderer.renderDynamic(template, entity: @entity)
|
55
|
+
expect(@$ground.text()).toBe "initial"
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
-
template = -> @object.value
|
57
|
+
runs ->
|
58
|
+
@entity.update "new"
|
58
59
|
|
59
|
-
|
60
|
+
waits 0
|
60
61
|
|
61
|
-
|
62
|
-
|
62
|
+
runs ->
|
63
|
+
expect(@$ground.text()).toBe "new"
|
63
64
|
|
64
|
-
|
65
|
+
it "does not update unloaded content", ->
|
66
|
+
template = (locals) -> locals.entity.value
|
65
67
|
|
66
|
-
|
67
|
-
|
68
|
+
runs ->
|
69
|
+
@$ground.html @renderer.renderDynamic(template, entity: @entity)
|
70
|
+
expect(@$ground.text()).toBe "initial"
|
71
|
+
@renderer.__removeMetamorphs()
|
68
72
|
|
69
|
-
|
73
|
+
runs ->
|
74
|
+
@entity.update "new"
|
70
75
|
|
71
|
-
|
76
|
+
waits 0
|
72
77
|
|
73
|
-
|
78
|
+
runs ->
|
79
|
+
expect(@$ground.text()).toBe "initial"
|
74
80
|
|
75
|
-
|
76
|
-
|
77
|
-
|
81
|
+
describe "Metamorph magic", ->
|
82
|
+
beforeEach ->
|
83
|
+
sinon.spy window, 'Metamorph'
|
78
84
|
|
79
|
-
|
80
|
-
|
81
|
-
@dummyObject.update "me evil"
|
85
|
+
template = (locals) -> locals.entity.value
|
86
|
+
@$ground.html @renderer.renderDynamic(template, entity: @entity)
|
82
87
|
|
83
|
-
|
88
|
+
# With this we intercept calls to Metamorph updates
|
89
|
+
@updater = sinon.spy window.Metamorph.returnValues[0], 'html'
|
84
90
|
|
85
|
-
|
86
|
-
|
87
|
-
expect(updater.callCount).toEqual 2
|
91
|
+
afterEach ->
|
92
|
+
Metamorph.restore()
|
88
93
|
|
89
|
-
|
90
|
-
|
94
|
+
it "debounces", ->
|
95
|
+
@entity.update "new"
|
96
|
+
@entity.update "don't make"
|
97
|
+
@entity.update "me evil"
|
91
98
|
|
92
|
-
|
93
|
-
template = (locals) -> @multiplier(10)
|
99
|
+
waits 0
|
94
100
|
|
95
|
-
|
101
|
+
runs ->
|
102
|
+
expect(@updater.callCount).toEqual 1
|
103
|
+
expect(@$ground.text()).toEqual "me evil"
|
96
104
|
|
97
|
-
|
98
|
-
|
105
|
+
it "catches manually removed nodes", ->
|
106
|
+
@$ground.html ''
|
99
107
|
|
100
|
-
|
108
|
+
@entity.update "new"
|
109
|
+
@entity.update "don't make"
|
110
|
+
@entity.update "me evil"
|
101
111
|
|
102
|
-
|
112
|
+
waits 0
|
103
113
|
|
104
|
-
|
105
|
-
|
106
|
-
value * 6
|
114
|
+
runs ->
|
115
|
+
expect(@updater.callCount).toEqual 0
|
107
116
|
|
108
|
-
|
109
|
-
template = (locals) -> @globalMultiplier(10)
|
117
|
+
describe "helpers includer", ->
|
110
118
|
|
111
|
-
|
119
|
+
it "works with modules", ->
|
120
|
+
Joosy.namespace 'Joosy.Helpers.Hoge', ->
|
121
|
+
@multiplier = (value) -> "#{value * 5}"
|
112
122
|
|
113
|
-
|
114
|
-
|
123
|
+
@Renderer.helper Joosy.Helpers.Hoge
|
124
|
+
template = (locals) -> locals.multiplier(10)
|
115
125
|
|
116
|
-
|
117
|
-
|
118
|
-
expect(elem.text()).toBe "60"
|
119
|
-
|
120
|
-
it "proxies onRefresh for containers", ->
|
121
|
-
class Box extends Joosy.Module
|
122
|
-
@include Joosy.Modules.Renderer
|
123
|
-
@include Joosy.Modules.Container
|
126
|
+
expect(@renderer.render template).toBe "50"
|
124
127
|
|
125
|
-
|
128
|
+
it "works with local methods", ->
|
129
|
+
@Renderer::multiplier = (value) -> "#{value * 10}"
|
130
|
+
@Renderer.helper 'multiplier'
|
131
|
+
template = (locals) -> locals.multiplier(10)
|
126
132
|
|
127
|
-
|
128
|
-
|
129
|
-
@render(template, locals)
|
133
|
+
expect(@renderer.render template).toBe "100"
|
134
|
+
delete @Renderer::multiplier
|
130
135
|
|
131
|
-
|
136
|
+
it "works with globals", ->
|
137
|
+
Joosy.Helpers.Application.multiplier = (value) -> "#{value * 3}"
|
138
|
+
template = (locals) -> locals.multiplier(10)
|
132
139
|
|
133
|
-
|
134
|
-
|
140
|
+
expect(@renderer.render template).toBe "30"
|
141
|
+
delete Joosy.Helpers.Application.multiplier
|
135
142
|
|
136
|
-
expect(callback.callCount).toEqual 1
|
@@ -1,25 +1,20 @@
|
|
1
1
|
describe "Joosy.Modules.TimeManager", ->
|
2
2
|
|
3
3
|
beforeEach ->
|
4
|
-
class @
|
4
|
+
class @Manager extends Joosy.Module
|
5
5
|
@include Joosy.Modules.TimeManager
|
6
|
-
@box = new @TestTimeManager()
|
7
6
|
|
7
|
+
@manager = new @Manager
|
8
8
|
|
9
|
-
it "
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
it "stops intervals and timeouts", ->
|
10
|
+
callback = sinon.spy()
|
11
|
+
|
12
|
+
runs ->
|
13
|
+
@manager.setTimeout 1, callback
|
14
|
+
@manager.setInterval 1, callback
|
15
|
+
@manager.__clearTime()
|
13
16
|
|
14
|
-
|
15
|
-
timer = @box.setInterval 10000, ->
|
16
|
-
expect(@box.__intervals).toEqual [timer]
|
17
|
-
window.clearInterval timer
|
17
|
+
waits 2
|
18
18
|
|
19
|
-
it "should stop intervals and timeouts", ->
|
20
|
-
callback = sinon.spy()
|
21
19
|
runs ->
|
22
|
-
|
23
|
-
@box.__clearTime()
|
24
|
-
waits(10)
|
25
|
-
runs -> expect(callback.callCount).toEqual(0)
|
20
|
+
expect(callback.callCount).toEqual 0
|
@@ -1,78 +1,96 @@
|
|
1
1
|
describe "Joosy.Modules.WidgetsManager", ->
|
2
2
|
|
3
3
|
beforeEach ->
|
4
|
-
class @
|
5
|
-
@include Joosy.Modules.WidgetsManager
|
4
|
+
class @Manager extends Joosy.Module
|
6
5
|
@include Joosy.Modules.Container
|
6
|
+
@include Joosy.Modules.WidgetsManager
|
7
|
+
|
8
|
+
class @Widget extends Joosy.Widget
|
9
|
+
constructor: (@argument) ->
|
10
|
+
|
11
|
+
@manager = new @Manager
|
12
|
+
|
13
|
+
describe "manager", ->
|
14
|
+
|
15
|
+
beforeEach ->
|
16
|
+
@widget = new @Widget
|
17
|
+
|
18
|
+
sinon.spy @widget, '__load'
|
19
|
+
sinon.spy @widget, '__unload'
|
20
|
+
|
21
|
+
it "registers widget", ->
|
22
|
+
result = @manager.registerWidget @$ground, @widget
|
23
|
+
expect(result instanceof @Widget).toBeTruthy()
|
24
|
+
expect(@manager.__activeWidgets).toEqual [result]
|
25
|
+
expect(@widget.__load.callCount).toEqual 1
|
26
|
+
|
27
|
+
it "unregisters widget", ->
|
28
|
+
@manager.registerWidget @$ground, @widget
|
29
|
+
|
30
|
+
expect(@manager.unregisterWidget @widget).toBeTruthy()
|
31
|
+
expect(@manager.__activeWidgets).toEqual []
|
32
|
+
expect(@widget.__unload.callCount).toEqual 1
|
33
|
+
|
34
|
+
it "unload all widgets properly", ->
|
35
|
+
3.times => @manager.registerWidget(@$ground, @widget)
|
36
|
+
@manager.__unloadWidgets()
|
37
|
+
expect(@widget.__unload.callCount).toEqual 3
|
38
|
+
|
39
|
+
describe 'declarator', ->
|
40
|
+
|
41
|
+
it "inherits widget declarations", ->
|
42
|
+
@Manager.mapWidgets
|
43
|
+
'test': 'widget'
|
7
44
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
expect(@widgetMock.__load.callCount).toEqual 1
|
20
|
-
|
21
|
-
expect(@box.unregisterWidget @widgetMock).toBeTruthy()
|
22
|
-
expect(@box.__activeWidgets).toEqual []
|
23
|
-
expect(@widgetMock.__unload.callCount).toEqual 1
|
24
|
-
|
25
|
-
it "should unload all widgets", ->
|
26
|
-
0.upto(2).each => @box.registerWidget(@ground, @widgetMock)
|
27
|
-
@box.__unloadWidgets()
|
28
|
-
expect(@widgetMock.__unload.callCount).toEqual 3
|
29
|
-
|
30
|
-
it "should inherit widget declarations", ->
|
31
|
-
@box.container = @ground
|
32
|
-
@TestWidgetManager::__widgets =
|
33
|
-
'test': 'widget'
|
34
|
-
class SubWidgetManagerA extends @TestWidgetManager
|
35
|
-
@mapWidgets
|
45
|
+
class A extends @Manager
|
46
|
+
@mapWidgets
|
47
|
+
'selector': 'widget'
|
48
|
+
|
49
|
+
class B extends A
|
50
|
+
@mapWidgets
|
51
|
+
'widgets': 'widget'
|
52
|
+
'selector': 'overriden'
|
53
|
+
|
54
|
+
expect((new A).__widgets).toEqual Object.extended
|
55
|
+
'test': 'widget'
|
36
56
|
'selector': 'widget'
|
37
|
-
|
38
|
-
|
39
|
-
'
|
57
|
+
|
58
|
+
expect((new B).__widgets).toEqual Object.extended
|
59
|
+
'test': 'widget'
|
60
|
+
'widgets': 'widget'
|
40
61
|
'selector': 'overriden'
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
@
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
'.
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
expect(@ground.find('.widget').html()).toEqual 'fluffy'
|
77
|
-
expect(@box.__activeWidgets[0].tester).toBeUndefined()
|
78
|
-
expect(@box.__activeWidgets[1].tester).toEqual 0
|
62
|
+
|
63
|
+
it "registers declared widgets", ->
|
64
|
+
@$ground.seed()
|
65
|
+
|
66
|
+
@Manager.mapElements
|
67
|
+
footer: '.footer'
|
68
|
+
|
69
|
+
@Manager.mapWidgets widgets =
|
70
|
+
'$container': Joosy.Widget
|
71
|
+
'$footer': Joosy.Widget
|
72
|
+
'.post': sinon.stub().returns new @Widget
|
73
|
+
|
74
|
+
@manager.container = $('#application')
|
75
|
+
@manager.__assignElements()
|
76
|
+
@manager.__setupWidgets()
|
77
|
+
|
78
|
+
expect(@manager.__activeWidgets.length).toEqual 5
|
79
|
+
expect(widgets['.post'].callCount).toEqual 3
|
80
|
+
expect(widgets['.post'].getCall(0).calledOn @manager).toBeTruthy()
|
81
|
+
|
82
|
+
it "bootstraps declared widgets properly", ->
|
83
|
+
@$ground.seed()
|
84
|
+
|
85
|
+
@Widget.view -> 'fluffy'
|
86
|
+
@Manager.mapWidgets
|
87
|
+
'#post1': @Widget
|
88
|
+
'#widget1': (i) => new @Widget i
|
89
|
+
|
90
|
+
@manager.container = $('#application')
|
91
|
+
@manager.__setupWidgets()
|
92
|
+
|
93
|
+
expect(@$ground.find('#post1').html()).toEqual 'fluffy'
|
94
|
+
expect(@$ground.find('#widget1').html()).toEqual 'fluffy'
|
95
|
+
expect(@manager.__activeWidgets[0].argument).toBeUndefined()
|
96
|
+
expect(@manager.__activeWidgets[1].argument).toEqual 0
|