(function() {
    'use strict';
    var isPatched = false;

    window.__asynculous = {};

    var origIt = window.it;
    var _done;
    window.it = function(description, test) {
      origIt(description, function(done) {
        _done = done;
        patchAsyncs();

        var result;
        var error;
        try {
          result = test();
        } catch(e) {
          error = e;
        }
        if (outstandingOps === 0) {
          resetAsyncs();
        }
        if (error) {
          _done(error);
        }
        return result;
      });
    };

    var outstandingOps = 0;
    var timers = [];

    function wrapCallback(callback) {
      return function() {
        outstandingOps--;
        try {
          var result = callback();
          callIfDone();
          return result;
        } catch(e) {
          _done(e);
        }
      };
    }

    function patchAsyncs() {
      if (isPatched) {
        debugger;
      }
      isPatched = true;
      
      patchSetClearAsyncs();      
    }

    function patchSetClearAsyncs() {
      ['Timeout', 'Interval', 'Immediate', 
       'requestAnimationFrame', 'mozRequestAnimationFrame',
       'webkitRequestAnimationFrame'].forEach(function(name) {
        var timers = [];

        var setName = 'set' + name;
        var clearName = 'clear' + name;

        if (!window[setName] && !window[clearName] && window[name]) {
          setName = name;
        }

        var origSet = window[setName];
        var origClear = window[clearName];

        if (origSet) {
          window[setName] = function() {
            var args = [].slice.call(arguments, 0);
            var callback = args[0];
            var wrappedCallback = wrapCallback(callback);
            args[0] = wrappedCallback;
            outstandingOps++;
            var timer = origSet.apply(window, args);
            timers.push(timer);
            return timer;
          };

          window.__asynculous[setName] = origSet;
        }

        if (origClear) {
          window[clearName] = function(timer) {
            var index = timers.indexOf(timer);
            if (index !== -1) {
              timers.splice(index, 1);
              outstandingOps--;
            }
            return origClear(timer);
          };

          window.__asynculous[clearName] = origClear;
        }

        
        
      });
    }

    function resetAsyncs() {
      isPatched = false;
      for (var key in window.__asynculous) {
        window[key] = window.__asynculous[key];
      }
    } 

    function callIfDone() {
      if (outstandingOps === 0) {
        _done();
        resetAsyncs();
      }
    }
  }());
@@ -76,16 +76,25 @@
 ynculous
+Originals
  = %7B%7D;%0A%0A
@@ -444,34 +444,36 @@
  %7B%0A          res
-e
 t
+ore
 Asyncs();%0A      
@@ -1958,16 +1958,25 @@
 ynculous
+Originals
 %5BsetName
@@ -2316,16 +2316,25 @@
 ynculous
+Originals
 %5BclearNa
@@ -2363,27 +2363,8 @@
    %7D
-%0A%0A        %0A        
 %0A   
@@ -2389,26 +2389,28 @@
 function res
-e
 t
+ore
 Asyncs() %7B%0A 
@@ -2474,16 +2474,25 @@
 ynculous
+Originals
 ) %7B%0A    
@@ -2528,16 +2528,25 @@
 ynculous
+Originals
 %5Bkey%5D;%0A 
@@ -2650,18 +2650,20 @@
      res
-e
 t
+ore
 Asyncs()

Fix incorrect namings