alpha-simprini-engine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +38 -0
  4. data/app/assets/javascripts/alpha_simprini.coffee +15 -0
  5. data/app/assets/javascripts/alpha_simprini/application.coffee +22 -0
  6. data/app/assets/javascripts/alpha_simprini/coffee_kup/binding.coffee +119 -0
  7. data/app/assets/javascripts/alpha_simprini/coffee_kup/helpers.coffee +17 -0
  8. data/app/assets/javascripts/alpha_simprini/coffee_kup/tags.coffee +7 -0
  9. data/app/assets/javascripts/alpha_simprini/collection.coffee +62 -0
  10. data/app/assets/javascripts/alpha_simprini/delegate.coffee +21 -0
  11. data/app/assets/javascripts/alpha_simprini/event.coffee +75 -0
  12. data/app/assets/javascripts/alpha_simprini/html.coffee +56 -0
  13. data/app/assets/javascripts/alpha_simprini/mixin.coffee +10 -0
  14. data/app/assets/javascripts/alpha_simprini/model.coffee +137 -0
  15. data/app/assets/javascripts/alpha_simprini/models/radio_selection_model.coffee +9 -0
  16. data/app/assets/javascripts/alpha_simprini/packer.coffee +93 -0
  17. data/app/assets/javascripts/alpha_simprini/template_helpers.coffee +8 -0
  18. data/app/assets/javascripts/alpha_simprini/view.coffee +182 -0
  19. data/app/assets/javascripts/alpha_simprini/views/canvas.coffee +2 -0
  20. data/app/assets/javascripts/alpha_simprini/views/horizontal_split.coffee +9 -0
  21. data/app/assets/javascripts/alpha_simprini/views/panel.coffee +2 -0
  22. data/app/assets/javascripts/alpha_simprini/views/splitter.coffee +2 -0
  23. data/app/assets/javascripts/alpha_simprini/views/stage.coffee +7 -0
  24. data/app/assets/javascripts/alpha_simprini/views/vertical_split.coffee +8 -0
  25. data/app/assets/javascripts/alpha_simprini/views/viewport.coffee +0 -0
  26. data/app/assets/javascripts/bundle.js +16416 -0
  27. data/app/assets/javascripts/lib/backbone.coffee +11 -0
  28. data/app/assets/javascripts/lib/koffeecup_backbone_databind.coffee +25 -0
  29. data/app/assets/javascripts/lib/module.coffee +15 -0
  30. data/app/assets/javascripts/lib/state_machine.coffee +33 -0
  31. data/app/assets/javascripts/lib/string.coffee +13 -0
  32. data/app/assets/javascripts/qunit.js +1513 -0
  33. data/app/assets/javascripts/test.coffee +4 -0
  34. data/app/assets/javascripts/test/alpha_simprini/coffee_kup/binding.coffee +118 -0
  35. data/app/assets/javascripts/test/alpha_simprini/coffee_kup/helpers.coffee +10 -0
  36. data/app/assets/javascripts/test/alpha_simprini/coffee_kup/tags.coffee +18 -0
  37. data/app/assets/javascripts/test/alpha_simprini/collection.coffee +7 -0
  38. data/app/assets/javascripts/test/alpha_simprini/event.coffee +43 -0
  39. data/app/assets/javascripts/test/alpha_simprini/model.coffee +63 -0
  40. data/app/assets/javascripts/test/alpha_simprini/view.coffee +72 -0
  41. data/app/assets/javascripts/test/alpha_simprini/views/canvas.coffee +8 -0
  42. data/app/assets/javascripts/test/alpha_simprini/views/horizontal_split.coffee +13 -0
  43. data/app/assets/javascripts/test/alpha_simprini/views/vertical_split.coffee +13 -0
  44. data/app/assets/javascripts/test/backbone/collection.js +345 -0
  45. data/app/assets/javascripts/test/backbone/events.js +86 -0
  46. data/app/assets/javascripts/test/backbone/model.js +426 -0
  47. data/app/assets/javascripts/test/backbone/view.js +137 -0
  48. data/app/assets/stylesheets/bootstrap.sass +6 -0
  49. data/app/assets/stylesheets/paneling.sass +2 -0
  50. data/app/assets/stylesheets/qunit.scss +228 -0
  51. data/app/assets/stylesheets/table.sass +10 -0
  52. data/app/assets/stylesheets/typography.sass +19 -0
  53. data/app/controllers/alpha_simprini/test_controller.rb +3 -0
  54. data/app/controllers/resources_controller.rb +7 -0
  55. data/app/views/alpha_simprini/test/root.rb +13 -0
  56. data/app/views/resources/base.rb +2 -0
  57. data/app/views/resources/edit.rb +9 -0
  58. data/app/views/resources/form.rb +26 -0
  59. data/app/views/resources/index.rb +41 -0
  60. data/app/views/resources/new.rb +9 -0
  61. data/app/views/resources/show.rb +42 -0
  62. data/app/views/resources/show_has_many.rb +28 -0
  63. data/config/locales/en.yml +4 -0
  64. data/config/routes.rb +3 -0
  65. data/lib/alpha-simprini-engine.rb +33 -0
  66. data/lib/alpha-simprini-engine/version.rb +3 -0
  67. data/lib/alpha_simprini/directive_processor.rb +77 -0
  68. data/lib/alpha_simprini/packer.rb +161 -0
  69. data/lib/alpha_simprini/page.rb +37 -0
  70. data/lib/tasks/alpha-simprini-engine_tasks.rake +4 -0
  71. data/test/alpha-simprini-engine_test.rb +7 -0
  72. data/test/dummy/Rakefile +7 -0
  73. data/test/dummy/app/assets/javascripts/application.js +9 -0
  74. data/test/dummy/app/assets/stylesheets/application.css +7 -0
  75. data/test/dummy/app/controllers/application_controller.rb +3 -0
  76. data/test/dummy/app/helpers/application_helper.rb +2 -0
  77. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  78. data/test/dummy/config.ru +4 -0
  79. data/test/dummy/config/application.rb +42 -0
  80. data/test/dummy/config/boot.rb +10 -0
  81. data/test/dummy/config/database.yml +25 -0
  82. data/test/dummy/config/environment.rb +5 -0
  83. data/test/dummy/config/environments/development.rb +27 -0
  84. data/test/dummy/config/environments/production.rb +51 -0
  85. data/test/dummy/config/environments/test.rb +39 -0
  86. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  87. data/test/dummy/config/initializers/inflections.rb +10 -0
  88. data/test/dummy/config/initializers/mime_types.rb +5 -0
  89. data/test/dummy/config/initializers/secret_token.rb +7 -0
  90. data/test/dummy/config/initializers/session_store.rb +8 -0
  91. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  92. data/test/dummy/config/locales/en.yml +4 -0
  93. data/test/dummy/config/routes.rb +58 -0
  94. data/test/dummy/db/development.sqlite3 +0 -0
  95. data/test/dummy/log/development.log +800 -0
  96. data/test/dummy/public/404.html +26 -0
  97. data/test/dummy/public/422.html +26 -0
  98. data/test/dummy/public/500.html +26 -0
  99. data/test/dummy/public/favicon.ico +0 -0
  100. data/test/dummy/script/rails +6 -0
  101. data/test/dummy/tmp/cache/assets/C24/D70/sprockets%2F388a550030239f3784f207fa32954f64 +0 -0
  102. data/test/dummy/tmp/cache/assets/C34/620/sprockets%2F097ee8532856d48d70420c006f475889 +0 -0
  103. data/test/dummy/tmp/cache/assets/C6F/710/sprockets%2F908d18b0f21c18dad508851126164a41 +0 -0
  104. data/test/dummy/tmp/cache/assets/CA7/120/sprockets%2F35278a6c0150c40394fe02629c8b0eb9 +0 -0
  105. data/test/dummy/tmp/cache/assets/CDB/A80/sprockets%2F443b1c6e71b482fdd83b1833b7e27712 +0 -0
  106. data/test/dummy/tmp/cache/assets/CE3/FB0/sprockets%2F6d3f87a4232e0368bb86760780c5f1bd +0 -0
  107. data/test/dummy/tmp/cache/assets/D1C/160/sprockets%2F87876f7e55ebc78ae11c6c08a27f0605 +0 -0
  108. data/test/dummy/tmp/cache/assets/D26/6C0/sprockets%2F65bce2254bb3140a50326ea1654ea5df +0 -0
  109. data/test/dummy/tmp/cache/assets/D26/FA0/sprockets%2F1f50f59148df5f3e2ab889df381d9744 +0 -0
  110. data/test/dummy/tmp/cache/assets/D36/220/sprockets%2F841654b01d89eada195d7d1fe10b57b0 +0 -0
  111. data/test/dummy/tmp/cache/assets/D47/410/sprockets%2Ff1fe319eb4064bd5b861ac28f7d76555 +18122 -0
  112. data/test/dummy/tmp/cache/assets/D57/1E0/sprockets%2Fe267e3e1059799c429e4f5cfb95ec53c +0 -0
  113. data/test/dummy/tmp/cache/assets/D64/3E0/sprockets%2Fb49b7f8034b81ec601bc32fb127fbe08 +0 -0
  114. data/test/dummy/tmp/cache/assets/D65/850/sprockets%2F7a9b6a0e2d51adb43a1d3f859213e6b8 +15469 -0
  115. data/test/dummy/tmp/cache/assets/D6C/E30/sprockets%2Fcc7322b05ac2bef75e9f4f145d38117f +0 -0
  116. data/test/dummy/tmp/cache/assets/D7D/E00/sprockets%2Fce33b82451c73df1cfec69928b4f77b6 +0 -0
  117. data/test/dummy/tmp/cache/assets/D85/5D0/sprockets%2Fcf743946c378c148b19ce78eeaa9cc75 +0 -0
  118. data/test/dummy/tmp/cache/assets/DBB/560/sprockets%2F5a1d70cf7dd81a5ab5ce7a40a3a38d06 +0 -0
  119. data/test/dummy/tmp/cache/assets/DC1/670/sprockets%2Fefdfad0542298a1db90d24dc27ecc250 +0 -0
  120. data/test/dummy/tmp/cache/assets/DC5/1E0/sprockets%2F7517f22ad0f9dc13b8f0f6e0cc0e5de2 +0 -0
  121. data/test/dummy/tmp/cache/assets/DCC/220/sprockets%2F28d953c6ab9cc9a7db15600aabc6d77d +208 -0
  122. data/test/dummy/tmp/cache/assets/DCF/DF0/sprockets%2Ff0d3068f05825e1dfd9f5aaba946d3dc +0 -0
  123. data/test/dummy/tmp/cache/assets/DD3/0E0/sprockets%2F3e9e08a334bae7deadb5335f5e4f195f +0 -0
  124. data/test/dummy/tmp/cache/assets/DDB/980/sprockets%2Fbd2abc80a17c901e2f497f88f9be58cf +0 -0
  125. data/test/dummy/tmp/cache/assets/E00/ED0/sprockets%2Ffecf3bffeb200a47e96bd04cbc878076 +1535 -0
  126. data/test/dummy/tmp/cache/assets/EFB/560/sprockets%2Fbca0daf751c020cdeddabbefa51cb6ea +0 -0
  127. data/test/dummy/tmp/restart.txt +0 -0
  128. data/test/test_helper.rb +10 -0
  129. metadata +326 -0
