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.
Files changed (98) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +14 -0
  3. data/Gemfile.lock +159 -0
  4. data/Guardfile +30 -0
  5. data/MIT-LICENSE +21 -0
  6. data/README.rdoc +3 -0
  7. data/Rakefile +14 -0
  8. data/app/assets/javascripts/joosy.js.coffee +7 -0
  9. data/app/assets/javascripts/joosy/core/application.js.coffee +28 -0
  10. data/app/assets/javascripts/joosy/core/form.js.coffee +87 -0
  11. data/app/assets/javascripts/joosy/core/helpers.js.coffee +6 -0
  12. data/app/assets/javascripts/joosy/core/joosy.js.coffee +65 -0
  13. data/app/assets/javascripts/joosy/core/layout.js.coffee +47 -0
  14. data/app/assets/javascripts/joosy/core/modules/container.js.coffee +59 -0
  15. data/app/assets/javascripts/joosy/core/modules/events.js.coffee +35 -0
  16. data/app/assets/javascripts/joosy/core/modules/filters.js.coffee +39 -0
  17. data/app/assets/javascripts/joosy/core/modules/log.js.coffee +15 -0
  18. data/app/assets/javascripts/joosy/core/modules/module.js.coffee +43 -0
  19. data/app/assets/javascripts/joosy/core/modules/renderer.js.coffee +116 -0
  20. data/app/assets/javascripts/joosy/core/modules/time_manager.js.coffee +25 -0
  21. data/app/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee +58 -0
  22. data/app/assets/javascripts/joosy/core/page.js.coffee +156 -0
  23. data/app/assets/javascripts/joosy/core/preloader.js.coffee +5 -0
  24. data/app/assets/javascripts/joosy/core/resource/generic.js.coffee +61 -0
  25. data/app/assets/javascripts/joosy/core/resource/rest.js.coffee +76 -0
  26. data/app/assets/javascripts/joosy/core/resource/rest_collection.js.coffee +48 -0
  27. data/app/assets/javascripts/joosy/core/router.js.coffee +89 -0
  28. data/app/assets/javascripts/joosy/core/templaters/rails_jst.js.coffee +20 -0
  29. data/app/assets/javascripts/joosy/core/widget.js.coffee +41 -0
  30. data/app/assets/javascripts/joosy/preloaders/caching.js.coffee +94 -0
  31. data/app/assets/javascripts/joosy/preloaders/inline.js.coffee +55 -0
  32. data/app/helpers/joosy/sprockets_helper.rb +23 -0
  33. data/app/views/layouts/json_wrapper.json.erb +1 -0
  34. data/joosy.gemspec +25 -0
  35. data/lib/joosy.rb +9 -0
  36. data/lib/joosy/forms.rb +47 -0
  37. data/lib/joosy/rails/engine.rb +17 -0
  38. data/lib/joosy/rails/version.rb +5 -0
  39. data/lib/rails/generators/joosy/application_generator.rb +41 -0
  40. data/lib/rails/generators/joosy/joosy_base.rb +30 -0
  41. data/lib/rails/generators/joosy/layout_generator.rb +32 -0
  42. data/lib/rails/generators/joosy/page_generator.rb +44 -0
  43. data/lib/rails/generators/joosy/preloader_generator.rb +32 -0
  44. data/lib/rails/generators/joosy/resource_generator.rb +29 -0
  45. data/lib/rails/generators/joosy/templates/app.js.coffee +10 -0
  46. data/lib/rails/generators/joosy/templates/app/helpers/application.js.coffee +4 -0
  47. data/lib/rails/generators/joosy/templates/app/layouts/application.js.coffee +2 -0
  48. data/lib/rails/generators/joosy/templates/app/layouts/template.js.coffee +2 -0
  49. data/lib/rails/generators/joosy/templates/app/pages/application.js.coffee +1 -0
  50. data/lib/rails/generators/joosy/templates/app/pages/template.js.coffee +5 -0
  51. data/lib/rails/generators/joosy/templates/app/pages/welcome/index.js.coffee +22 -0
  52. data/lib/rails/generators/joosy/templates/app/resources/template.js.coffee +2 -0
  53. data/lib/rails/generators/joosy/templates/app/routes.js.coffee +8 -0
  54. data/lib/rails/generators/joosy/templates/app/templates/layouts/application.jst.hamlc +2 -0
  55. data/lib/rails/generators/joosy/templates/app/templates/pages/welcome/index.jst.hamlc +7 -0
  56. data/lib/rails/generators/joosy/templates/app/widgets/template.js.coffee +2 -0
  57. data/lib/rails/generators/joosy/templates/app_controller.rb +9 -0
  58. data/lib/rails/generators/joosy/templates/app_preloader.js.coffee.erb +13 -0
  59. data/lib/rails/generators/joosy/templates/preload.html.erb +26 -0
  60. data/lib/rails/generators/joosy/templates/preload.html.haml +19 -0
  61. data/lib/rails/generators/joosy/widget_generator.rb +32 -0
  62. data/spec/javascripts/helpers/spec_helper.js.coffee +44 -0
  63. data/spec/javascripts/joosy/core/application_spec.js.coffee +40 -0
  64. data/spec/javascripts/joosy/core/form_spec.js.coffee +141 -0
  65. data/spec/javascripts/joosy/core/joosy_spec.js.coffee +72 -0
  66. data/spec/javascripts/joosy/core/layout_spec.js.coffee +50 -0
  67. data/spec/javascripts/joosy/core/modules/container_spec.js.coffee +92 -0
  68. data/spec/javascripts/joosy/core/modules/events_spec.js.coffee +53 -0
  69. data/spec/javascripts/joosy/core/modules/filters_spec.js.coffee +71 -0
  70. data/spec/javascripts/joosy/core/modules/log_spec.js.coffee +15 -0
  71. data/spec/javascripts/joosy/core/modules/module_spec.js.coffee +47 -0
  72. data/spec/javascripts/joosy/core/modules/renderer_spec.js.coffee +149 -0
  73. data/spec/javascripts/joosy/core/modules/time_manager_spec.js.coffee +25 -0
  74. data/spec/javascripts/joosy/core/modules/widget_manager_spec.js.coffee +75 -0
  75. data/spec/javascripts/joosy/core/page_spec.js.coffee +175 -0
  76. data/spec/javascripts/joosy/core/resource/generic_spec.js.coffee +35 -0
  77. data/spec/javascripts/joosy/core/resource/rest_collection_spec.js.coffee +65 -0
  78. data/spec/javascripts/joosy/core/resource/rest_spec.js.coffee +108 -0
  79. data/spec/javascripts/joosy/core/router_spec.js.coffee +123 -0
  80. data/spec/javascripts/joosy/core/templaters/rails_jst_spec.js.coffee +25 -0
  81. data/spec/javascripts/joosy/core/widget_spec.js.coffee +51 -0
  82. data/spec/javascripts/joosy/preloaders/caching_spec.js.coffee +36 -0
  83. data/spec/javascripts/joosy/preloaders/inline_spec.js.coffee +16 -0
  84. data/spec/javascripts/support/assets/coolface.jpg +0 -0
  85. data/spec/javascripts/support/assets/okay.jpg +0 -0
  86. data/spec/javascripts/support/assets/test.js +1 -0
  87. data/spec/javascripts/support/jasmine.yml +74 -0
  88. data/spec/javascripts/support/jasmine_config.rb +23 -0
  89. data/spec/javascripts/support/jasmine_runner.rb +32 -0
  90. data/spec/javascripts/support/sinon-1.3.1.js +3469 -0
  91. data/spec/javascripts/support/sinon-ie-1.3.1.js +82 -0
  92. data/vendor/assets/javascripts/base64.js +135 -0
  93. data/vendor/assets/javascripts/inflection.js +656 -0
  94. data/vendor/assets/javascripts/jquery.form.js +980 -0
  95. data/vendor/assets/javascripts/jquery.hashchange.js +390 -0
  96. data/vendor/assets/javascripts/metamorph.js +409 -0
  97. data/vendor/assets/javascripts/sugar.js +6040 -0
  98. metadata +232 -0
