BusyBird
view release on metacpan or search on metacpan
xt/js/utils.html view on Meta::CPAN
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Utility functions tests</title>
<link rel="stylesheet" href="qunit.css">
</head>
<body>
<div id="mb"></div>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="qunit.js"></script>
<script src="sinon.js"></script>
<script src="../../share/www/static/jquery.js"></script>
<script src="../../share/www/static/q.js"></script>
<script src="../../share/www/static/busybird.js"></script>
<script type="text/javascript">
"use strict";
var is = strictEqual;
var faketimer;
function fakeTimer() {
if(defined(faketimer)) {
faketimer.restore();
}
faketimer = sinon.useFakeTimers();
}
var fakeserver;
// SlowStartServer starts slowly.
// At first it responds with 404 for fail_num times.
// After that it starts responding with 200.
//
// @param fail_num Number of failed responses.
// @param fail_code HTTP erro code. It's 404 by default.
var SlowStartServer = function(fail_num, fail_code) {
var self = this;
self.fail_num = fail_num;
self.count = 0;
self.reqs = [];
self.fail_code = fail_code || 404;
self.xhr = sinon.useFakeXMLHttpRequest();
self.xhr.onCreate = function(req) {
self.reqs.push(req);
};
};
SlowStartServer.prototype = {
pendingNum: function() { return this.reqs.length },
respond: function() {
var self = this;
var i, request;
for(i = 0 ; i < self.reqs.length ; i++) {
request = self.reqs[i];
if(self.count < self.fail_num) {
request.respond(self.fail_code, {"Content-Type": "text/plain"}, "" + self.count);
}else {
request.respond(200, {"Content-Type": "text/plain"}, "" + self.count);
}
self.count++;
}
self.reqs = [];
},
restore: function() { this.xhr.restore() },
};
asyncTest("ajaxRetry (succeed at first request)", function() {
var res;
// serverSlowStart(0);
fakeserver = new SlowStartServer(0);
var pending = bb.ajaxRetry({url: "/"});
ok(!defined(res), "response is not returned yet");
is(fakeserver.pendingNum(), 1, "1 request pending");
fakeserver.respond();
pending.promise.then(function(data) {
res = data;
}, function(reason) {
ok(false, "ajaxRetry should succeed: " + reason);
}).then(function() {
is(res, "0", "response received at count = 0");
fakeserver.restore();
start();
});
});
asyncTest("ajaxRetry (fail several times)", function() {
var res;
// serverSlowStart(5);
fakeserver = new SlowStartServer(5);
fakeTimer();
var pending = bb.ajaxRetry({url: "/"});
pending.promise.then(
function(data) { res = data },
function() { ok(false, "the ajax call should not be an error.") }
);
ok(!defined(res), "response is not returned yet");
is(fakeserver.pendingNum(), 1, "1 request pending");
fakeserver.respond();
is(fakeserver.pendingNum(), 0, "0 request pending");
faketimer.tick(200);
is(fakeserver.pendingNum(), 0, "0 request pending (not yet requested)");
faketimer.tick(200000);
is(fakeserver.pendingNum(), 1, "1 request pending");
fakeserver.respond();
faketimer.tick(1000);
is(fakeserver.pendingNum(), 0, "0 request pending (retry backoff)");
faketimer.tick(200000);
is(fakeserver.pendingNum(), 1, "1 request pending");
fakeserver.respond();
faketimer.tick(200000);
is(fakeserver.pendingNum(), 1, "1 request pending");
fakeserver.respond();
faketimer.tick(200000);
is(fakeserver.pendingNum(), 1, "1 request pending");
fakeserver.respond();
faketimer.tick(200000);
is(fakeserver.pendingNum(), 1, "1 request pending");
faketimer.restore();
Q.fcall(function() {
ok(!defined(res), "successful response is not returned yet");
fakeserver.respond();
return pending.promise;
}).then(function(data) {
is(res, "5", "response received at count = 5");
}, function(reason) {
ok(false, "ajaxRetry should succeed: " + reason);
}).then(function() {
fakeserver.restore();
start();
});
});
asyncTest("ajaxRetry (cancel)", function() {
var pending_req;
var ajax_xhr;
var ajax_spy = sinon.spy(jQuery, "ajax");
var ajax_abort_spy;
var next_executed = false;
var error_executed = false;
fakeserver = new SlowStartServer(0)
pending_req = bb.ajaxRetry({url: "/"});
is(fakeserver.pendingNum(), 1, "1 pending request");
is(ajax_spy.callCount, 1, "$.ajax() called once");
ajax_xhr = ajax_spy.getCall(0).returnValue;
ajax_abort_spy = sinon.spy(ajax_xhr, "abort");
pending_req.cancel();
pending_req.promise.then(function() {
ok(false, "fulfilled callback should not be executed.");
}, function(reason) {
ok(true, "rejected callback should be executed.");
}).then(function() {
is(ajax_abort_spy.callCount, 1, "ajaxXHR.abort() called once");
}).fail(function(reason) {
ok(false, "error: " + reason);
}).then(function() {
fakeserver.restore();
start();
});
});
asyncTest("ajaxRetry (tryMax)", function() {
var next_executed = false;
var error_executed = false;
fakeserver = new SlowStartServer(1);
var pending = bb.ajaxRetry({url: "/", tryMax: 1})
Q.fcall(function() {
is(fakeserver.pendingNum(), 1, "1 pending request");
ok(!next_executed, "next callback is not executed");
ok(!error_executed, "error callback is not executed");
fakeserver.respond();
});
pending.promise.then(function() {
next_executed = true;
}, function() {
error_executed = true;
}).then(function() {
ok(!next_executed, "next callback is not executed");
ok(error_executed, "error callback is executed");
}).fail(function(reason) {
ok(false, "error: " + reason);
}).then(function() {
fakeserver.restore();
start();
});
});
$.each([400, 401, 403, 500, 501, 503], function(i, code) {
asyncTest("ajaxRetry (code = "+ code +")", function() {
fakeserver = new SlowStartServer(100, code);
fakeTimer();
var pending = bb.ajaxRetry({url: "/", tryMax: 2});
is(fakeserver.pendingNum(), 1, "1 request pending");
fakeserver.respond();
is(fakeserver.pendingNum(), 0, "0 request pending");
faketimer.tick(1000);
is(fakeserver.pendingNum(), 1, "retried request pending");
fakeserver.respond();
is(fakeserver.pendingNum(), 0, "0 request pending");
faketimer.tick(10000);
is(fakeserver.pendingNum(), 0, "no more request");
faketimer.restore();
pending.promise.then(function() {
ok(false, "ajaxRetry should not succeed");
}, function() {
ok(true, "ajaxRetry failure expected");
}).then(function() {
fakeserver.restore();
start();
});
});
});
asyncTest("blockEach (1 block)", function() {
var counter = 0;
bb.blockEach([1,2,3], 10, function(block_array, global_index) {
counter++;
deepEqual(block_array, [1,2,3], "1 block covers all");
is(global_index, 0, "global index OK");
}).then(function() {
is(counter, 1, "repeats 1 time");
}, function() {
ok(false, "this blockEach should not fail");
}).then(function() {
start();
});
});
asyncTest("blockEach (3 blocks)", function() {
var counter = 0;
var exp_blocks = [[1,2,3], [4,5,6], [7,8]];
bb.blockEach([1,2,3,4,5,6,7,8], 3, function(block_array, global_index) {
deepEqual(block_array, exp_blocks[counter], "block content OK");
is(global_index, counter * 3, "global index OK");
counter++;
}).then(function() {
is(counter, 3, "repeats 3 times");
}, function() {
ok(false, "this blockEach should not fail");
}).then(function() {
start();
});
});
asyncTest("blockEach (0 block)", function() {
bb.blockEach([], 10, function() {
ok(false, "this should not be executed");
}).then(function() {
ok(true, "blockEach succeeds without executing the callback");
}, function() {
ok(false, "this blockEach should not fail");
}).then(function() {
start();
});
})
</script>
</body>
</html>
( run in 0.599 second using v1.01-cache-2.11-cpan-39bf76dae61 )