The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>UnackedCountsPoller tests</title>
    <link rel="stylesheet" href="qunit.css">
  </head>
  <body>
    <div id="spinner"></div>
    <div id="qunit"></div>
    <div id="qunit-fixture"></div>
    <script src="qunit.js"></script>
    <script src="../../share/www/static/jquery.js"></script>
    <script src="./sinon.js"></script>
    <script src="./uri.js"></script>
    <script src="../../share/www/static/q.js"></script>
    <script src="../../share/www/static/busybird.js"></script>
    <script src="../../share/www/static/timeline_list.js"></script>
    <script type="text/javascript">
"use strict";

var is = strictEqual;

var removeUnderscoreQuery = function(url) {
    return url.replace(/\&_=[0-9]+/, "");
};

var FakeCountsServer = function() {
    var self = this;
    self.fakexhr = sinon.useFakeXMLHttpRequest();
    self.pending_request = null;
    self.request_arrived = Q.defer();
    self.fakexhr.onCreate = function(req) {
        if(defined(self.pending_request)) {
            throw "Request arrived while there is already a pending request.";
        }
        self.pending_request = req;
        self.request_arrived.resolve();
    };
};

FakeCountsServer.prototype = {
    restore: function() { this.fakexhr.restore(); },
    waitForRequest: function() { return this.request_arrived.promise; },
    getRequestURL: function() {
        if(!defined(this.pending_request)) {
            throw "getRequestURL fails: No pending request";
        }
        return removeUnderscoreQuery(this.pending_request.url);
    },
    respond: function(timeline_unacked_counts) {
        if(!defined(this.pending_request)) {
            throw "respond fails: No pending request";
        }
        this.pending_request.respond(
            200, {},
            JSON.stringify({"error": null, "unacked_counts": timeline_unacked_counts})
        );
        this.pending_request = null;
        this.request_arrived = Q.defer();
    }
};

asyncTest("single timeline, default init counts", function() {
    var server = new FakeCountsServer();
    var poller = new bb.UnackedCountsPoller({apiBase: "/apptop"});
    var received_counts_defer = Q.defer();
    poller.addTimeline({
        timelineName: "hoge",
        callback: function(unacked_counts) {
            received_counts_defer.resolve(unacked_counts);
        }
    });
    poller.start();
    server.waitForRequest().then(function() {
        is(server.getRequestURL(), "/apptop/updates/unacked_counts.json?level=total&tl_hoge=0", "first request URL OK");
        server.respond({"hoge": {"total": 10, "1": 5, "-1": 5}});
        return received_counts_defer.promise;
    }).then(function(received_counts) {
        deepEqual(received_counts, {"total": 10, "1": 5, "-1": 5}, "first received OK");
        received_counts = Q.defer();
        return server.waitForRequest();
    }).then(function() {
        is(server.getRequestURL(), "/apptop/updates/unacked_counts.json?level=total&tl_hoge=10", "second request URL OK");
    }).fail(function(error) {
        ok(false, "should not fail");
        ok(true, "reason: " + error);
    }).then(function() {
        server.restore();
        start();
    });
});

asyncTest("multiple timelines", function() {
    var server = new FakeCountsServer();
    var poller = new bb.UnackedCountsPoller({apiBase: "/apptop"});
    var received_counts_defers = [];
    $.each(["zero", "one", "two", "three"], function(i, name) {
        var init_counts = {total : (i+1)};
        init_counts[i+1] = i+1;
        received_counts_defers.push(Q.defer());
        poller.addTimeline({
            timelineName: name,
            callback: function(unacked_counts) {
                received_counts_defers[i].resolve(unacked_counts);
            },
            initialUnackedCounts: init_counts
        });
    });
    var resetReceivedCountsDefers = function(received_index_list) {
        var received_index_map = {};
        $.each(received_index_list, function(i, val) {
            received_index_map[val] = 1;
        });
        $.each(received_counts_defers, function(i, defer) {
            if(received_index_map[i]) {
                ok(!defer.promise.isPending(), "defer " + i + "should be resolved");
            }else {
                ok(defer.promise.isPending(), "defer " + i + "should be pending");
            }
        });
        received_counts_defers = $.map(received_counts_defers, function() { return Q.defer(); });
    }
    poller.start();
    server.waitForRequest().then(function() {
        is(server.getRequestURL(), "/apptop/updates/unacked_counts.json?level=total&tl_zero=1&tl_one=2&tl_two=3&tl_three=4", "first request OK");
        server.respond({"zero": {"total": 0}});
        return received_counts_defers[0].promise;
    }).then(function(unacked_counts_zero) {
        deepEqual(unacked_counts_zero, {"total": 0}, "response for zero OK");
        resetReceivedCountsDefers([0]);
        return server.waitForRequest();
    }).then(function() {
        is(server.getRequestURL(), "/apptop/updates/unacked_counts.json?level=total&tl_zero=0&tl_one=2&tl_two=3&tl_three=4", "second request OK");
        server.respond({
            "one": { "2": 3, "0": 2, "-4": 5, "total": 10 },
            "two": {  "4": 3, "1": 2, "total": 5 }
        });
        return received_counts_defers[1].promise;
    }).then(function(unacked_counts_one) {
        deepEqual(unacked_counts_one, { "2": 3, "0": 2, "-4": 5, "total": 10 }, "response for one OK");
        return received_counts_defers[2].promise;
    }).then(function(unacked_counts_two) {
        deepEqual(unacked_counts_two, {"4": 3, "1": 2, "total": 5}, "response for two OK");
        resetReceivedCountsDefers([1,2]);
        return server.waitForRequest();
    }).then(function() {
        is(server.getRequestURL(), "/apptop/updates/unacked_counts.json?level=total&tl_zero=0&tl_one=10&tl_two=5&tl_three=4", "third request OK");
        server.respond({
            "three": { "0": 5, "total": 5 },
        });
        return received_counts_defers[3].promise;
    }).then(function(unacked_counts_three) {
        deepEqual(unacked_counts_three, {"0": 5, "total": 5}, "response for three (0 => 5, total => 5) OK");
        resetReceivedCountsDefers([3]);
        return server.waitForRequest();
    }).then(function() {
        is(server.getRequestURL(), "/apptop/updates/unacked_counts.json?level=total&tl_zero=0&tl_one=10&tl_two=5&tl_three=5", "fourth request OK");
    }).fail(function(error) {
        ok(false, "should not fail");
        ok(true, "reason: " + error);
    }).then(function() {
        server.restore();
        start();
    });
});

    </script>
  </body>
</html>