joosy 0.1.0.RC1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|