joosy 0.1.0.RC1
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.
- data/.gitignore +5 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +159 -0
- data/Guardfile +30 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +3 -0
- data/Rakefile +14 -0
- data/app/assets/javascripts/joosy.js.coffee +7 -0
- data/app/assets/javascripts/joosy/core/application.js.coffee +28 -0
- data/app/assets/javascripts/joosy/core/form.js.coffee +87 -0
- data/app/assets/javascripts/joosy/core/helpers.js.coffee +6 -0
- data/app/assets/javascripts/joosy/core/joosy.js.coffee +65 -0
- data/app/assets/javascripts/joosy/core/layout.js.coffee +47 -0
- data/app/assets/javascripts/joosy/core/modules/container.js.coffee +59 -0
- data/app/assets/javascripts/joosy/core/modules/events.js.coffee +35 -0
- data/app/assets/javascripts/joosy/core/modules/filters.js.coffee +39 -0
- data/app/assets/javascripts/joosy/core/modules/log.js.coffee +15 -0
- data/app/assets/javascripts/joosy/core/modules/module.js.coffee +43 -0
- data/app/assets/javascripts/joosy/core/modules/renderer.js.coffee +116 -0
- data/app/assets/javascripts/joosy/core/modules/time_manager.js.coffee +25 -0
- data/app/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee +58 -0
- data/app/assets/javascripts/joosy/core/page.js.coffee +156 -0
- data/app/assets/javascripts/joosy/core/preloader.js.coffee +5 -0
- data/app/assets/javascripts/joosy/core/resource/generic.js.coffee +61 -0
- data/app/assets/javascripts/joosy/core/resource/rest.js.coffee +76 -0
- data/app/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +48 -0
- data/app/assets/javascripts/joosy/core/router.js.coffee +89 -0
- data/app/assets/javascripts/joosy/core/templaters/rails_jst.js.coffee +20 -0
- data/app/assets/javascripts/joosy/core/widget.js.coffee +41 -0
- data/app/assets/javascripts/joosy/preloaders/caching.js.coffee +94 -0
- data/app/assets/javascripts/joosy/preloaders/inline.js.coffee +55 -0
- data/app/helpers/joosy/sprockets_helper.rb +23 -0
- data/app/views/layouts/json_wrapper.json.erb +1 -0
- data/joosy.gemspec +25 -0
- data/lib/joosy.rb +9 -0
- data/lib/joosy/forms.rb +47 -0
- data/lib/joosy/rails/engine.rb +17 -0
- data/lib/joosy/rails/version.rb +5 -0
- data/lib/rails/generators/joosy/application_generator.rb +41 -0
- data/lib/rails/generators/joosy/joosy_base.rb +30 -0
- data/lib/rails/generators/joosy/layout_generator.rb +32 -0
- data/lib/rails/generators/joosy/page_generator.rb +44 -0
- data/lib/rails/generators/joosy/preloader_generator.rb +32 -0
- data/lib/rails/generators/joosy/resource_generator.rb +29 -0
- data/lib/rails/generators/joosy/templates/app.js.coffee +10 -0
- data/lib/rails/generators/joosy/templates/app/helpers/application.js.coffee +4 -0
- data/lib/rails/generators/joosy/templates/app/layouts/application.js.coffee +2 -0
- data/lib/rails/generators/joosy/templates/app/layouts/template.js.coffee +2 -0
- data/lib/rails/generators/joosy/templates/app/pages/application.js.coffee +1 -0
- data/lib/rails/generators/joosy/templates/app/pages/template.js.coffee +5 -0
- data/lib/rails/generators/joosy/templates/app/pages/welcome/index.js.coffee +22 -0
- data/lib/rails/generators/joosy/templates/app/resources/template.js.coffee +2 -0
- data/lib/rails/generators/joosy/templates/app/routes.js.coffee +8 -0
- data/lib/rails/generators/joosy/templates/app/templates/layouts/application.jst.hamlc +2 -0
- data/lib/rails/generators/joosy/templates/app/templates/pages/welcome/index.jst.hamlc +7 -0
- data/lib/rails/generators/joosy/templates/app/widgets/template.js.coffee +2 -0
- data/lib/rails/generators/joosy/templates/app_controller.rb +9 -0
- data/lib/rails/generators/joosy/templates/app_preloader.js.coffee.erb +13 -0
- data/lib/rails/generators/joosy/templates/preload.html.erb +26 -0
- data/lib/rails/generators/joosy/templates/preload.html.haml +19 -0
- data/lib/rails/generators/joosy/widget_generator.rb +32 -0
- data/spec/javascripts/helpers/spec_helper.js.coffee +44 -0
- data/spec/javascripts/joosy/core/application_spec.js.coffee +40 -0
- data/spec/javascripts/joosy/core/form_spec.js.coffee +141 -0
- data/spec/javascripts/joosy/core/joosy_spec.js.coffee +72 -0
- data/spec/javascripts/joosy/core/layout_spec.js.coffee +50 -0
- data/spec/javascripts/joosy/core/modules/container_spec.js.coffee +92 -0
- data/spec/javascripts/joosy/core/modules/events_spec.js.coffee +53 -0
- data/spec/javascripts/joosy/core/modules/filters_spec.js.coffee +71 -0
- data/spec/javascripts/joosy/core/modules/log_spec.js.coffee +15 -0
- data/spec/javascripts/joosy/core/modules/module_spec.js.coffee +47 -0
- data/spec/javascripts/joosy/core/modules/renderer_spec.js.coffee +149 -0
- data/spec/javascripts/joosy/core/modules/time_manager_spec.js.coffee +25 -0
- data/spec/javascripts/joosy/core/modules/widget_manager_spec.js.coffee +75 -0
- data/spec/javascripts/joosy/core/page_spec.js.coffee +175 -0
- data/spec/javascripts/joosy/core/resource/generic_spec.js.coffee +35 -0
- data/spec/javascripts/joosy/core/resource/rest_collection_spec.js.coffee +65 -0
- data/spec/javascripts/joosy/core/resource/rest_spec.js.coffee +108 -0
- data/spec/javascripts/joosy/core/router_spec.js.coffee +123 -0
- data/spec/javascripts/joosy/core/templaters/rails_jst_spec.js.coffee +25 -0
- data/spec/javascripts/joosy/core/widget_spec.js.coffee +51 -0
- data/spec/javascripts/joosy/preloaders/caching_spec.js.coffee +36 -0
- data/spec/javascripts/joosy/preloaders/inline_spec.js.coffee +16 -0
- data/spec/javascripts/support/assets/coolface.jpg +0 -0
- data/spec/javascripts/support/assets/okay.jpg +0 -0
- data/spec/javascripts/support/assets/test.js +1 -0
- data/spec/javascripts/support/jasmine.yml +74 -0
- data/spec/javascripts/support/jasmine_config.rb +23 -0
- data/spec/javascripts/support/jasmine_runner.rb +32 -0
- data/spec/javascripts/support/sinon-1.3.1.js +3469 -0
- data/spec/javascripts/support/sinon-ie-1.3.1.js +82 -0
- data/vendor/assets/javascripts/base64.js +135 -0
- data/vendor/assets/javascripts/inflection.js +656 -0
- data/vendor/assets/javascripts/jquery.form.js +980 -0
- data/vendor/assets/javascripts/jquery.hashchange.js +390 -0
- data/vendor/assets/javascripts/metamorph.js +409 -0
- data/vendor/assets/javascripts/sugar.js +6040 -0
- metadata +232 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
describe "Joosy", ->
|
|
2
|
+
|
|
3
|
+
it "should properly initialize", ->
|
|
4
|
+
expect(Joosy.debug).toBeFalsy()
|
|
5
|
+
expect(Joosy.Modules).toBeDefined()
|
|
6
|
+
expect(Joosy.Resource).toBeDefined()
|
|
7
|
+
|
|
8
|
+
it "should declare namespaces", ->
|
|
9
|
+
Joosy.namespace 'Namespaces.Test1'
|
|
10
|
+
Joosy.namespace 'Namespaces.Test2', ->
|
|
11
|
+
@bingo = 'bongo'
|
|
12
|
+
expect(window.Namespaces.Test1).toBeDefined()
|
|
13
|
+
expect(window.Namespaces.Test2.bingo).toEqual('bongo')
|
|
14
|
+
|
|
15
|
+
it "should imprint namespace paths in Joosy.Module descendants", ->
|
|
16
|
+
Joosy.namespace 'Irish', ->
|
|
17
|
+
class @Pub extends Joosy.Module
|
|
18
|
+
|
|
19
|
+
Joosy.namespace 'British', ->
|
|
20
|
+
class @Pub extends Joosy.Module
|
|
21
|
+
|
|
22
|
+
Joosy.namespace 'Keltic', ->
|
|
23
|
+
class @Pub extends Irish.Pub
|
|
24
|
+
|
|
25
|
+
expect(Irish.Pub.__namespace__).toEqual ["Irish"]
|
|
26
|
+
expect(British.Pub.__namespace__).toEqual ["British"]
|
|
27
|
+
expect(Keltic.Pub.__namespace__).toEqual ["Keltic"]
|
|
28
|
+
|
|
29
|
+
Joosy.namespace 'Deeply.Nested', ->
|
|
30
|
+
class @Klass extends Joosy.Module
|
|
31
|
+
|
|
32
|
+
expect(Deeply.Nested.Klass.__namespace__).toEqual ["Deeply", "Nested"]
|
|
33
|
+
|
|
34
|
+
class @Flat extends Joosy.Module
|
|
35
|
+
|
|
36
|
+
expect(@Flat.__namespace__).toEqual []
|
|
37
|
+
|
|
38
|
+
it "should set up helpers", ->
|
|
39
|
+
Joosy.helpers 'Hoge', ->
|
|
40
|
+
@fuga = ->
|
|
41
|
+
"piyo"
|
|
42
|
+
|
|
43
|
+
expect(window.Joosy.Helpers).toBeDefined()
|
|
44
|
+
expect(window.Joosy.Helpers.Hoge).toBeDefined()
|
|
45
|
+
expect(window.Joosy.Helpers.Hoge.fuga()).toBe "piyo"
|
|
46
|
+
|
|
47
|
+
it "should generate proper UUIDs", ->
|
|
48
|
+
uuids = []
|
|
49
|
+
2.times ->
|
|
50
|
+
uuids.push Joosy.uuid()
|
|
51
|
+
expect(uuids.unique().length).toEqual(2)
|
|
52
|
+
expect(uuids[0]).toMatch /[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}/
|
|
53
|
+
|
|
54
|
+
it "should build proper URLs", ->
|
|
55
|
+
expect(Joosy.buildUrl 'http://www.org').toEqual('http://www.org')
|
|
56
|
+
expect(Joosy.buildUrl 'http://www.org#hash').toEqual('http://www.org#hash')
|
|
57
|
+
expect(Joosy.buildUrl 'http://www.org', {foo: 'bar'}).toEqual('http://www.org?foo=bar')
|
|
58
|
+
expect(Joosy.buildUrl 'http://www.org?bar=baz', {foo: 'bar'}).toEqual('http://www.org?bar=baz&foo=bar')
|
|
59
|
+
|
|
60
|
+
it "should preload images", ->
|
|
61
|
+
path = "/spec/javascripts/support/assets/"
|
|
62
|
+
images = [path+"okay.jpg", path+"okay.jpg"]
|
|
63
|
+
|
|
64
|
+
callback = sinon.spy()
|
|
65
|
+
|
|
66
|
+
runs -> Joosy.preloadImages path+"coolface.jpg", callback
|
|
67
|
+
waits(150)
|
|
68
|
+
runs -> expect(callback.callCount).toEqual(1)
|
|
69
|
+
|
|
70
|
+
runs -> Joosy.preloadImages images, callback
|
|
71
|
+
waits(150)
|
|
72
|
+
runs -> expect(callback.callCount).toEqual(2)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
describe "Joosy.Layout", ->
|
|
2
|
+
|
|
3
|
+
beforeEach ->
|
|
4
|
+
class @TestLayout extends Joosy.Layout
|
|
5
|
+
@box = new @TestLayout()
|
|
6
|
+
|
|
7
|
+
it "should have appropriate accessors", ->
|
|
8
|
+
callback_names = ['beforePaint', 'paint', 'erase']
|
|
9
|
+
callback_names.each (func) =>
|
|
10
|
+
@TestLayout[func] 'callback'
|
|
11
|
+
expect(@TestLayout::['__' + func]).toEqual 'callback'
|
|
12
|
+
|
|
13
|
+
it "should have default view", ->
|
|
14
|
+
@box = new @TestLayout()
|
|
15
|
+
expect(@box.__renderer instanceof Function).toBeTruthy()
|
|
16
|
+
|
|
17
|
+
it "should use Router", ->
|
|
18
|
+
target = sinon.stub Joosy.Router, 'navigate'
|
|
19
|
+
@box.navigate 'there'
|
|
20
|
+
expect(target.callCount).toEqual 1
|
|
21
|
+
expect(target.alwaysCalledWithExactly 'there').toBeTruthy()
|
|
22
|
+
Joosy.Router.navigate.restore()
|
|
23
|
+
|
|
24
|
+
it "should load itself", ->
|
|
25
|
+
spies = []
|
|
26
|
+
spies.push sinon.spy(@box, 'refreshElements')
|
|
27
|
+
spies.push sinon.spy(@box, '__delegateEvents')
|
|
28
|
+
spies.push sinon.spy(@box, '__setupWidgets')
|
|
29
|
+
spies.push sinon.spy(@box, '__runAfterLoads')
|
|
30
|
+
@box.__load(@ground)
|
|
31
|
+
expect(spies).toBeSequenced()
|
|
32
|
+
|
|
33
|
+
it "should unload itself", ->
|
|
34
|
+
spies = []
|
|
35
|
+
spies.push sinon.spy(@box, 'clearTime')
|
|
36
|
+
spies.push sinon.spy(@box, '__unloadWidgets')
|
|
37
|
+
spies.push sinon.spy(@box, '__runAfterUnloads')
|
|
38
|
+
@box.__unload()
|
|
39
|
+
expect(spies).toBeSequenced()
|
|
40
|
+
|
|
41
|
+
it "should generate uuid", ->
|
|
42
|
+
sinon.spy Joosy, 'uuid'
|
|
43
|
+
@box.yield()
|
|
44
|
+
expect(Joosy.uuid.callCount).toEqual 1
|
|
45
|
+
expect(@box.uuid).toBeDefined()
|
|
46
|
+
Joosy.uuid.restore()
|
|
47
|
+
|
|
48
|
+
it "should uuid as selector", ->
|
|
49
|
+
@box.yield()
|
|
50
|
+
expect(@box.content().selector).toEqual '#' + @box.uuid
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
describe "Joosy.Modules.Container", ->
|
|
2
|
+
|
|
3
|
+
beforeEach ->
|
|
4
|
+
@seedGround()
|
|
5
|
+
class @TestContainer extends Joosy.Module
|
|
6
|
+
@include Joosy.Modules.Container
|
|
7
|
+
elements:
|
|
8
|
+
footer: '.footer'
|
|
9
|
+
events:
|
|
10
|
+
'test': 'onContainerTest'
|
|
11
|
+
container: $('#application', @ground)
|
|
12
|
+
@box = new @TestContainer()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
it "should have property named per declared element in container", ->
|
|
16
|
+
@ground.prepend('<div class="footer" />') # out of container
|
|
17
|
+
@box.refreshElements()
|
|
18
|
+
target = @box.footer.get 0
|
|
19
|
+
expect(target).toBeTruthy()
|
|
20
|
+
expect(target).toBe $('.footer', @box.container).get 0
|
|
21
|
+
expect(target).toBe @box.$('.footer').get 0
|
|
22
|
+
|
|
23
|
+
it "should reinitialize container", ->
|
|
24
|
+
old_container = @box.container
|
|
25
|
+
parent = old_container.parent()
|
|
26
|
+
callback = sinon.spy()
|
|
27
|
+
old_container.bind 'test', callback
|
|
28
|
+
old_container.trigger 'test'
|
|
29
|
+
new_container = Joosy.Modules.Container.swapContainer old_container, 'new content'
|
|
30
|
+
new_container.trigger 'test'
|
|
31
|
+
expect(new_container.html()).toEqual 'new content'
|
|
32
|
+
expect(new_container.parent().get(0)).toBe parent.get 0
|
|
33
|
+
expect(old_container.parent().get(0)).toBeUndefined()
|
|
34
|
+
expect(callback.callCount).toEqual 1
|
|
35
|
+
|
|
36
|
+
it "should inherit element declarations", ->
|
|
37
|
+
class SubContainerA extends @TestContainer
|
|
38
|
+
elements:
|
|
39
|
+
first: 'first'
|
|
40
|
+
second: 'second'
|
|
41
|
+
class SubContainerB extends SubContainerA
|
|
42
|
+
elements:
|
|
43
|
+
first: 'overrided'
|
|
44
|
+
third: 'third'
|
|
45
|
+
subBox = new SubContainerB()
|
|
46
|
+
target = subBox.__collectElements()
|
|
47
|
+
expect(target).toEqual Object.extended
|
|
48
|
+
first: 'overrided'
|
|
49
|
+
second: 'second'
|
|
50
|
+
third: 'third'
|
|
51
|
+
footer: '.footer'
|
|
52
|
+
target = (new @TestContainer()).__collectElements()
|
|
53
|
+
expect(target).toEqual Object.extended(footer: '.footer')
|
|
54
|
+
|
|
55
|
+
it "should resolve element selector", ->
|
|
56
|
+
target = @box.__extractSelector '$footer'
|
|
57
|
+
expect(target).toEqual '.footer'
|
|
58
|
+
|
|
59
|
+
it "should inherit event declarations", ->
|
|
60
|
+
class SubContainerA extends @TestContainer
|
|
61
|
+
events:
|
|
62
|
+
'test .post': 'callback2'
|
|
63
|
+
'custom' : 'method'
|
|
64
|
+
class SubContainerB extends SubContainerA
|
|
65
|
+
events:
|
|
66
|
+
'test $footer': 'onFooterTest'
|
|
67
|
+
'custom' : 'overrided'
|
|
68
|
+
subBox = new SubContainerB()
|
|
69
|
+
target = subBox.__collectEvents()
|
|
70
|
+
expect(target).toEqual Object.extended
|
|
71
|
+
'test': 'onContainerTest'
|
|
72
|
+
'test .post': 'callback2'
|
|
73
|
+
'test $footer': 'onFooterTest'
|
|
74
|
+
'custom' : 'overrided'
|
|
75
|
+
target = (new @TestContainer()).__collectEvents()
|
|
76
|
+
expect(target).toEqual Object.extended('test': 'onContainerTest')
|
|
77
|
+
|
|
78
|
+
it "should delegate events", ->
|
|
79
|
+
callback = 1.upto(3).map -> sinon.spy()
|
|
80
|
+
@box.events = Object.extended(@box.events).merge
|
|
81
|
+
'test .post': callback[2]
|
|
82
|
+
'test $footer': 'onFooterTest'
|
|
83
|
+
|
|
84
|
+
@box.onContainerTest = callback[0]
|
|
85
|
+
@box.onFooterTest = callback[1]
|
|
86
|
+
@box.__delegateEvents()
|
|
87
|
+
@box.container.trigger 'test'
|
|
88
|
+
$('.footer', @box.container).trigger 'test'
|
|
89
|
+
$('.post', @box.container).trigger 'test'
|
|
90
|
+
expect(callback[0].callCount).toEqual 5
|
|
91
|
+
expect(callback[1].callCount).toEqual 1
|
|
92
|
+
expect(callback[2].callCount).toEqual 3
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
describe "Joosy.Modules.Events", ->
|
|
2
|
+
|
|
3
|
+
beforeEach ->
|
|
4
|
+
class @TestEvents extends Joosy.Module
|
|
5
|
+
@include Joosy.Modules.Events
|
|
6
|
+
class @SubTestEvents extends @TestEvents
|
|
7
|
+
@include Joosy.Modules.Events
|
|
8
|
+
@box = new @TestEvents()
|
|
9
|
+
@sub = new @SubTestEvents()
|
|
10
|
+
|
|
11
|
+
it "should run callback once when the all listed events have occurred", ->
|
|
12
|
+
callback = sinon.spy()
|
|
13
|
+
|
|
14
|
+
@box.wait 'events list', callback
|
|
15
|
+
|
|
16
|
+
@box.trigger 'events'
|
|
17
|
+
expect(callback.callCount).toEqual 0
|
|
18
|
+
@box.trigger 'list'
|
|
19
|
+
expect(callback.callCount).toEqual 1
|
|
20
|
+
|
|
21
|
+
@box.trigger 'events'
|
|
22
|
+
expect(callback.callCount).toEqual 1
|
|
23
|
+
@box.trigger 'list'
|
|
24
|
+
expect(callback.callCount).toEqual 1
|
|
25
|
+
|
|
26
|
+
it "should allow for binding and unbinding to events", ->
|
|
27
|
+
callback = sinon.spy()
|
|
28
|
+
|
|
29
|
+
@box.bind 'event', callback
|
|
30
|
+
|
|
31
|
+
@box.trigger 'other-event'
|
|
32
|
+
expect(callback.callCount).toEqual 0
|
|
33
|
+
@box.trigger 'event'
|
|
34
|
+
expect(callback.callCount).toEqual 1
|
|
35
|
+
@box.trigger 'event'
|
|
36
|
+
expect(callback.callCount).toEqual 2
|
|
37
|
+
|
|
38
|
+
@box.unbind 'other-event'
|
|
39
|
+
|
|
40
|
+
@box.trigger 'event'
|
|
41
|
+
expect(callback.callCount).toEqual 3
|
|
42
|
+
|
|
43
|
+
@box.unbind callback
|
|
44
|
+
|
|
45
|
+
@box.trigger 'event'
|
|
46
|
+
expect(callback.callCount).toEqual 3
|
|
47
|
+
|
|
48
|
+
it "should handle inheritance well", ->
|
|
49
|
+
callback = sinon.spy()
|
|
50
|
+
@sub.wait 'foo', callback
|
|
51
|
+
|
|
52
|
+
expect(@sub.__oneShotEvents).toEqual [[['foo'], callback]]
|
|
53
|
+
expect(@box.__oneShotEvents).toBeUndefined()
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
describe "Joosy.Modules.Filters", ->
|
|
2
|
+
|
|
3
|
+
beforeEach ->
|
|
4
|
+
class @TestFilters extends Joosy.Module
|
|
5
|
+
@include Joosy.Modules.Filters
|
|
6
|
+
@box = new @TestFilters()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
it "should inherit filters by copying them", ->
|
|
10
|
+
class SubFiltersA extends @TestFilters
|
|
11
|
+
@beforeLoad 'filter1'
|
|
12
|
+
@afterLoad 'filter2'
|
|
13
|
+
@afterUnload 'filter3'
|
|
14
|
+
class SubFiltersB extends SubFiltersA
|
|
15
|
+
@beforeLoad 'filter4'
|
|
16
|
+
@afterLoad 'filter5'
|
|
17
|
+
@afterUnload 'filter6'
|
|
18
|
+
target = new SubFiltersB()
|
|
19
|
+
expect(target.__beforeLoads).toEqual ['filter1', 'filter4']
|
|
20
|
+
expect(target.__afterLoads).toEqual ['filter2', 'filter5']
|
|
21
|
+
expect(target.__afterUnloads).toEqual ['filter3', 'filter6']
|
|
22
|
+
target = new SubFiltersA()
|
|
23
|
+
expect(target.__beforeLoads).toEqual ['filter1']
|
|
24
|
+
expect(target.__afterLoads).toEqual ['filter2']
|
|
25
|
+
expect(target.__afterUnloads).toEqual ['filter3']
|
|
26
|
+
target = new @TestFilters()
|
|
27
|
+
expect(target.__beforeLoads).toBeUndefined()
|
|
28
|
+
expect(target.__afterLoads).toBeUndefined()
|
|
29
|
+
expect(target.__afterUnloads).toBeUndefined()
|
|
30
|
+
|
|
31
|
+
it "should run callbacks", ->
|
|
32
|
+
callback = 0.upto(2).map -> sinon.spy()
|
|
33
|
+
@box.constructor.beforeLoad callback[0]
|
|
34
|
+
@box.constructor.afterLoad callback[1]
|
|
35
|
+
@box.constructor.afterUnload callback[2]
|
|
36
|
+
@box.__runBeforeLoads 1, 2
|
|
37
|
+
@box.__runAfterLoads 1, 2
|
|
38
|
+
@box.__runAfterUnloads 1, 2
|
|
39
|
+
for i in 0.upto(2)
|
|
40
|
+
expect(callback[i].callCount).toEqual 1
|
|
41
|
+
expect(callback[i].alwaysCalledWithExactly 1, 2).toBeTruthy()
|
|
42
|
+
|
|
43
|
+
it "should chain beforeLoad filters", ->
|
|
44
|
+
callback = 0.upto(2).map -> sinon.stub()
|
|
45
|
+
callback[0].returns true
|
|
46
|
+
@box.constructor.beforeLoad(callback[i]) for i in 0.upto 2
|
|
47
|
+
expect(@box.__runBeforeLoads()).toBeFalsy()
|
|
48
|
+
expect(callback[0].callCount).toEqual 1
|
|
49
|
+
expect(callback[1].callCount).toEqual 1
|
|
50
|
+
expect(callback[2].callCount).toEqual 0
|
|
51
|
+
|
|
52
|
+
it "should chain beforeLoad filters", ->
|
|
53
|
+
callback = 0.upto(1).map -> sinon.stub()
|
|
54
|
+
callback[0].returns true
|
|
55
|
+
callback[1].returns true
|
|
56
|
+
@box.constructor.beforeLoad(callback[i]) for i in 0.upto(1)
|
|
57
|
+
expect(@box.__runBeforeLoads()).toBeTruthy()
|
|
58
|
+
expect(callback[0].callCount).toEqual 1
|
|
59
|
+
expect(callback[1].callCount).toEqual 1
|
|
60
|
+
|
|
61
|
+
it "should accept callback names", ->
|
|
62
|
+
@box.constructor.beforeLoad 'callback0'
|
|
63
|
+
@box.constructor.afterLoad 'callback1'
|
|
64
|
+
@box.constructor.afterUnload 'callback2'
|
|
65
|
+
for i in 0.upto(2)
|
|
66
|
+
@box['callback' + i] = sinon.spy()
|
|
67
|
+
@box.__runBeforeLoads()
|
|
68
|
+
@box.__runAfterLoads()
|
|
69
|
+
@box.__runAfterUnloads()
|
|
70
|
+
for i in 0.upto(2)
|
|
71
|
+
expect(@box['callback' + i].callCount).toEqual 1
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
describe "Joosy.Modules.Log", ->
|
|
2
|
+
|
|
3
|
+
beforeEach ->
|
|
4
|
+
class @TestLog extends Joosy.Module
|
|
5
|
+
@include Joosy.Modules.Log
|
|
6
|
+
@box = new @TestLog()
|
|
7
|
+
|
|
8
|
+
it "should log into console", ->
|
|
9
|
+
@box.log 'message', 'appendix'
|
|
10
|
+
|
|
11
|
+
it "should log debug messages into console", ->
|
|
12
|
+
Joosy.debug = true
|
|
13
|
+
@box.debug 'debug message'
|
|
14
|
+
Joosy.debug = false
|
|
15
|
+
@box.debug 'unseen debug message'
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
describe "Joosy.Module", ->
|
|
2
|
+
|
|
3
|
+
it "should track inheritance", ->
|
|
4
|
+
class A
|
|
5
|
+
class B extends A
|
|
6
|
+
class C extends B
|
|
7
|
+
class D
|
|
8
|
+
for a in [A, B, C, D]
|
|
9
|
+
for b in [A, B, C, D]
|
|
10
|
+
if (a == b) ||
|
|
11
|
+
((a == B) && (b == A)) ||
|
|
12
|
+
((a == C) && (b != D))
|
|
13
|
+
expect(Joosy.Module.hasAncestor.apply(null, [a, b])).toBeTruthy()
|
|
14
|
+
else
|
|
15
|
+
expect(Joosy.Module.hasAncestor.apply(null, [a, b])).toBeFalsy()
|
|
16
|
+
|
|
17
|
+
it "should include properties into prototype", ->
|
|
18
|
+
TestModule =
|
|
19
|
+
property: 'value'
|
|
20
|
+
class Klass extends Joosy.Module
|
|
21
|
+
@include TestModule
|
|
22
|
+
expect(Klass::property).toEqual 'value'
|
|
23
|
+
expect((new Klass()).property).toEqual 'value'
|
|
24
|
+
|
|
25
|
+
it "should extend object", ->
|
|
26
|
+
TestModule =
|
|
27
|
+
property: 'value'
|
|
28
|
+
class Klass extends Joosy.Module
|
|
29
|
+
@extend TestModule
|
|
30
|
+
expect(Klass.property).toEqual 'value'
|
|
31
|
+
expect((new Klass()).property).toBeUndefined()
|
|
32
|
+
|
|
33
|
+
it "should run callbacks on include and extend", ->
|
|
34
|
+
TestModule =
|
|
35
|
+
property: 'value'
|
|
36
|
+
included: sinon.spy()
|
|
37
|
+
extended: sinon.spy()
|
|
38
|
+
class Klass extends Joosy.Module
|
|
39
|
+
@include TestModule
|
|
40
|
+
@extend TestModule
|
|
41
|
+
for callback in ['included', 'extended']
|
|
42
|
+
expect(TestModule[callback].callCount).toEqual 1
|
|
43
|
+
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', 'include', 'extend']
|
|
47
|
+
expect(Object.extended(Joosy.Module.prototype).keys()).toEqual []
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
describe "Joosy.Modules.Renderer", ->
|
|
2
|
+
|
|
3
|
+
beforeEach ->
|
|
4
|
+
@seedGround()
|
|
5
|
+
|
|
6
|
+
class @TestContainer extends Joosy.Module
|
|
7
|
+
@include Joosy.Modules.Renderer
|
|
8
|
+
|
|
9
|
+
@dummyContainer = new @TestContainer
|
|
10
|
+
|
|
11
|
+
class @TestObject extends Joosy.Module
|
|
12
|
+
@include Joosy.Modules.Events
|
|
13
|
+
|
|
14
|
+
constructor: (@value) ->
|
|
15
|
+
|
|
16
|
+
update: (@value) ->
|
|
17
|
+
@trigger 'changed'
|
|
18
|
+
|
|
19
|
+
@dummyObject = new @TestObject("initial")
|
|
20
|
+
|
|
21
|
+
Joosy.namespace 'Joosy.Helpers.Hoge', ->
|
|
22
|
+
@multiplier = (value) ->
|
|
23
|
+
"#{value * 5}"
|
|
24
|
+
|
|
25
|
+
it "should update contents, but only while it is bound to DOM", ->
|
|
26
|
+
@TestContainer.view (locals) ->
|
|
27
|
+
template = (locals) ->
|
|
28
|
+
"#{locals.object.value}"
|
|
29
|
+
|
|
30
|
+
@render(template, locals)
|
|
31
|
+
|
|
32
|
+
elem = $("<div></div>")
|
|
33
|
+
@ground.append elem
|
|
34
|
+
|
|
35
|
+
elem.html @dummyContainer.__renderer({ object: @dummyObject })
|
|
36
|
+
expect(elem.text()).toBe "initial"
|
|
37
|
+
|
|
38
|
+
@dummyObject.update "new"
|
|
39
|
+
|
|
40
|
+
waits 0
|
|
41
|
+
|
|
42
|
+
runs ->
|
|
43
|
+
expect(elem.text()).toBe "new"
|
|
44
|
+
|
|
45
|
+
waits 0
|
|
46
|
+
|
|
47
|
+
runs ->
|
|
48
|
+
@dummyContainer.__removeMetamorphs()
|
|
49
|
+
@dummyObject.update "afterwards"
|
|
50
|
+
|
|
51
|
+
waits 0
|
|
52
|
+
|
|
53
|
+
runs ->
|
|
54
|
+
expect(elem.text()).toBe "new"
|
|
55
|
+
|
|
56
|
+
it "should render resources and keep html up2date", ->
|
|
57
|
+
data = Joosy.Resource.Generic.create zombie: 'rock'
|
|
58
|
+
|
|
59
|
+
@TestContainer.view (locals) ->
|
|
60
|
+
template = (locals) ->
|
|
61
|
+
"#{locals.zombie}"
|
|
62
|
+
|
|
63
|
+
@render(template, locals)
|
|
64
|
+
|
|
65
|
+
elem = $("<div></div>")
|
|
66
|
+
@ground.append elem
|
|
67
|
+
|
|
68
|
+
elem.html @dummyContainer.__renderer(data)
|
|
69
|
+
|
|
70
|
+
waits 0
|
|
71
|
+
|
|
72
|
+
runs ->
|
|
73
|
+
expect(elem.text()).toBe "rock"
|
|
74
|
+
|
|
75
|
+
runs ->
|
|
76
|
+
data 'zombie', 'suck'
|
|
77
|
+
|
|
78
|
+
waits 0
|
|
79
|
+
|
|
80
|
+
runs ->
|
|
81
|
+
expect(elem.text()).toBe "suck"
|
|
82
|
+
|
|
83
|
+
it "should debounce morpher updates", ->
|
|
84
|
+
@TestContainer.view (locals) ->
|
|
85
|
+
template = (locals) ->
|
|
86
|
+
"#{locals.object.value}"
|
|
87
|
+
|
|
88
|
+
@render(template, locals)
|
|
89
|
+
|
|
90
|
+
elem = $("<div></div>")
|
|
91
|
+
@ground.append elem
|
|
92
|
+
|
|
93
|
+
sinon.spy window, 'Metamorph'
|
|
94
|
+
|
|
95
|
+
elem.html @dummyContainer.__renderer({ object: @dummyObject })
|
|
96
|
+
expect(elem.text()).toBe "initial"
|
|
97
|
+
|
|
98
|
+
updater = sinon.spy window.Metamorph.returnValues[0], 'html'
|
|
99
|
+
|
|
100
|
+
@dummyObject.update "new"
|
|
101
|
+
|
|
102
|
+
waits 0
|
|
103
|
+
|
|
104
|
+
runs ->
|
|
105
|
+
expect(elem.text()).toBe "new"
|
|
106
|
+
expect(updater.callCount).toEqual 1
|
|
107
|
+
|
|
108
|
+
runs ->
|
|
109
|
+
@dummyObject.update "don't make"
|
|
110
|
+
@dummyObject.update "me evil"
|
|
111
|
+
|
|
112
|
+
waits 0
|
|
113
|
+
|
|
114
|
+
runs ->
|
|
115
|
+
expect(elem.text()).toBe "me evil"
|
|
116
|
+
expect(updater.callCount).toEqual 2
|
|
117
|
+
|
|
118
|
+
it "should include rendering helpers in locals", ->
|
|
119
|
+
@TestContainer.helpers "Hoge"
|
|
120
|
+
|
|
121
|
+
@TestContainer.view (locals) ->
|
|
122
|
+
template = (locals) ->
|
|
123
|
+
"#{locals.multiplier(10)}"
|
|
124
|
+
|
|
125
|
+
@render(template, locals)
|
|
126
|
+
|
|
127
|
+
elem = $("<div></div>")
|
|
128
|
+
@ground.append elem
|
|
129
|
+
|
|
130
|
+
elem.html @dummyContainer.__renderer({ })
|
|
131
|
+
|
|
132
|
+
expect(elem.text()).toBe "50"
|
|
133
|
+
|
|
134
|
+
it "should include global rendering helpers in locals", ->
|
|
135
|
+
Joosy.Helpers.Application.globalMultiplier = (value) ->
|
|
136
|
+
value * 6
|
|
137
|
+
|
|
138
|
+
@TestContainer.view (locals) ->
|
|
139
|
+
template = (locals) ->
|
|
140
|
+
"#{locals.globalMultiplier(10)}"
|
|
141
|
+
|
|
142
|
+
@render(template, locals)
|
|
143
|
+
|
|
144
|
+
elem = $("<div></div>")
|
|
145
|
+
@ground.append elem
|
|
146
|
+
|
|
147
|
+
elem.html @dummyContainer.__renderer({ })
|
|
148
|
+
|
|
149
|
+
expect(elem.text()).toBe "60"
|