@@ -0,0 +1,32 @@
1
+ require 'rails/generators/named_base'
2
+
3
+ module Joosy
4
+ module Generators
5
+ class PreloaderGenerator < ::Rails::Generators::NamedBase
6
+ class_option :template_engine, :type => :string,
7
+ :desc => "Generate templates for specified engine."
8
+
9
+ source_root File.join(File.dirname(__FILE__), 'templates')
10
+
11
+ def create_preloader_files
12
+ unless class_path.empty?
13
+ puts <<HELP
14
+ Usage: rails generate joosy:preloader joosy_app_name
15
+ HELP
16
+ exit 1
17
+ end
18
+
19
+ template "app_preloader.js.coffee.erb", "app/assets/javascripts/#{file_name}_preloader.js.coffee.erb"
20
+
21
+ empty_directory "app/controllers"
22
+ template "app_controller.rb", "app/controllers/#{file_name}_controller.rb"
23
+
24
+ empty_directory "app/views/layouts"
25
+ template "preload.html.#{options[:template_engine]}",
26
+ "app/views/layouts/#{file_name}.html.#{options[:template_engine]}"
27
+
28
+ route "match '#{file_name}' => '#{file_name}#index'"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ require 'rails/generators/joosy/joosy_base'
2
+
3
+ module Joosy
4
+ module Generators
5
+ class ResourceGenerator < ::Rails::Generators::JoosyBase
6
+ source_root File.join(File.dirname(__FILE__), 'templates')
7
+
8
+ def create_files
9
+ super
10
+
11
+ empty_directory "#{app_path}/resources"
12
+ template "app/resources/template.js.coffee", "#{app_path}/resources/#{file_name}.js.coffee"
13
+ end
14
+
15
+ protected
16
+
17
+ def app_path
18
+ unless class_path.size == 1
19
+ puts <<HELP
20
+ Usage: rails generate joosy:resource joosy_app_name/resource_name
21
+ Tip: resource_name is better to be singular
22
+ HELP
23
+ exit 1
24
+ end
25
+ class_path[0]
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ #= require hamlcoffee
2
+ #= require joosy
3
+ #
4
+ #= require_tree ./<%= file_name %>/helpers
5
+ #= require_tree ./<%= file_name %>/templates
6
+ #= require_tree ./<%= file_name %>/resources
7
+ #= require_tree ./<%= file_name %>/widgets
8
+ #= require_tree ./<%= file_name %>/layouts
9
+ #= require_tree ./<%= file_name %>/pages
10
+ #= require_tree ./<%= file_name %>
@@ -0,0 +1,4 @@
1
+ Joosy.helpers 'Application', ->
2
+
3
+ # helloWorld = (name) ->
4
+ # "Hello World, #{name}"
@@ -0,0 +1,2 @@
1
+ class @ApplicationLayout extends Joosy.Layout
2
+ @view 'application'
@@ -0,0 +1,2 @@
1
+ class @<%= file_name.camelize %>Layout extends ApplicationLayout
2
+ @view '<%= file_name %>'
@@ -0,0 +1 @@
1
+ class @ApplicationPage extends Joosy.Page
@@ -0,0 +1,5 @@
1
+ Joosy.namespace '<%= namespace_name %>', ->
2
+
3
+ class @<%= file_name.camelize %>Page extends ApplicationPage
4
+ @layout <%= layout_name.camelize %>Layout
5
+ @view '<%= file_name %>'
@@ -0,0 +1,22 @@
1
+ Joosy.namespace 'Welcome', ->
2
+
3
+ class @IndexPage extends ApplicationPage
4
+ @layout ApplicationLayout
5
+ @view 'index'
6
+
7
+ @afterLoad ->
8
+ @startHeartbeat()
9
+ @content.css
10
+ 'padding-top': "#{$(window).height() / 2 - 160}px"
11
+
12
+ elements:
13
+ content: '#content'
14
+ joosy: '.joosy'
15
+
16
+ events:
17
+ 'mouseover $joosy': -> clearInterval @heartbeat
18
+ 'mouseout $joosy': 'startHeartbeat'
19
+
20
+ startHeartbeat: ->
21
+ @heartbeat = @setInterval 1500, =>
22
+ @joosy.animate({opacity: 0.8}, 300).animate({opacity: 1}, 300)
@@ -0,0 +1,2 @@
1
+ class @<%= file_name.camelize %>Resource extends Joosy.Resource.REST
2
+ @entity '<%= file_name %>'
@@ -0,0 +1,8 @@
1
+ Joosy.Router.map
2
+ 404 : (path) -> alert "Page '#{path}' was not found :("
3
+ '/' : Welcome.IndexPage
4
+ # '/resources' :
5
+ # '/' : Resource.IndexPage
6
+ # '/:id' : Resource.ShowPage
7
+ # '/:id/edit' : Resource.EditPage
8
+ # '/new' : Resource.EditPage
@@ -0,0 +1,2 @@
1
+ #page{:style => 'font-family: "Lucida Grande", "Verdana"; text-align: center'}
2
+ .content{:id => @yield()}
@@ -0,0 +1,7 @@
1
+ #wrapper
2
+ #content
3
+ %h1 Welcome aboard
4
+ %h2{:style => 'margin-bottom: 30px'} You’re still riding Ruby on Rails.
5
+ .joosy{:style => 'background: #F71; border-radius: 10px; width: 250px; display: inline-block'}
6
+ %div{:style => 'color: #FFF; padding: 10px;'}
7
+ But it's so joosy this time!
@@ -0,0 +1,2 @@
1
+ class @<%= file_name.camelize %>Widget extends Joosy.Widget
2
+ @view '<%= file_name %>'
@@ -0,0 +1,9 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Controller < ApplicationController
3
+ helper 'joosy/sprockets'
4
+
5
+ def index
6
+ render nothing: true, layout: '<%= file_path %>'
7
+ end
8
+ end
9
+ <% end -%>
@@ -0,0 +1,13 @@
1
+ <%= "<%= require_joosy_preloader_for '" %><%= file_name %><%= "', preloader: 'caching', force: false %" + ">" %>
2
+
3
+ bootstrap = ->
4
+ $('#preloader').remove()
5
+ Joosy.Application.initialize '<%= file_name %>','#application',
6
+ environment: window.joosy.environment
7
+ debug: false
8
+
9
+ window.onload = ->
10
+ Preloader.load window.joosy.libraries,
11
+ complete: bootstrap
12
+ start: -> document.getElementById('preloader').style.display = 'block'
13
+ progress: (percent) -> document.getElementById('percents').innerHTML = percent + '%'
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= file_path %></title>
5
+
6
+ <script type="text/javascript">
7
+ window.joosy = {
8
+ libraries: <%= "<%= extract_sources_and_sizes_from_include_tag('#{file_path}') %"+">" %>,
9
+ environment: '<%= "<%= Rails.env.to_s %"+">" %>'
10
+ };
11
+ </script>
12
+
13
+ <%= "<%= stylesheet_link_tag 'application' %"+">" %>
14
+ <%= "<%= csrf_meta_tags %"+">" %>
15
+ </head>
16
+
17
+ <body>
18
+ <%= "<%= javascript_include_tag '#{file_path}_preloader' %"+">" %>
19
+ <div id="application">
20
+ <div id="preloader">
21
+ Loading application...
22
+ <span id="percents">0%</span>
23
+ </div>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,19 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title> <%= file_path %>
5
+
6
+ javascript:
7
+ window.preload = {
8
+ libraries: #{extract_sources_and_sizes_from_include_tag('<%= file_path %>')}
9
+ };
10
+
11
+ = stylesheet_link_tag 'application'
12
+ = csrf_meta_tags
13
+
14
+ %body
15
+ = javascript_include_tag '<%= file_path %>_preloader'
16
+ #application
17
+ #preloader
18
+ Loading application...
19
+ %span#percents 0%
@@ -0,0 +1,32 @@
1
+ require 'rails/generators/joosy/joosy_base'
2
+
3
+ module Joosy
4
+ module Generators
5
+ class WidgetGenerator < ::Rails::Generators::JoosyBase
6
+ source_root File.join(File.dirname(__FILE__), 'templates')
7
+
8
+ def create_files
9
+ super
10
+
11
+ empty_directory "#{app_path}/widgets"
12
+ template "app/widgets/template.js.coffee", "#{app_path}/widgets/#{file_name}.js.coffee"
13
+
14
+ empty_directory "#{app_path}/templates/widgets"
15
+ create_file "#{app_path}/templates/widgets/#{file_name}.jst.#{options[:template_kind]}"
16
+ end
17
+
18
+ protected
19
+
20
+ def app_path
21
+ unless class_path.size == 1
22
+ puts <<HELP
23
+ Usage: rails generate joosy:widget joosy_app_name/widget_name
24
+ Tip: do not add Widget suffix to widget_name
25
+ HELP
26
+ exit 1
27
+ end
28
+ class_path[0]
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,44 @@
1
+ beforeEach ->
2
+ window.JST = {}
3
+ $('body').append('<div id="ground">')
4
+ @ground = $('body #ground')
5
+ @seedGround = ->
6
+ @ground.html('
7
+ <div id="application" class="application">
8
+ <div id="header" class="header" />
9
+ <div id="wrapper" class="wrapper">
10
+ <div id="content" class="content">
11
+ <div id="post1" class="post" />
12
+ <div id="post2" class="post" />
13
+ <div id="post3" class="post" />
14
+ </div>
15
+ <div id="sidebar" class="sidebar">
16
+ <div id="widget1" class="widget" />
17
+ <div id="widget2" class="widget" />
18
+ </div>
19
+ </div>
20
+ <div id="footer" class="footer" />
21
+ </div>
22
+ ')
23
+ @addMatchers
24
+ toBeSequenced: () ->
25
+ if !Object.isArray(@actual) || @actual.length == 0
26
+ console.log 'toBeSequenced: not array or empty array given'
27
+ return false
28
+ i = 0
29
+ for spy in @actual
30
+ unless spy.callCount == 1
31
+ console.log "toBeSequenced: spy ##{i} was called #{spy.callCount} times"
32
+ return false
33
+ i++
34
+ if @actual.length > 1
35
+ for spy in @actual.from(1)
36
+ i = @actual.indexOf spy
37
+ previous = @actual[i - 1]
38
+ unless spy.calledAfter previous
39
+ console.log "toBeSequenced: spy ##{i} wasn't called after spy ##{i - 1}"
40
+ return false
41
+ return true
42
+
43
+ afterEach ->
44
+ @ground.remove() unless @polluteGround
@@ -0,0 +1,40 @@
1
+ describe "Joosy.Application", ->
2
+
3
+ beforeEach ->
4
+ sinon.stub(Joosy.Router, "setupRoutes")
5
+ @seedGround()
6
+
7
+ afterEach ->
8
+ Joosy.Router.setupRoutes.restore()
9
+
10
+ it "should initialize", ->
11
+ Joosy.Application.initialize 'app', '#application'
12
+ expect(Joosy.Application.page).toBeUndefined()
13
+ expect(Joosy.Application.selector).toEqual '#application'
14
+ expect(Joosy.Application.sandboxSelector).toMatch /#[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}/
15
+ expect($(Joosy.Application.sandboxSelector).length).toEqual 1
16
+ expect(Joosy.Router.setupRoutes.callCount).toEqual 1
17
+ expect(Joosy.Application.name).toEqual 'app'
18
+
19
+ it "should set container", ->
20
+ expect(Joosy.Application.content()).toEqual $('#application')
21
+
22
+ it "should properly initialize and save pages", ->
23
+ spy = sinon.spy()
24
+ class Page1
25
+ constructor: spy
26
+ class Page2
27
+ constructor: spy
28
+
29
+ Joosy.Application.setCurrentPage(Page1, {foo: 'bar'})
30
+
31
+ expect(Joosy.Application.page instanceof Page1).toBeTruthy()
32
+ expect(spy.callCount).toEqual 1
33
+ expect(spy.args[0]).toEqual [{foo: 'bar'}, undefined]
34
+
35
+ Joosy.Application.setCurrentPage(Page2, {bar: 'baz'})
36
+
37
+ expect(Joosy.Application.page instanceof Page2).toBeTruthy()
38
+ expect(spy.callCount).toEqual 2
39
+ expect(spy.args[1][0]).toEqual {bar: 'baz'}
40
+ expect(spy.args[1][1] instanceof Page1).toBeTruthy()
@@ -0,0 +1,141 @@
1
+ describe "Joosy.Form", ->
2
+
3
+ beforeEach ->
4
+ @server = sinon.fakeServer.create()
5
+ @seedGround()
6
+ @nudeForm = "<form id='nude'><input name='test[foo]'/><input name='test[bar]'/></form>"
7
+ @putForm = "<form id='put' method='put'><input name='test[camel_baz]'/></form>"
8
+ @moreForm = "<form id='more' method='put'><input name='test[ololo]'/></form>"
9
+
10
+ @ground.find('#sidebar').after(@nudeForm).after(@putForm).after(@moreForm)
11
+
12
+ @nudeForm = $('#nude')
13
+ @putForm = $('#put')
14
+ @moreForm = $('#more')
15
+
16
+ class Test extends Joosy.Resource.REST
17
+ @entity 'test'
18
+
19
+ @resource = Test.create
20
+ foo: 'foo',
21
+ bar: 'bar'
22
+ camelBaz: 'baz'
23
+
24
+ afterEach ->
25
+ @server.restore()
26
+
27
+ describe "Initialization", ->
28
+
29
+ beforeEach ->
30
+ @spy = sinon.spy $.fn, 'ajaxForm'
31
+
32
+ afterEach ->
33
+ @spy.restore()
34
+
35
+ it "should properly act with options", ->
36
+ formWithProperties = new Joosy.Form @nudeForm, invalidationClass: 'fluffy'
37
+ expect(formWithProperties.container).toEqual @nudeForm
38
+ expect(formWithProperties.invalidationClass).toEqual 'fluffy'
39
+ expect(formWithProperties.fields.length).toEqual 2
40
+
41
+ expect(@spy.callCount).toEqual 1
42
+
43
+ it "should properly act with callback", ->
44
+ formWithCallback = new Joosy.Form @putForm, callback=sinon.spy()
45
+ expect(formWithCallback.container).toEqual @putForm
46
+ expect(formWithCallback.invalidationClass).toEqual 'field_with_errors'
47
+ expect(formWithCallback.success).toBe callback
48
+ expect(formWithCallback.fields.length).toEqual 1
49
+
50
+ expect(@spy.callCount).toEqual 1
51
+
52
+ it "should hijack form method if it differs from POST/GET", ->
53
+ form = new Joosy.Form @putForm, callback=sinon.spy()
54
+ marker = @putForm.find "input[type=hidden]"
55
+ expect(@putForm.attr('method')?.toLowerCase()).toEqual 'post'
56
+ expect(marker.attr 'name').toEqual '_method'
57
+ expect(marker.attr 'value').toEqual 'put'
58
+
59
+ describe "Filling", ->
60
+
61
+ beforeEach ->
62
+ @nudeForm = new Joosy.Form @nudeForm
63
+ @putForm = new Joosy.Form @putForm
64
+ @moreForm = new Joosy.Form @moreForm
65
+
66
+ it "should fill form and set propert action and method", ->
67
+ @nudeForm.fill @resource
68
+ expect(@nudeForm.fields[0].value).toEqual 'foo'
69
+ expect(@nudeForm.fields[1].value).toEqual 'bar'
70
+ expect(@nudeForm.container.attr('method').toLowerCase()).toEqual 'post'
71
+ expect(@nudeForm.container.attr 'action').toEqual '/tests/'
72
+
73
+ it "should fill form with camelized properties", ->
74
+ @putForm.fill @resource
75
+ expect(@putForm.fields[0].value).toEqual 'baz'
76
+ expect(@putForm.container.attr('method').toLowerCase()).toEqual 'post'
77
+ expect(@putForm.container.attr 'action').toEqual '/tests/'
78
+
79
+ it "should fill form with decorator", ->
80
+ @moreForm.fill @resource, (e) ->
81
+ e.ololo = e.camelBaz
82
+ e
83
+ expect(@moreForm.fields[0].value).toEqual 'baz'
84
+
85
+ describe "Callbacks", ->
86
+ beforeEach ->
87
+ @nudeForm = new Joosy.Form @nudeForm, @spy=sinon.spy()
88
+ @nudeForm.fill @resource
89
+ @nudeForm.container.submit()
90
+ @target = @server.requests.last()
91
+
92
+ it "should trigger 'success'", ->
93
+ expect(@target.method).toEqual 'POST'
94
+ expect(@target.url).toEqual '/tests/'
95
+ @target.respond 200, 'Content-Type': 'application/json', '{"form": "works"}'
96
+ expect(@spy.callCount).toEqual 1
97
+ expect(@spy.args[0][0]).toEqual {form: 'works'}
98
+
99
+ it "should fill class for invalidated fields by default", ->
100
+ @target.respond 422, 'Content-Type': 'application/json', '{"test[foo]": "error!"}'
101
+ expect($(@nudeForm.fields[0]).attr 'class').toEqual 'field_with_errors'
102
+
103
+ it "should trigger 'error' and complete default action if it returned true", ->
104
+ @nudeForm.error = sinon.spy ->
105
+ true
106
+ @target.respond 422, 'Content-Type': 'application/json', '{"test[foo]": "error!"}'
107
+ expect($(@nudeForm.fields[0]).attr 'class').toEqual 'field_with_errors'
108
+ expect(@nudeForm.error.callCount).toEqual 1
109
+ expect(@nudeForm.error.args[0][0]).toEqual Object.extended
110
+ "test[foo]": "error!"
111
+
112
+ it "should trigger 'error' and skip default action if it returned false", ->
113
+ @nudeForm.error = sinon.spy ->
114
+ false
115
+ @target.respond 422, 'Content-Type': 'application/json', '{"test[foo]": "error!"}'
116
+ expect($(@nudeForm.fields[0]).attr 'class').toNotEqual 'field_with_errors'
117
+ expect(@nudeForm.error.callCount).toEqual 1
118
+
119
+ it "should clear fields before another submit", ->
120
+ @target.respond 422, 'Content-Type': 'application/json', '{"test[foo]": "error!"}'
121
+ expect($(@nudeForm.fields[0]).attr 'class').toEqual 'field_with_errors'
122
+ @nudeForm.container.submit()
123
+ expect($(@nudeForm.fields[0]).attr 'class').toNotEqual 'field_with_errors'
124
+
125
+ it "should trigger 'before' and do default action if it returns true", ->
126
+ @target.respond 422, 'Content-Type': 'application/json', '{"test[foo]": "error!"}'
127
+ expect($(@nudeForm.fields[0]).attr 'class').toEqual 'field_with_errors'
128
+ @nudeForm.before = sinon.spy ->
129
+ true
130
+ @nudeForm.container.submit()
131
+ expect($(@nudeForm.fields[0]).attr 'class').toNotEqual 'field_with_errors'
132
+ expect(@nudeForm.before.callCount).toEqual 1
133
+
134
+ it "should trigger 'before' and skip default action if it returns false", ->
135
+ @target.respond 422, 'Content-Type': 'application/json', '{"test[foo]": "error!"}'
136
+ expect($(@nudeForm.fields[0]).attr 'class').toEqual 'field_with_errors'
137
+ @nudeForm.before = sinon.spy ->
138
+ false
139
+ @nudeForm.container.submit()
140
+ expect($(@nudeForm.fields[0]).attr 'class').toEqual 'field_with_errors'
141
+ expect(@nudeForm.before.callCount).toEqual 1