Telegram Web, preconfigured for usage in I2P. http://web.telegram.i2p/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
7.2 KiB

11 years ago
var helper = require('./helper');
var events = require('./events');
var logger = require('./logger');
var Result = function() {
var startTime = Date.now();
this.total = this.skipped = this.failed = this.success = 0;
this.netTime = this.totalTime = 0;
this.disconnected = this.error = false;
this.totalTimeEnd = function() {
this.totalTime = Date.now() - startTime;
};
};
// The browser is ready to execute tests.
var READY = 1;
// The browser is executing the tests/
var EXECUTING = 2;
// The browser is not executing, but temporarily disconnected (waiting for reconnecting).
var READY_DISCONNECTED = 3;
// The browser is executing the tests, but temporarily disconnect (waiting for reconnecting).
var EXECUTING_DISCONNECTED = 4;
// The browser got permanently disconnected (being removed from the collection and destroyed).
var DISCONNECTED = 5;
var Browser = function(id, fullName, /* capturedBrowsers */ collection, emitter, socket, timer,
/* config.browserDisconnectTimeout */ disconnectDelay) {
var name = helper.browserFullNameToShort(fullName);
var log = logger.create(name);
this.id = id;
this.fullName = fullName;
this.name = name;
this.state = READY;
this.lastResult = new Result();
this.init = function() {
collection.add(this);
events.bindAll(this, socket);
log.info('Connected on socket %s', socket.id);
// TODO(vojta): remove launchId,
// it's here just for WebStorm B-C.
this.launchId = this.id;
this.id = socket.id;
// TODO(vojta): move to collection
emitter.emit('browsers_change', collection);
emitter.emit('browser_register', this);
};
this.isReady = function() {
return this.state === READY;
};
this.toString = function() {
return this.name;
};
this.onError = function(error) {
if (this.isReady()) {
return;
}
this.lastResult.error = true;
emitter.emit('browser_error', this, error);
};
this.onInfo = function(info) {
if (this.isReady()) {
return;
}
// TODO(vojta): remove
if (helper.isDefined(info.dump)) {
emitter.emit('browser_log', this, info.dump, 'dump');
}
if (helper.isDefined(info.log)) {
emitter.emit('browser_log', this, info.log, info.type);
}
if (helper.isDefined(info.total)) {
this.lastResult.total = info.total;
}
};
this.onComplete = function(result) {
if (this.isReady()) {
return;
}
this.state = READY;
this.lastResult.totalTimeEnd();
if (!this.lastResult.success) {
this.lastResult.error = true;
}
emitter.emit('browsers_change', collection);
emitter.emit('browser_complete', this, result);
};
var self = this;
var disconnect = function() {
self.state = DISCONNECTED;
log.warn('Disconnected');
collection.remove(self);
};
var pendingDisconnect;
this.onDisconnect = function() {
if (this.state === READY) {
disconnect();
} else if (this.state === EXECUTING) {
log.debug('Disconnected during run, waiting for reconnecting.');
this.state = EXECUTING_DISCONNECTED;
pendingDisconnect = timer.setTimeout(function() {
self.lastResult.totalTimeEnd();
self.lastResult.disconnected = true;
disconnect();
emitter.emit('browser_complete', self);
}, disconnectDelay);
}
};
this.onReconnect = function(newSocket) {
if (this.state === EXECUTING_DISCONNECTED) {
this.state = EXECUTING;
log.debug('Reconnected.');
} else if (this.state === EXECUTING || this.state === READY) {
log.debug('New connection, forgetting the old one.');
// TODO(vojta): this should only remove this browser.onDisconnect listener
socket.removeAllListeners('disconnect');
}
socket = newSocket;
events.bindAll(this, newSocket);
if (pendingDisconnect) {
timer.clearTimeout(pendingDisconnect);
}
};
this.onResult = function(result) {
if (result.length) {
return result.forEach(this.onResult, this);
}
// ignore - probably results from last run (after server disconnecting)
if (this.isReady()) {
return;
}
if (result.skipped) {
this.lastResult.skipped++;
} else if (result.success) {
this.lastResult.success++;
} else {
this.lastResult.failed++;
}
this.lastResult.netTime += result.time;
emitter.emit('spec_complete', this, result);
};
this.serialize = function() {
return {
id: this.id,
name: this.name,
isReady: this.state === READY
};
};
};
Browser.STATE_READY = READY;
Browser.STATE_EXECUTING = EXECUTING;
Browser.STATE_READY_DISCONNECTED = READY_DISCONNECTED;
Browser.STATE_EXECUTING_DISCONNECTED = EXECUTING_DISCONNECTED;
Browser.STATE_DISCONNECTED = DISCONNECTED;
var Collection = function(emitter, browsers) {
browsers = browsers || [];
this.add = function(browser) {
browsers.push(browser);
emitter.emit('browsers_change', this);
};
this.remove = function(browser) {
var index = browsers.indexOf(browser);
if (index === -1) {
return false;
}
browsers.splice(index, 1);
emitter.emit('browsers_change', this);
return true;
};
this.getById = function(browserId) {
for (var i = 0; i < browsers.length; i++) {
// TODO(vojta): use id, once we fix WebStorm plugin
if (browsers[i].launchId === browserId) {
return browsers[i];
}
}
return null;
};
this.setAllToExecuting = function() {
browsers.forEach(function(browser) {
browser.state = EXECUTING;
});
emitter.emit('browsers_change', this);
};
this.areAllReady = function(nonReadyList) {
nonReadyList = nonReadyList || [];
browsers.forEach(function(browser) {
if (!browser.isReady()) {
nonReadyList.push(browser);
}
});
return nonReadyList.length === 0;
};
this.serialize = function() {
return browsers.map(function(browser) {
return browser.serialize();
});
};
this.getResults = function() {
var results = browsers.reduce(function(previous, current) {
previous.success += current.lastResult.success;
previous.failed += current.lastResult.failed;
previous.error = previous.error || current.lastResult.error;
previous.disconnected = previous.disconnected || current.lastResult.disconnected;
return previous;
}, {success: 0, failed: 0, error: false, disconnected: false, exitCode: 0});
// compute exit status code
results.exitCode = results.failed || results.error || results.disconnected ? 1 : 0;
return results;
};
this.clearResults = function() {
browsers.forEach(function(browser) {
browser.lastResult = new Result();
});
};
this.clone = function() {
return new Collection(emitter, browsers.slice());
};
// Array APIs
this.map = function(callback, context) {
return browsers.map(callback, context);
};
this.forEach = function(callback, context) {
return browsers.forEach(callback, context);
};
// this.length
Object.defineProperty(this, 'length', {
get: function() {
return browsers.length;
}
});
};
Collection.$inject = ['emitter'];
exports.Result = Result;
exports.Browser = Browser;
exports.Collection = Collection;