@@ -0,0 +1,4 @@
1
+ #= require alpha_simprini
2
+ #= require qunit
3
+ #= require_tree ./test
4
+
@@ -0,0 +1,118 @@
1
+ @module "AS.CK.Binding"
2
+ render = (locals, template) ->
3
+ locals.hardcode = AS.TemplateHelpers
4
+ jQuery CoffeeKup.render template, locals
5
+
6
+ add_remove_do = (elements..., fn) ->
7
+ element.appendTo(document.body) for element in elements
8
+ fn.call()
9
+ element.remove() for element in elements
10
+
11
+ test "bind", ->
12
+ model = new AS.Model
13
+ model.set property:"value"
14
+
15
+ bound = render model:model, ->
16
+ div -> bind @model, "property"
17
+
18
+ bound_get = render model:model, ->
19
+ div -> bind @model, "property", -> "#{this}-GOT"
20
+
21
+ add_remove_do bound, bound_get, =>
22
+ equal bound.find("span").text(), "value", "binds initial value to a span"
23
+ equal bound_get.find("span").text(), "value-GOT", "processes value through getter"
24
+ model.set property:"new"
25
+ equal bound.find("span").text(), "new", "updates value in place when bound property changes"
26
+ equal bound_get.find("span").text(), "new-GOT", "processes updated value in place through getter"
27
+ model.destroy()
28
+ ok bound.find("span").get(0) is undefined, "remove binding from dom when model is destroyed"
29
+ ok bound_get.find("span").get(0) is undefined, "removes binding from dom when model is destroyed"
30
+
31
+ test "bound_input", ->
32
+ model = new AS.Model
33
+ model.set property:"value"
34
+
35
+ bound = render model:model, ->
36
+ div -> bound_input @model, "property"
37
+
38
+ add_remove_do bound, =>
39
+ input = bound.find("input")
40
+ equal input.val(), "value", "binds initial value to input"
41
+
42
+ model.set property:"new"
43
+ equal input.val(), "new", "updates input when model changes"
44
+
45
+ input.val("keyup")
46
+ input.trigger("keyup")
47
+ equal model.get("property"), "keyup", "updates model on keyup of input"
48
+
49
+ input.val("change")
50
+ input.trigger("change")
51
+ equal model.get("property"), "change", "updates model on change of input"
52
+
53
+ test "bound_select", ->
54
+ model = new AS.Model
55
+ options = new AS.Collection
56
+ option = new AS.Model value:"option1"
57
+ added_option = new AS.Model value:"option2"
58
+ options.add option
59
+
60
+ bound = render model:model, options:options, ->
61
+ div -> bound_select @model, "property", @options, "value"
62
+
63
+ add_remove_do bound, =>
64
+ select = bound.find("select")
65
+ equal select.find("[value=#{option.cid}]option").text(), "option1", "renders given options from collection"
66
+
67
+ options.add added_option
68
+ added_option_node = select.find("[value=#{added_option.cid}]option")
69
+ equal added_option_node.text(), "option2", "adds option to select when item added to collection"
70
+
71
+ select.val(added_option.cid)
72
+ select.trigger("change")
73
+ equal model.get("property"), added_option, "sets value on model when property chosen"
74
+
75
+ model.set property:option
76
+ equal select.val(), option.cid, "changes value of select when property set on model"
77
+
78
+ option.set value:"changed option"
79
+ equal select.find("[value=#{option.cid}]option").text(), "changed option", "changes select text when option model value changes"
80
+
81
+ options.remove option
82
+ equal select.find("[value=#{option.cid}]option").get(0), undefined, "removes option from select when item added to collection"
83
+ equal model.get("property"), added_option, "reselects another option when option removed"
84
+
85
+ test "bound_select with blank", ->
86
+ model = new AS.Model
87
+ options = new AS.Collection
88
+ option = new AS.Model value:"option1"
89
+ options.add option
90
+
91
+ with_blank = render model:model, options:options, ->
92
+ div -> bound_select @model, "property", @options, "value", blank:"blank"
93
+
94
+ add_remove_do with_blank, =>
95
+ select = with_blank.find("select")
96
+ equal select.find("option:first").text(), "blank", "includes blank option"
97
+ equal select.val(), "blank", "starts out without selection selected"
98
+ equal model.get("property"), undefined, "leaves model property clear"
99
+
100
+ test "bound_select with preselect", ->
101
+ model = new AS.Model
102
+ options = new AS.Collection
103
+ option = new AS.Model value:"option1"
104
+ options.add option
105
+ model.set property:option
106
+
107
+ with_preselect = render model:model, options:options, ->
108
+ div -> bound_select @model, "property", @options, "value", blank:"blank"
109
+
110
+ add_remove_do with_preselect, =>
111
+ select = with_preselect.find("select")
112
+ equal select.find("option:first").text(), "blank", "includes blank option"
113
+ equal select.val(), option.cid, "starts out with selection selected"
114
+
115
+
116
+
117
+
118
+
@@ -0,0 +1,10 @@
1
+ module "AS.CK.Helpers"
2
+ test "autoId", ->
3
+ id = AS.CK.Helpers.autoId()
4
+ ok id.string != "", "selector is not blank"
5
+ ok id.string != undefined, "selector is defined"
6
+ equal id.query().selector, "##{id.string}", "gives id as a string and a selector"
7
+
8
+ test "shy", ->
9
+ shy = AS.CK.Helpers.shy("ThisShallShy")
10
+ equal shy, "This­Shall­Shy", "adds shy markers to titlecase text"
@@ -0,0 +1,18 @@
1
+ @module "AS.CK.Tags"
2
+ render = (locals, template) ->
3
+ locals.hardcode = AS.TemplateHelpers
4
+ jQuery CoffeeKup.render template, locals
5
+
6
+ test "model tag", ->
7
+ model = new AS.Model
8
+ defaults = render model:model, -> model_tag @model
9
+ tagnamed = render model:model, -> model_tag @model, tagname: "ul"
10
+ content = render model:model, ->
11
+ model_tag @model, -> p "content"
12
+ optioned = render model:model, ->
13
+ model_tag @model, key:"value"
14
+
15
+ ok defaults.is("div##{model.cid}"), "renders div with model cid by default"
16
+ ok tagnamed.is("ul##{model.cid}"), "renders tagname when given as an option"
17
+ equal content.find("p").text(), "content", "renders nested content when given as a function"
18
+ ok optioned.is("[key=value]"), "renders other options passed"
@@ -0,0 +1,7 @@
1
+ module "AS.Collection"
2
+ test "adding a model to a collection with @inverse and @source property specified", ->
3
+ collection = new (AS.Collection.extend(inverse: "inverse", source: "source"))
4
+ model = new AS.Model
5
+
6
+ collection.add model
7
+ equal model.get('inverse'), "source", "sets collection to property on model"
@@ -0,0 +1,43 @@
1
+ for klass in [AS.Model, AS.Collection, AS.View]
2
+ module "#{klass.name} Event Extensions"
3
+ class of_prototype
4
+ of_prototype.prototype = klass.prototype
5
+
6
+ test "events bound are triggered by event with and without namespace", ->
7
+ proof = false
8
+ object = new of_prototype
9
+ object.bind "event.namespace", -> proof = true
10
+ object.trigger "event"
11
+ ok proof, "triggers without namespace"
12
+
13
+ proof = false
14
+ object.trigger "event.namespace"
15
+ ok proof, "triggers with namespace"
16
+
17
+ test "events bound without namespace are not triggered by namespace", ->
18
+ proof = false
19
+ all_proof = false
20
+ object = new of_prototype
21
+ object.bind "all", -> all_proof = true
22
+ object.bind "event", -> proof = true
23
+ object.trigger "event.namespace"
24
+ ok !proof, "doesn't trigger with namespace"
25
+ ok all_proof, "triggers all event"
26
+
27
+ test "unbind with namespace", ->
28
+ proof = false
29
+ other_proof = false
30
+ none_proof = false
31
+ object = new of_prototype
32
+ object.bind "event.namespace", -> proof = true
33
+ object.bind "event.other_namespace", -> other_proof = true
34
+ object.bind "event", -> none_proof = true
35
+
36
+ object.unbind "event.namespace"
37
+
38
+ object.trigger "event"
39
+
40
+ ok !proof, "clears binding for namespace"
41
+ ok other_proof, "doesn't clear binding for other namespace"
42
+ ok none_proof, "doesn't clear binding for no namespace"
43
+
@@ -0,0 +1,63 @@
1
+ module "AS.Model"
2
+ test "All", ->
3
+ model = new AS.Model
4
+ equal AS.All.getByCid(model.cid), model, "All models are automatically addded to the All collection"
5
+
6
+ test "has_many", ->
7
+ class AS.HasManyModel extends AS.Model
8
+ @has_many 'things', model: -> "AS.HadModel"
9
+ class AS.HadModel extends AS.Model
10
+
11
+ deepEqual AS.HasManyModel.associations, ["things"], "stores the association in the association list"
12
+ ok AS.HasManyModel.has_manys.things, "stores a configuration for the association"
13
+
14
+ equal AS.HasManyModel.has_manys.things.model, undefined, "association collection configuration is lazy to allow associated class to load"
15
+ model = new AS.HasManyModel
16
+ equal AS.HasManyModel.has_manys.things.model, AS.HadModel, "configures the collection class properly when needed"
17
+
18
+ equal model.get("things").model, AS.HadModel, "association collection is auto-created"
19
+
20
+ model.get("things").add {}
21
+
22
+ equal model.get("things").at(0).constructor, AS.HadModel, "items added to the association are properly instantiated"
23
+
24
+ model2 = new AS.HasManyModel
25
+ things: [{}]
26
+
27
+ equal model2.get("things").at(0).constructor, AS.HadModel, "items passed to constructor for the association are properly instantiated"
28
+
29
+ test "belongs to", ->
30
+ class AS.Belonging extends AS.Model
31
+ @belongs_to "parent"
32
+ class AS.Owner extends AS.Model
33
+
34
+ deepEqual AS.Belonging.associations, ["parent"], "stores the association on the class"
35
+
36
+ ok AS.Belonging.belongs_to.parent, "stores a configuration object for the association on the class"
37
+
38
+ owner = new AS.Owner id:"OWNERID"
39
+ model = new AS.Belonging
40
+
41
+ model.set parent:owner
42
+
43
+ equal model.get("parent"), owner, "correctly sets the owner"
44
+
45
+ model = new AS.Belonging
46
+
47
+ model.set parent:owner.get("id")
48
+ equal model.get("parent"), owner, "correctly sets the from a string id"
49
+
50
+ proof = false
51
+ model.bind "change:parent", -> proof = true
52
+ owner.set some:"value"
53
+
54
+ ok proof, "association changes trigger on the child"
55
+
56
+ proof = false
57
+ new_owner = new AS.Owner
58
+ model.set parent: new_owner
59
+ new_owner.set some:"other value"
60
+
61
+ ok proof, "changes trigger when associated model is changed"
62
+
63
+
@@ -0,0 +1,72 @@
1
+ module "AS.View"
2
+ test "::klass_string()", ->
3
+ equal new AS.View().klass_string(), "ASView", "basic klass_string is ASView"
4
+
5
+ class SomeView extends AS.View
6
+
7
+ equal new SomeView().klass_string(), "ASView.SomeView", "subclasses include parent class string"
8
+
9
+ test "::element_string()", ->
10
+ equal new AS.View().element_string(), "div.ASView", "defaults to a div + klass_string"
11
+ equal new AS.View(tagName:"tagname").element_string(), "tagname.ASView", "allows setting of a tag"
12
+
13
+ model = {cid: "cid"}
14
+
15
+ equal new AS.View(model:model).element_string(), "div.ASView#cid.Object", "uses the cid/class of an associated model as the dom id/class"
16
+
17
+ test "::build_element()", ->
18
+ ok new AS.View().build_element().is(new AS.View().element_string()), "uses jQuery.satisfy to build the element"
19
+ model = {cid: "cid"}
20
+ ok new AS.View(model:model).build_element().is(new AS.View(model:model).element_string()), "with more complex element"
21
+
22
+ test "element is jquery wrapped", ->
23
+ equal new AS.View().el.constructor, jQuery
24
+
25
+ test "configuration", ->
26
+ view = new AS.View option:"OPTION"
27
+ equal view.option, "OPTION", "allow setting of arbitrary options from constructor"
28
+
29
+ test "event delegation", ->
30
+ click_proof = false
31
+ member_proof = false
32
+ button_proof = false
33
+ guard_pass_proof = false
34
+ guard_fail_proof = false
35
+
36
+ class BoundView extends AS.View
37
+ constructor: ->
38
+ @member = new AS.Model
39
+ super
40
+ @el.append @button = jQuery.satisfy("button")
41
+ @render()
42
+
43
+ events:
44
+ "click": "click_handler"
45
+ "click button": "button_handler"
46
+ "event @member": "member_handler"
47
+ "pass{pass:true} @member": "guard_pass_handler"
48
+ "fail{pass:false} @member": "guard_fail_handler"
49
+
50
+ click_handler: -> click_proof = true
51
+ member_handler: -> member_proof = true
52
+ button_handler: -> button_proof = true
53
+ guard_fail_handler: -> guard_fail_proof = true
54
+ guard_pass_handler: -> guard_pass_proof = true
55
+
56
+ render: -> @el.appendTo(document.body)
57
+
58
+ view = new BoundView
59
+
60
+ view.el.click()
61
+ view.member.trigger("event")
62
+ view.button.click()
63
+ view.member.trigger("pass", pass: true)
64
+ view.member.trigger("fail", pass: true)
65
+
66
+ ok click_proof, "binds simple dom events to view element"
67
+ ok member_proof, "binds to events of member objects"
68
+ ok button_proof, "binds to events of elements inside view"
69
+ ok guard_pass_proof, "correct values get past the guard"
70
+ ok !guard_fail_proof, "incorrect values blocked by the guard"
71
+
72
+ view.el.remove()
@@ -0,0 +1,8 @@
1
+ module "AS.Views.Stage"
2
+ test "is a Panel", ->
3
+ ok (new AS.Views.Stage).el.is(".Panel")
4
+ test "Comes with a canvas inside it", ->
5
+ view = new AS.Views.Stage
6
+ ok view.el.find(".Canvas").is(".ASView")
7
+ test "allows setting any canvas", ->
8
+ equal (new AS.Views.Stage canvas:"canvas").canvas, "canvas"
@@ -0,0 +1,13 @@
1
+ module "AS.Views.HorizontalSplit"
2
+ test "contains left, right and splitter elemens", ->
3
+ view = new AS.Views.HorizontalSplit()
4
+
5
+ equal view.el.find(".Panel").length, 2, "contains two panels"
6
+ ok view.el.find(":nth-child(2)").is(".Splitter"), "with a splitter in the middle"
7
+
8
+ test "allows configurable left, right and splitter elements", ->
9
+ view = new AS.Views.HorizontalSplit
10
+ left: 'left', right: 'right', splitter: 'splitter'
11
+
12
+ deepEqual [view.left, view.right, view.splitter], 'left right splitter'.split(" "), "lets you set them"
13
+
@@ -0,0 +1,13 @@
1
+ module "AS.Views.VerticalSplit"
2
+ test "contains top, bottom and splitter elemens", ->
3
+ view = new AS.Views.VerticalSplit()
4
+
5
+ equal view.el.find(".Panel").length, 2, "contains two panels"
6
+ ok view.el.find(":nth-child(2)").is(".Splitter"), "with a splitter in the middle"
7
+
8
+ test "allows configurable top, bottom and splitter elements", ->
9
+ view = new AS.Views.VerticalSplit
10
+ top: 'top', bottom: 'bottom', splitter: 'splitter'
11
+
12
+ deepEqual [view.top, view.bottom, view.splitter], 'top bottom splitter'.split(" "), "lets you set them"
13
+
@@ -0,0 +1,345 @@
1
+ $(document).ready(function() {
2
+
3
+ module("Backbone.Collection");
4
+
5
+ window.lastRequest = null;
6
+
7
+ Backbone.sync = function() {
8
+ lastRequest = _.toArray(arguments);
9
+ };
10
+
11
+ var a = new Backbone.Model({id: 3, label: 'a'});
12
+ var b = new Backbone.Model({id: 2, label: 'b'});
13
+ var c = new Backbone.Model({id: 1, label: 'c'});
14
+ var d = new Backbone.Model({id: 0, label: 'd'});
15
+ var e = null;
16
+ var col = new Backbone.Collection([a,b,c,d]);
17
+ var otherCol = new Backbone.Collection();
18
+
19
+ test("Collection: new and sort", function() {
20
+ equals(col.first(), a, "a should be first");
21
+ equals(col.last(), d, "d should be last");
22
+ col.comparator = function(model) { return model.id; };
23
+ col.sort();
24
+ equals(col.first(), d, "d should be first");
25
+ equals(col.last(), a, "a should be last");
26
+ equals(col.length, 4);
27
+ });
28
+
29
+ test("Collection: get, getByCid", function() {
30
+ equals(col.get(0), d);
31
+ equals(col.get(2), b);
32
+ equals(col.getByCid(col.first().cid), col.first());
33
+ });
34
+
35
+ test("Collection: get with non-default ids", function() {
36
+ var col = new Backbone.Collection();
37
+ var MongoModel = Backbone.Model.extend({
38
+ idAttribute: '_id'
39
+ });
40
+ var model = new MongoModel({_id: 100});
41
+ col.add(model);
42
+ equals(col.get(100), model);
43
+ model.set({_id: 101});
44
+ equals(col.get(101), model);
45
+ });
46
+
47
+ test("Collection: update index when id changes", function() {
48
+ var col = new Backbone.Collection();
49
+ col.add([
50
+ {id : 0, name : 'one'},
51
+ {id : 1, name : 'two'}
52
+ ]);
53
+ var one = col.get(0);
54
+ equals(one.get('name'), 'one');
55
+ one.set({id : 101});
56
+ equals(col.get(0), null);
57
+ equals(col.get(101).get('name'), 'one');
58
+ });
59
+
60
+ test("Collection: at", function() {
61
+ equals(col.at(2), b);
62
+ });
63
+
64
+ test("Collection: pluck", function() {
65
+ equals(col.pluck('label').join(' '), 'd c b a');
66
+ });
67
+
68
+ test("Collection: add", function() {
69
+ var added = opts = secondAdded = null;
70
+ e = new Backbone.Model({id: 10, label : 'e'});
71
+ otherCol.add(e);
72
+ otherCol.bind('add', function() {
73
+ secondAdded = true;
74
+ });
75
+ col.bind('add', function(model, collection, options){
76
+ added = model.get('label');
77
+ opts = options;
78
+ });
79
+ col.add(e, {amazing: true});
80
+ equals(added, 'e');
81
+ equals(col.length, 5);
82
+ equals(col.last(), e);
83
+ equals(otherCol.length, 1);
84
+ equals(secondAdded, null);
85
+ ok(opts.amazing);
86
+
87
+ var f = new Backbone.Model({id: 20, label : 'f'});
88
+ var g = new Backbone.Model({id: 21, label : 'g'});
89
+ var h = new Backbone.Model({id: 22, label : 'h'});
90
+ var atCol = new Backbone.Collection([f, g, h]);
91
+ equals(atCol.length, 3);
92
+ atCol.add(e, {at: 1});
93
+ equals(atCol.length, 4);
94
+ equals(atCol.at(1), e);
95
+ equals(atCol.last(), h);
96
+ });
97
+
98
+ test("Collection: add model to collection twice", function() {
99
+ try {
100
+ // no id, same cid
101
+ var a2 = new Backbone.Model({label: a.label});
102
+ a2.cid = a.cid;
103
+ col.add(a2);
104
+ ok(false, "duplicate; expected add to fail");
105
+ } catch (e) {
106
+ equals(e.message, "Can't add the same model to a set twice,3");
107
+ }
108
+ });
109
+
110
+ test("Collection: add model to multiple collections", function() {
111
+ var counter = 0;
112
+ var e = new Backbone.Model({id: 10, label : 'e'});
113
+ e.bind('add', function(model, collection) {
114
+ counter++;
115
+ equals(e, model);
116
+ if (counter > 1) {
117
+ equals(collection, colF);
118
+ } else {
119
+ equals(collection, colE);
120
+ }
121
+ });
122
+ var colE = new Backbone.Collection([]);
123
+ colE.bind('add', function(model, collection) {
124
+ equals(e, model);
125
+ equals(colE, collection);
126
+ });
127
+ var colF = new Backbone.Collection([]);
128
+ colF.bind('add', function(model, collection) {
129
+ equals(e, model);
130
+ equals(colF, collection);
131
+ });
132
+ colE.add(e);
133
+ equals(e.collection, colE);
134
+ colF.add(e);
135
+ equals(e.collection, colE);
136
+ });
137
+
138
+ test("Collection: remove", function() {
139
+ var removed = otherRemoved = null;
140
+ col.bind('remove', function(model){ removed = model.get('label'); });
141
+ otherCol.bind('remove', function(){ otherRemoved = true; });
142
+ col.remove(e);
143
+ equals(removed, 'e');
144
+ equals(col.length, 4);
145
+ equals(col.first(), d);
146
+ equals(otherRemoved, null);
147
+ });
148
+
149
+ test("Collection: events are unbound on remove", function() {
150
+ var counter = 0;
151
+ var dj = new Backbone.Model();
152
+ var emcees = new Backbone.Collection([dj]);
153
+ emcees.bind('change', function(){ counter++; });
154
+ dj.set({name : 'Kool'});
155
+ equals(counter, 1);
156
+ emcees.reset([]);
157
+ equals(dj.collection, undefined);
158
+ dj.set({name : 'Shadow'});
159
+ equals(counter, 1);
160
+ });
161
+
162
+ test("Collection: remove in multiple collections", function() {
163
+ var modelData = {
164
+ id : 5,
165
+ title : 'Othello'
166
+ };
167
+ var passed = false;
168
+ var e = new Backbone.Model(modelData);
169
+ var f = new Backbone.Model(modelData);
170
+ f.bind('remove', function() {
171
+ passed = true;
172
+ });
173
+ var colE = new Backbone.Collection([e]);
174
+ var colF = new Backbone.Collection([f]);
175
+ ok(e != f);
176
+ ok(colE.length == 1);
177
+ ok(colF.length == 1);
178
+ colE.remove(e);
179
+ equals(passed, false);
180
+ ok(colE.length == 0);
181
+ colF.remove(e);
182
+ ok(colF.length == 0);
183
+ equals(passed, true);
184
+ });
185
+
186
+ test("Collection: remove same model in multiple collection", function() {
187
+ var counter = 0;
188
+ var e = new Backbone.Model({id: 5, title: 'Othello'});
189
+ e.bind('remove', function(model, collection) {
190
+ counter++;
191
+ equals(e, model);
192
+ if (counter > 1) {
193
+ equals(collection, colE);
194
+ } else {
195
+ equals(collection, colF);
196
+ }
197
+ });
198
+ var colE = new Backbone.Collection([e]);
199
+ colE.bind('remove', function(model, collection) {
200
+ equals(e, model);
201
+ equals(colE, collection);
202
+ });
203
+ var colF = new Backbone.Collection([e]);
204
+ colF.bind('remove', function(model, collection) {
205
+ equals(e, model);
206
+ equals(colF, collection);
207
+ });
208
+ equals(colE, e.collection);
209
+ colF.remove(e);
210
+ ok(colF.length == 0);
211
+ ok(colE.length == 1);
212
+ equals(counter, 1);
213
+ equals(colE, e.collection);
214
+ colE.remove(e);
215
+ equals(null, e.collection);
216
+ ok(colE.length == 0);
217
+ equals(counter, 2);
218
+ });
219
+
220
+ test("Collection: model destroy removes from all collections", function() {
221
+ var e = new Backbone.Model({id: 5, title: 'Othello'});
222
+ e.sync = function(method, model, options) { options.success({}); };
223
+ var colE = new Backbone.Collection([e]);
224
+ var colF = new Backbone.Collection([e]);
225
+ e.destroy();
226
+ ok(colE.length == 0);
227
+ ok(colF.length == 0);
228
+ equals(null, e.collection);
229
+ });
230
+
231
+ test("Colllection: non-persisted model destroy removes from all collections", function() {
232
+ var e = new Backbone.Model({title: 'Othello'});
233
+ e.sync = function(method, model, options) { throw "should not be called"; };
234
+ var colE = new Backbone.Collection([e]);
235
+ var colF = new Backbone.Collection([e]);
236
+ e.destroy();
237
+ ok(colE.length == 0);
238
+ ok(colF.length == 0);
239
+ equals(null, e.collection);
240
+ });
241
+
242
+ test("Collection: fetch", function() {
243
+ col.fetch();
244
+ equals(lastRequest[0], 'read');
245
+ equals(lastRequest[1], col);
246
+ });
247
+
248
+ test("Collection: create", function() {
249
+ var model = col.create({label: 'f'});
250
+ equals(lastRequest[0], 'create');
251
+ equals(lastRequest[1], model);
252
+ equals(model.get('label'), 'f');
253
+ equals(model.collection, col);
254
+ });
255
+
256
+ test("Collection: create enforces validation", function() {
257
+ var ValidatingModel = Backbone.Model.extend({
258
+ validate: function(attrs) {
259
+ return "fail";
260
+ }
261
+ });
262
+ var ValidatingCollection = Backbone.Collection.extend({
263
+ model: ValidatingModel
264
+ });
265
+ var col = new ValidatingCollection();
266
+ equals(col.create({"foo":"bar"}),false);
267
+ });
268
+
269
+ test("Collection: a failing create runs the error callback", function() {
270
+ var ValidatingModel = Backbone.Model.extend({
271
+ validate: function(attrs) {
272
+ return "fail";
273
+ }
274
+ });
275
+ var ValidatingCollection = Backbone.Collection.extend({
276
+ model: ValidatingModel
277
+ });
278
+ var flag = false;
279
+ var callback = function(model, error) { flag = true; };
280
+ var col = new ValidatingCollection();
281
+ col.create({"foo":"bar"}, { error: callback });
282
+ equals(flag, true);
283
+ });
284
+
285
+ test("collection: initialize", function() {
286
+ var Collection = Backbone.Collection.extend({
287
+ initialize: function() {
288
+ this.one = 1;
289
+ }
290
+ });
291
+ var coll = new Collection;
292
+ equals(coll.one, 1);
293
+ });
294
+
295
+ test("Collection: toJSON", function() {
296
+ equals(JSON.stringify(col), '[{"id":0,"label":"d"},{"id":1,"label":"c"},{"id":2,"label":"b"},{"id":3,"label":"a"}]');
297
+ });
298
+
299
+ test("Collection: Underscore methods", function() {
300
+ equals(col.map(function(model){ return model.get('label'); }).join(' '), 'd c b a');
301
+ equals(col.any(function(model){ return model.id === 100; }), false);
302
+ equals(col.any(function(model){ return model.id === 0; }), true);
303
+ equals(col.indexOf(b), 2);
304
+ equals(col.size(), 4);
305
+ equals(col.rest().length, 3);
306
+ ok(!_.include(col.rest()), a);
307
+ ok(!_.include(col.rest()), d);
308
+ ok(!col.isEmpty());
309
+ ok(!_.include(col.without(d)), d);
310
+ equals(col.max(function(model){ return model.id; }).id, 3);
311
+ equals(col.min(function(model){ return model.id; }).id, 0);
312
+ same(col.chain()
313
+ .filter(function(o){ return o.id % 2 === 0; })
314
+ .map(function(o){ return o.id * 2; })
315
+ .value(),
316
+ [0, 4]);
317
+ });
318
+
319
+ test("Collection: reset", function() {
320
+ var resetCount = 0;
321
+ var models = col.models;
322
+ col.bind('reset', function() { resetCount += 1; });
323
+ col.reset([]);
324
+ equals(resetCount, 1);
325
+ equals(col.length, 0);
326
+ equals(col.last(), null);
327
+ col.reset(models);
328
+ equals(resetCount, 2);
329
+ equals(col.length, 4);
330
+ equals(col.last(), a);
331
+ col.reset(_.map(models, function(m){ return m.attributes; }));
332
+ equals(resetCount, 3);
333
+ equals(col.length, 4);
334
+ ok(col.last() !== a);
335
+ ok(_.isEqual(col.last().attributes, a.attributes));
336
+ });
337
+
338
+ test("Collection: trigger custom events on models", function() {
339
+ var fired = null;
340
+ a.bind("custom", function() { fired = true; });
341
+ a.trigger("custom");
342
+ equals(fired, true);
343
+ });
344
+
345
+ });