dijit
Version:
Dijit provides a complete collection of user interface controls based on Dojo, giving you the power to create web applications that are highly optimized for usability, performance, internationalization, accessibility, but above all deliver an incredible u
178 lines (154 loc) • 5.32 kB
HTML
<html>
<head>
<title>Destroyable unit test</title>
<script src="boilerplate.js"></script>
<script type="text/javascript">
require([
"doh/runner",
"dojo/aspect", "dojo/_base/declare", "dojo/Deferred", "dojo/dom", "dojo/dom-construct",
"dojo/_base/lang", "dojo/on", "dojo/Stateful",
"dijit/Destroyable", "dojo/domReady!"
], function(doh, aspect, declare, Deferred, dom, domConstruct, lang, on, Stateful, Destroyable){
doh.register("Destroyable", [
function general(){
var SupportingWidget = declare([], {
destroyCalls: 0,
constructor: function(name){
this.name = name;
},
destroy: function(){
this.destroyCalls++;
}
});
var watchMe = new Stateful({
name: "watchMe",
x: 0
});
var DestroyableSubClass = declare(Destroyable, {
// number of times my button was clicked
clicks: 0,
// number of times watchMe changed value of x
watches: 0,
constructor: function(){
var self = this;
this.domNode = domConstruct.create("button");
this.own(
// setup an event handler (to be destroyed when I'm destroyed)
on(this.domNode, "click", function(){ self.clicks++; }),
// watch external watchMe class (to be unwatch()'d when I'm destroyed)
watchMe.watch("x", function(name, oVal, nVal){ self.watches++; })
);
// Setup two supporting widgets, to be destroyed when I'm destroyed
this.own(this.sw1 = new SupportingWidget("sw1"));
this.own(this.sw2 = new SupportingWidget("sw2"));
}
});
var destroyable1 = new DestroyableSubClass();
dom.byId("container").appendChild(destroyable1.domNode);
// make sure event handler was setup
destroyable1.domNode.click();
doh.is(1, destroyable1.clicks, "one click");
// make sure watch handler was setup
watchMe.set("x", 1);
doh.is(1, destroyable1.watches, "one watch notification");
// manually destroy one of the supporting widgets
destroyable1.sw1.destroy();
doh.is(1, destroyable1.sw1.destroyCalls);
// Destroy the Destroyable instance itself. destroyable1 should:
// - destroy the sw2 supporting widget, but not try to re-destroy sw1
// - disconnect the watch() listener on watchMe
// - disconnect the click event handler on destroyable1.domNode
destroyable1.destroy();
doh.is(1, destroyable1.sw1.destroyCalls, "sw1 wasn't redestroyed");
doh.is(1, destroyable1.sw2.destroyCalls, "sw2 was destroyed");
destroyable1.domNode.click();
doh.is(1, destroyable1.clicks, "no new click notification");
watchMe.set("x", 2);
doh.is(1, destroyable1.watches, "no new watch notification");
},
function multipleDestroyFunctions(){
var destroyRecursiveCount = 0;
var destroyCount = 0;
var W1 = declare([Destroyable], {
destroyRecursive: function() {
destroyRecursiveCount++;
this.destroy();
this.inherited(arguments);
},
destroy: function() {
destroyCount++;
this.inherited(arguments);
}
});
var W2 = declare([Destroyable], {
test: function() {
var w1 = new W1();
this.own(w1);
w1.destroy();
},
destroy: function() {
this.inherited(arguments);
}
});
var W3 = declare([Destroyable], {
test: function() {
var w1 = new W1();
this.own(w1);
w1.destroyRecursive();
},
destroy: function() {
this.inherited(arguments);
}
});
var w2 = new W2();
w2.test();
w2.destroy();
doh.is(0, destroyRecursiveCount, "destroyRecursive was not called as expected");
doh.is(1, destroyCount, "destroy was not called as expected");
destroyRecursiveCount = 0;
destroyCount = 0;
var w3 = new W3();
w3.test();
w3.destroy();
doh.is(1, destroyRecursiveCount, "destroyRecursive was not called as expected");
doh.is(1, destroyCount, "destroy was not called as expected");
},
function owningPromises(){
var cancels = 0;
var W1 = declare(Destroyable, {
constructor: function(){
this.p1 = new Deferred(function(){ console.log("cancel p1"); cancels++; });
this.p2 = new Deferred(function(){ console.log("cancel p2"); cancels++; });
this.p3 = new Deferred(function(){ console.log("cancel p3"); cancels++; });
this.p4 = new Deferred(function(){ console.log("cancel p4"); cancels++; });
this.own(this.p1, this.p2, this.p3, this.p4);
}
});
var w1 = new W1();
w1.p1.resolve(true);
aspect.after(w1.p1, "cancel", function(){
throw new Error("p1 shouldn't have been canceled");
}, true);
w1.p2.reject(new Error("I was rejected"));
aspect.after(w1.p2, "cancel", function(){
throw new Error("p2 shouldn't have been canceled");
}, true);
w1.p3.cancel();
doh.is(1, cancels, "one promise canceled manually before destroy");
// Destroying the widget should only cancel p4; it's the only Promise that hasn't been dealt with already.
// OTOH if Destroyable is broken, one of the asserts above may go off during the destroy() call.
w1.destroy();
doh.is(2, cancels, "only p4 canceled on widget destroy");
}
]); // doh.register()
doh.run();
}); // require()
</script>
</head>
<body>
<h1>dijit/Destroyable Unit Test</h1>
<div id="container"></div>
</body>
</html>