Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Full test coverage for Function.prototype.notifier.js
<!doctype html>
<html>
<head>
<title>Function.prototype.notifier</title>
<!-- https://github.com/WebReflection/wru -->
<script src="callback.js"></script>
<script>function wru(wru){var assert=wru.assert,async=wru.async;
// enojy your tests!
wru.test([
{
name: "Function.prototype.notifier exists",
test: function () {
assert(typeof assert.notifier == "function");
}
},{
name: "public and protected API is present",
test: function () {
var assertNotifier = assert.notifier();
assert("addListener", typeof assertNotifier.addListener == "function");
assert("fireListener", typeof assertNotifier.fireListener == "function");
assert("removeListener", typeof assertNotifier.removeListener == "function");
assert("_callback", assertNotifier._callback === assert);
assert("_handlers", typeof assertNotifier._handlers == "object");
assert("one _notifier per each function", assert._notifier === assertNotifier);
}
},{
name: "'before' event is working as expected",
test: function () {
var before, expected = 0, assertNotifier = assert.notifier();
assertNotifier.addListener("before", before = async(function () {
assertNotifier.removeListener("before", before);
assert("fired", ++expected);
}));
assertNotifier.addListener("before", function before() {
assertNotifier.removeListener("before", before);
assert("fired", ++expected);
});
setTimeout(function () {
assertNotifier(true);
assert("2 calls", expected == 2);
}, 500);
}
},{
name: "'after' event is executed after",
test: function () {
function before(e) {
expected.push(0);
assertNotifier.removeListener("before", before);
}
function test() {
expected.push(1);
return genericOutput;
}
function after(e) {
expected.push(2);
assertNotifier.removeListener("after", after);
assert(e.output === genericOutput);
}
var expected = [], assertNotifier = test.notifier(), genericOutput = {};
assertNotifier.addListener("before", before);
assertNotifier.addListener("after", after);
assertNotifier();
assert(expected.join("") == "012");
}
},{
name: "'before' event could prevent execution and after call",
test: function () {
function test() {
++expected;
}
function after(e) {
++expected;
}
var expected = 0, assertNotifier = test.notifier();
assertNotifier.addListener("before", function before(e) {
assertNotifier.removeListener("before", before);
e.preventDefault();
});
assertNotifier.addListener("after", after);
assertNotifier();
assert("0 calls", !expected);
assertNotifier.removeListener("after", after);
}
},{
name: "if object is passed events are attached automatically",
test: function () {
var
expected = [],
assertNotifier = function test() {
expected.push(1);
}.notifier({
before: function before(e) {
expected.push(0);
assertNotifier.removeListener("before", before);
},
after: function after(e) {
expected.push(2);
assertNotifier.removeListener("after", after);
}
})
;
assertNotifier();
assert(expected.join("") == "012");
}
},{
name: "'error' event works as expected",
test: function () {
var
expected = [],
assertNotifier = function test() {
throw new Error("what happened");
}.notifier({
before: function before(e) {
expected.push(0);
assertNotifier.removeListener("before", before);
},
error: function (e) {
expected.push(e.error.message === "what happened");
},
after: function after(e) {
expected.push(2);
assertNotifier.removeListener("after", after);
}
})
;
assertNotifier();
assert(expected.join("") == "0true2");
}
},{
name: "the event object has arguments, context, and other properties",
test: function () {
function test() {
++expected;
assert([].slice.call(arguments).join("-") == args.join("-"));
assert(this === context);
error = new Error("what happened");
throw error;
}
var
args = [1, 2, 3],
context = {},
expected = 0,
error,
assertNotifier = test.notifier({
before: function before(e) {
++expected;
assertNotifier.removeListener("before", before);
assert(e.arguments.join("-") == args.join("-"));
assert(e.context === context);
assert(e.type === "before");
assert(e.callback === test);
assert(e.handler === before);
assert(e.notifier === assertNotifier);
assert(e.error == null);
assert(!e.hasOwnProperty("output"));
},
error: function errorHandler(e) {
++expected;
assert(e.arguments.join("-") == args.join("-"));
assert(e.context === context);
assert(e.type === "error");
assert(e.error === error);
assert(e.callback === test);
assert(e.handler === errorHandler);
assert(e.notifier === assertNotifier);
assert(!e.hasOwnProperty("output"));
},
after: function after(e) {
++expected;
assertNotifier.removeListener("after", after);
assert(e.arguments.join("-") == args.join("-"));
assert(e.context === context);
assert(e.type === "after");
assert(e.callback === test);
assert(e.handler === after);
assert(e.notifier === assertNotifier);
assert(e.error == null);
assert(e.hasOwnProperty("output"));
}
})
;
assertNotifier.apply(context, args);
assert("total amount of tests", expected === 4);
}
},{
name: "if a handler has an error, 'hendlererror' is fired",
test: function () {
var
error,
expected = [],
assertNotifier = function test() {}.notifier({
before: function before(e) {
error = new Error("WTF");
},
handlererror: function handlererror(e) {
assert(e.type === "handlererror");
assert(e.error === error);
assert(e.handler === handlererror);
}
})
;
assertNotifier();
assert("test was executed", !!error);
}
}
]);
}</script>
<!-- add other scripts here if necessary-->
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />
<style type="text/css">
#wru {
font-family: sans-serif;
font-size: 11pt;
border: 1px solid #333;
}
#wru div {
cursor: default;
padding: 0;
color: #000;
}
#wru div span,
#wru div strong {
display: block;
padding: 4px;
margin: 0;
}
#wru div ul {
margin: 0;
padding-bottom: 4px;
}
#wru div.pass {
background: #90EE90;
}
#wru div.fail {
background: #FF6347;
}
#wru div.error {
background: #000;
color: #FFF;
}
</style>
</head>
<body>
<div id="wru"></div>
<script>
/*!
(C) Andrea Giammarchi, @WebReflection - Mit Style License
*/
wru(function(V){function i(){y=I.call(l);if(y){(N=k(k(W.node,"div"),"span"))[C]=((ad(y,P)&&y[P])||(ad(y,e)&&y[e])||O)+h+h;a=[];s=[];Q=[];Y={};b("setup");Q[ae]||b("test");b("teardown");L||p()}else{r()}}function n(ag){try{return M.call(g,ag)}catch(af){return g.createElement(ag)}}function k(af,ag){return af.appendChild(n(ag))}function f(af){N[C]=v.call(N[C],0,-2)+h+af}function r(){var ag=W.node.insertBefore(n("div"),W.node.firstChild),ah,af;if(aa){af="error";ah="There Are Errors: "+aa}else{if(A){af="fail";ah=A+" Tests Failed"}else{af="pass";ah="Passed "+q+" Tests"}}ag[C]="<strong>"+ah+"</strong>";ag.className=af}function E(){var af=this.lastChild.style;af.display=af.display=="none"?"block":"none"}function c(af){N[C]+="<ul>"+B+t.call(af,d+B)+d+"</ul>";(N.onclick=E).call(N)}function p(){q+=a[ae];A+=s[ae];aa+=Q[ae];f("("+t.call([a[ae],K=s[ae],Q[ae]],", ")+")");N=N.parentNode;Q[ae]?c(Q,T="error"):(K?c(s,T="fail"):T="pass");N.className=T;K=0;T=h;i()}function b(af){if(ad(y,af)){try{y[af](Y)}catch(ag){X.call(Q,h+ag)}}}function ad(ag,af){return o.call(ag,af)}function u(){return D()<0.5?-1:1}var W={assert:function R(ag,af){if(arguments[ae]==1){af=ag;ag=O}x=G;X.call(af?a:s,T+ag);return af},async:function S(ag,aj,ah,ai){ai=++L;if(typeof ag=="function"){ah=aj;aj=ag;ag="asynchronous test #"+ai}ah=U(function(){ai=0;X.call(s,ag);--L||p()},J(ah||w)||w);return function af(){if(!ai){return}x=ab;T=ag+": ";try{aj.apply(this,arguments)}catch(ak){x=G;X.call(Q,T+ak)}T=h;if(x){F(ah);--L||p()}}},test:function m(af){l=H.apply(l,[af]);W.random&&ac.call(l,u);L||i()}},G=true,ab=!G,w=100,h=" ",O="unknown",ae="length",P="name",e="description",B="<li>",d="</li>",j="\\|/-",o=W.hasOwnProperty,T=h,Z=T.charAt,v=T.slice,l=[],H=l.concat,t=l.join,X=l.push,I=l.shift,ac=l.sort,L=0,K=0,q=0,A=0,aa=0,C="innerHTML",g=V.document,M=g.createElement,z,J,D,U,F,y,N,a,s,Q,Y,x;z=V.Math;J=z.abs;D=z.random;U=V.setTimeout;F=V.clearTimeout;W.node=(g.getElementById("wru")||g.body||g.documentElement);V.setInterval(function(){L&&f(Z.call(j,K++%4))},w);w*=w;W.random=ab;return W}(this));
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment