Permalink
Browse files

Recover agents from a client that aborts. Ref #45.

  • Loading branch information...
1 parent 3f38d6c commit 851320aaa592806699ac91149bab2e84da3ad2cc @reid committed Apr 19, 2012
Showing with 100 additions and 0 deletions.
  1. +5 −0 lib/hub/agent.js
  2. +16 −0 lib/hub/batch.js
  3. +79 −0 test/functional.js
View
@@ -76,6 +76,11 @@ Agent.prototype.connect = function (socket) {
this.socketEmitter.add(socket);
};
+Agent.prototype.abort = function () {
+ this.urlQueue = [];
+ this.next();
+};
+
Agent.prototype.nextURL = function () {
var url;
View
@@ -69,6 +69,20 @@ Batch.prototype.completeAgent = function (agent) {
}
};
+// The CLI client has disconnected.
+Batch.prototype.handleUnexpectedEnd = function () {
+ var self = this;
+ Object.keys(this.runningAgents).forEach(function (id) {
+ var agent = self.agents[id];
+
+ delete self.runningAgents[id];
+
+ self.agentEmitter.remove(agent);
+
+ agent.abort();
+ });
+};
+
Batch.prototype.proxyEvent = function (yoshiEvent, selfEvent) {
var self = this;
@@ -104,6 +118,8 @@ Batch.prototype.setupAgentEmitter = function () {
self.on("agentComplete", function (agent) {
self.completeAgent(agent);
});
+
+ self.batchSession.on("end", self.handleUnexpectedEnd.bind(self));
};
Batch.prototype.getId = function () {
View
@@ -153,6 +153,79 @@ function createBatchTopic(createBatchConfiguration) {
};
}
+function clientErrorContext(createBatchConfiguration) {
+ return captureContext({
+ topic: function (pageTopic, browser, lastTopic) {
+ var vow = this,
+ results = [],
+ batchStarted = false,
+ dispatchTimeout = setTimeout(function () {
+ vow.callback(new Error("Batch dispatch failed for " + lastTopic.url));
+ process.exit(1);
+ }, 20000),
+ seenTimeout,
+ batch = lastTopic.client.createBatch(createBatchConfiguration);
+
+ function onFinalPage(pathname) {
+ if (!pathname) {
+ // We were called from setTimeout.
+ pathname = "FAIL";
+ }
+
+ pageTopic.page.release();
+ vow.callback(null, {
+ expectedPathname: lastTopic.pathname,
+ finalPathname: pathname
+ });
+ }
+
+ seenTimeout = setTimeout(onFinalPage, 2000);
+
+ function finalPageCheck() {
+ pageTopic.page.evaluate(function () {
+ /*global window:true */
+ // This function runs in the scope of the web page.
+ return window.location.pathname;
+ }, function (pathname) {
+ onFinalPage(pathname);
+ });
+ }
+
+ lastTopic.client.on("agentSeen", function onAgentSeen() {
+ clearTimeout(dispatchTimeout);
+ clearTimeout(seenTimeout);
+
+ pageTopic.page.evaluate(function () {
+ /*global window:true */
+ // This function runs in the scope of the web page.
+ return window.location.pathname;
+ }, function (pathname) {
+ // We expect this event to fire like this:
+ // 1st: Navigate to capture page.
+ // 2nd: Navigate from capture to first test.
+
+ if (pathname.indexOf("/batch") !== 0) {
+ // 1st fire.
+ return;
+ }
+
+ // 2nd fire. This section runs during the test.
+ // We are done with this event.
+ lastTopic.client.removeListener("agentSeen", onAgentSeen);
+
+ // Disconnect from the Hub.
+ lastTopic.client.end();
+
+ setTimeout(finalPageCheck, 200);
+ });
+ });
+ },
+ "the browser returned to the capture page": function (topic) {
+ assert.strictEqual(topic.finalPathname, topic.expectedPathname);
+ }
+ });
+}
+
function visitorContext(createBatchConfiguration) {
return captureContext({
topic: createBatchTopic(createBatchConfiguration),
@@ -346,6 +419,12 @@ vows.describe("Yeti Functional")
})
}))
.addBatch(hub.functionalContext({
+ "visits Yeti and disconnects": clientErrorContext({
+ basedir: __dirname + "/fixture",
+ tests: ["basic.html", "local-js.html"]
+ })
+ }))
+ .addBatch(hub.functionalContext({
"visits Yeti with invalid files": errorContext({
basedir: __dirname + "/fixture",
tests: ["this-file-does-not-exist.html"]

0 comments on commit 851320a

Please sign in to comment.