From 1d9074e0e74484fbac8ebdd185a1b0e6c1b3c3b6 Mon Sep 17 00:00:00 2001
From: Dan Connor
Date: Fri, 18 Nov 2011 20:20:46 -0800
Subject: [PATCH] Adding a test to demonstrate $.route bindings not being
properly unbound on Controller destruction.
---
controller/controller_test.js | 470 +++++++++++++++++++---------------
1 file changed, 262 insertions(+), 208 deletions(-)
diff --git a/controller/controller_test.js b/controller/controller_test.js
index d94799e9..4e0aa3ca 100644
--- a/controller/controller_test.js
+++ b/controller/controller_test.js
@@ -1,224 +1,278 @@
-steal("jquery/controller",'jquery/controller/subscribe') //load your app
+steal("jquery/controller",'jquery/controller/subscribe', 'jquery/dom/route/route.js') //load your app
.then('funcunit/qunit') //load qunit
.then(function(){
-
+
module("jquery/controller")
+test("route unbinding works", function(){
+ var set_count = 0, init_count = 0;
+ $.route("/foo/:code");
+ $.route("/foo/");
+
+ jQuery.Controller.extend("RouteChange",{
+ "{$.route} code set" : function() {
+ set_count++;
+ },
+
+ "{$.route} code remove" : function() {
+ this.element.remove();
+ },
+
+ init: function(el, options){
+ init_count++;
+ if ($.isFunction(options.callback)) options.callback.call(this);
+ }
+ });
+
+ // init the RouteChange controller
+
+ $("#qunit-test-area").html("")
+ $("#sample_controller").route_change({callback: function(){
+ location.hash = "!/foo/1";
+ // race condition between $.route event listener and location.hash
+ // just using the debugger to delay things a bit
+ debugger;
+
+ // we unset the code, causing our controller to be removed
+ location.hash = "!/foo";
+
+ $("#qunit-test-area").html("
")
+ $("#sample_controller").route_change({callback: function(){
+
+ /* let's do it again - if the route bindings are automagically
+ unbound on .destroy() we should get only one more triggered
+ $.route event when we change the location hash again */
+ location.hash = "!/foo/2"
+
+ // race condition between $.route event listener and location.hash
+ // just using the debugger to delay things a bit
+ debugger;
+
+ // init is called twice
+ equals(init_count,2, "init was correctly called twice")
+
+ // if this fails, set_count will be *3* because the event wasn't unbound
+ equals(set_count,2, "set binding was correctly called twice")
+ $("#qunit-test-area").html("");
+ }});
+ }});
+});
+
test("subscribe testing works", function(){
-
- var ta = $("
").appendTo( $("#qunit-test-area") )
-
- ta.html("click here")
-
- var clicks = 0, destroys = 0;
- var subscribes = 0;
- $.Controller.extend("MyTest",{
- click: function() {
- clicks++
- },
- "a.b subscribe" : function() {
- subscribes++
- },
- destroy: function() {
-
- this._super()
- destroys++;
- }
- })
- ta.my_test();
- ta.trigger("click")
- equals(clicks,1, "can listen to clicks")
-
- OpenAjax.hub.publish("a.b",{})
- equals(subscribes,1, "can subscribe")
- var controllerInstance = ta.controller('my_test')
- ok( controllerInstance.Class == MyTest, "can get controller" )
- controllerInstance.destroy()
-
- equals(destroys,1, "destroy called once")
- ok(!ta.controller(), "controller is removed")
-
- OpenAjax.hub.publish("a.b",{})
- equals(subscribes,1, "subscription is torn down")
- ta.trigger("click")
- equals(clicks,1, "No longer listening")
-
-
-
- ta.my_test();
- ta.trigger("click")
- OpenAjax.hub.publish("a.b",{})
- equals(clicks,2, "can listen again to clicks")
- equals(subscribes,2, "can listen again to subscription")
-
- ta.remove();
-
- ta.trigger("click")
- OpenAjax.hub.publish("a.b",{})
- equals(clicks,2, "Clicks stopped")
- equals(subscribes,2, "Subscribes stopped")
+
+ var ta = $("
").appendTo( $("#qunit-test-area") )
+
+ ta.html("click here")
+
+ var clicks = 0, destroys = 0;
+ var subscribes = 0;
+ $.Controller.extend("MyTest",{
+ click: function() {
+ clicks++
+ },
+ "a.b subscribe" : function() {
+ subscribes++
+ },
+ destroy: function() {
+
+ this._super()
+ destroys++;
+ }
+ })
+ ta.my_test();
+ ta.trigger("click")
+ equals(clicks,1, "can listen to clicks")
+
+ OpenAjax.hub.publish("a.b",{})
+ equals(subscribes,1, "can subscribe")
+ var controllerInstance = ta.controller('my_test')
+ ok( controllerInstance.Class == MyTest, "can get controller" )
+ controllerInstance.destroy()
+
+ equals(destroys,1, "destroy called once")
+ ok(!ta.controller(), "controller is removed")
+
+ OpenAjax.hub.publish("a.b",{})
+ equals(subscribes,1, "subscription is torn down")
+ ta.trigger("click")
+ equals(clicks,1, "No longer listening")
+
+
+
+ ta.my_test();
+ ta.trigger("click")
+ OpenAjax.hub.publish("a.b",{})
+ equals(clicks,2, "can listen again to clicks")
+ equals(subscribes,2, "can listen again to subscription")
+
+ ta.remove();
+
+ ta.trigger("click")
+ OpenAjax.hub.publish("a.b",{})
+ equals(clicks,2, "Clicks stopped")
+ equals(subscribes,2, "Subscribes stopped")
})
test("bind to any special", function(){
- jQuery.event.special.crazyEvent = {
-
- }
- var called = false;
- jQuery.Controller.extend("WeirdBind",{
- crazyEvent: function() {
- called = true;
- }
- })
- var a = $("
").appendTo($("#qunit-test-area"))
- a.weird_bind();
- a.trigger("crazyEvent")
- ok(called, "heard the trigger");
-
- $("#qunit-test-area").html("")
-
+ jQuery.event.special.crazyEvent = {
+
+ }
+ var called = false;
+ jQuery.Controller.extend("WeirdBind",{
+ crazyEvent: function() {
+ called = true;
+ }
+ })
+ var a = $("
").appendTo($("#qunit-test-area"))
+ a.weird_bind();
+ a.trigger("crazyEvent")
+ ok(called, "heard the trigger");
+
+ $("#qunit-test-area").html("")
+
})
test("parameterized actions", function(){
- var called = false;
- jQuery.Controller.extend("WeirderBind",{
- "{parameterized}" : function() {
- called = true;
- }
- })
- var a = $("
").appendTo($("#qunit-test-area"))
- a.weirder_bind({parameterized: "sillyEvent"});
- a.trigger("sillyEvent")
- ok(called, "heard the trigger")
-
- $("#qunit-test-area").html("")
+ var called = false;
+ jQuery.Controller.extend("WeirderBind",{
+ "{parameterized}" : function() {
+ called = true;
+ }
+ })
+ var a = $("
").appendTo($("#qunit-test-area"))
+ a.weirder_bind({parameterized: "sillyEvent"});
+ a.trigger("sillyEvent")
+ ok(called, "heard the trigger")
+
+ $("#qunit-test-area").html("")
})
test("windowresize", function(){
- var called = false;
- jQuery.Controller.extend("WindowBind",{
- "{window} resize" : function() {
- called = true;
- }
- })
- $("#qunit-test-area").html("
")
- $("#weird").window_bind();
- $(window).trigger('resize')
- ok(called,"got window resize event");
-
- $("#qunit-test-area").html("")
+ var called = false;
+ jQuery.Controller.extend("WindowBind",{
+ "{window} resize" : function() {
+ called = true;
+ }
+ })
+ $("#qunit-test-area").html("
")
+ $("#weird").window_bind();
+ $(window).trigger('resize')
+ ok(called,"got window resize event");
+
+ $("#qunit-test-area").html("")
})
-// this.delegate(this.cached.header.find('tr'), "th", "mousemove", "th_mousemove");
+// this.delegate(this.cached.header.find('tr'), "th", "mousemove", "th_mousemove");
test("delegate", function(){
- var called = false;
- jQuery.Controller.extend("DelegateTest",{
- click: function() {}
- })
- var els = $("
").appendTo($("#qunit-test-area"))
- var c = els.delegate_test();
- c.controller().delegate(els.find("span"), "a", "click", function(){
- called = true;
- })
- els.find("a").trigger('click')
- ok(called, "delegate works")
- $("#qunit-test-area").html("")
+ var called = false;
+ jQuery.Controller.extend("DelegateTest",{
+ click: function() {}
+ })
+ var els = $("
").appendTo($("#qunit-test-area"))
+ var c = els.delegate_test();
+ c.controller().delegate(els.find("span"), "a", "click", function(){
+ called = true;
+ })
+ els.find("a").trigger('click')
+ ok(called, "delegate works")
+ $("#qunit-test-area").html("")
})
test("inherit", function(){
- var called = false;
- $.Controller.extend( "Parent", {
- click: function(){
- called = true;
- }
- })
- Parent.extend( "Child", {
-
- })
- var els = $("
").appendTo($("#qunit-test-area"))
- els.child();
- els.find("a").trigger('click')
- ok(called, "inherited the click method")
- $("#qunit-test-area").html("")
+ var called = false;
+ $.Controller.extend( "Parent", {
+ click: function(){
+ called = true;
+ }
+ })
+ Parent.extend( "Child", {
+
+ })
+ var els = $("
").appendTo($("#qunit-test-area"))
+ els.child();
+ els.find("a").trigger('click')
+ ok(called, "inherited the click method")
+ $("#qunit-test-area").html("")
});
test("objects in action", function(){
- $.Controller('Thing',{
- "{item} someEvent" : function(thing, ev){
- ok(true, "called");
- equals(ev.type, "someEvent","correct event")
- equals(this.constructor.fullName, "Thing", "This is a controller isntance")
- equals(thing.name,"Justin","Raw, not jQuery wrapped thing")
- }
- });
-
- var thing1 = {name: "Justin"};
-
- var ta = $("
").appendTo( $("#qunit-test-area") )
- ta.thing({item : thing1});
-
- $(thing1).trigger("someEvent");
-
- $("#qunit-test-area").html("");
-
+ $.Controller('Thing',{
+ "{item} someEvent" : function(thing, ev){
+ ok(true, "called");
+ equals(ev.type, "someEvent","correct event")
+ equals(this.constructor.fullName, "Thing", "This is a controller isntance")
+ equals(thing.name,"Justin","Raw, not jQuery wrapped thing")
+ }
+ });
+
+ var thing1 = {name: "Justin"};
+
+ var ta = $("
").appendTo( $("#qunit-test-area") )
+ ta.thing({item : thing1});
+
+ $(thing1).trigger("someEvent");
+
+ $("#qunit-test-area").html("");
+
});
test("dot",function(){
- $.Controller("Dot",{
- "foo.bar" : function(){
- ok(true,'called')
- }
- });
-
- var ta = $("
").appendTo( $("#qunit-test-area") );
- ta.dot().trigger("foo.bar");
- $("#qunit-test-area").html("");
+ $.Controller("Dot",{
+ "foo.bar" : function(){
+ ok(true,'called')
+ }
+ });
+
+ var ta = $("
").appendTo( $("#qunit-test-area") );
+ ta.dot().trigger("foo.bar");
+ $("#qunit-test-area").html("");
})
// HTMLFormElement[0] breaks
test("the right element", 1, function(){
- $.Controller('FormTester',{
- init : function(){
- equals(this.element[0].nodeName.toLowerCase(), "form" )
- }
- })
- $("
").appendTo( $("#qunit-test-area") )
- .form_tester();
- $("#qunit-test-area").html("")
+ $.Controller('FormTester',{
+ init : function(){
+ equals(this.element[0].nodeName.toLowerCase(), "form" )
+ }
+ })
+ $("
").appendTo( $("#qunit-test-area") )
+ .form_tester();
+ $("#qunit-test-area").html("")
})
test("pluginName", function() {
- // Testing for controller pluginName fixes as reported in
- // http://forum.javascriptmvc.com/#topic/32525000000253001
- // http://forum.javascriptmvc.com/#topic/32525000000488001
- expect(6);
-
- $.Controller("PluginName", {
- pluginName : "my_plugin"
- }, {
- method : function(arg) {
- ok(true, "Method called");
- },
-
- update : function(options) {
- this._super(options);
- ok(true, "Update called");
- },
-
- destroy : function() {
- ok(true, "Destroyed");
- this._super();
- }
- });
-
- var ta = $("
").addClass('existing_class').appendTo( $("#qunit-test-area") );
- ta.my_plugin(); // Init
- ok(ta.hasClass("my_plugin"), "Should have class my_plugin");
- ta.my_plugin(); // Update
- ta.my_plugin("method"); // method()
- ta.controller().destroy(); // destroy
- ok(!ta.hasClass("my_plugin"), "Shouldn't have class my_plugin after being destroyed");
- ok(ta.hasClass("existing_class"), "Existing class should still be there");
+ // Testing for controller pluginName fixes as reported in
+ // http://forum.javascriptmvc.com/#topic/32525000000253001
+ // http://forum.javascriptmvc.com/#topic/32525000000488001
+ expect(6);
+
+ $.Controller("PluginName", {
+ pluginName : "my_plugin"
+ }, {
+ method : function(arg) {
+ ok(true, "Method called");
+ },
+
+ update : function(options) {
+ this._super(options);
+ ok(true, "Update called");
+ },
+
+ destroy : function() {
+ ok(true, "Destroyed");
+ this._super();
+ }
+ });
+
+ var ta = $("
").addClass('existing_class').appendTo( $("#qunit-test-area") );
+ ta.my_plugin(); // Init
+ ok(ta.hasClass("my_plugin"), "Should have class my_plugin");
+ ta.my_plugin(); // Update
+ ta.my_plugin("method"); // method()
+ ta.controller().destroy(); // destroy
+ ok(!ta.hasClass("my_plugin"), "Shouldn't have class my_plugin after being destroyed");
+ ok(ta.hasClass("existing_class"), "Existing class should still be there");
})
test("inherit defaults", function() {
@@ -242,27 +296,27 @@ test("inherit defaults", function() {
});
test("update rebinding", 2, function(){
- var first = true;
- $.Controller("Rebinder", {
- "{item} foo" : function(item, ev){
- if(first){
- equals(item.id, 1, "first item");
- first = false;
- } else {
- equals(item.id, 2, "first item");
- }
- }
- });
-
- var item1 = {id: 1},
- item2 = {id: 2},
- el = $('
').rebinder({item: item1})
-
- $(item1).trigger("foo")
-
- el.rebinder({item: item2});
-
- $(item2).trigger("foo")
+ var first = true;
+ $.Controller("Rebinder", {
+ "{item} foo" : function(item, ev){
+ if(first){
+ equals(item.id, 1, "first item");
+ first = false;
+ } else {
+ equals(item.id, 2, "first item");
+ }
+ }
+ });
+
+ var item1 = {id: 1},
+ item2 = {id: 2},
+ el = $('
').rebinder({item: item1})
+
+ $(item1).trigger("foo")
+
+ el.rebinder({item: item2});
+
+ $(item2).trigger("foo")
})