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,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 @@
|
|
|
1
|
+
class @ApplicationPage extends Joosy.Page
|
|
@@ -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,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,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
|