alpha-simprini-engine 0.0.1

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 (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
+ });