First pass at tests and initial bugfixes/necessary features, including onReady callback.

This commit is contained in:
Ian Gulliver
2014-05-13 19:12:06 +03:00
parent 600054b5ca
commit 3a3cba9be3
4 changed files with 122 additions and 8 deletions

View File

@@ -108,7 +108,9 @@ class Subject(db.Model):
subject = cls.get_by_key_name(name)
if subject:
return subject
return cls(key_name=name).put()
subject = cls(key_name=name)
subject.put()
return subject
@db.transactional()
def GetRecentMessages(self, num_messages):

View File

@@ -38,6 +38,8 @@ Cosmopolite = function(callbacks, urlPrefix, namespace) {
this.urlPrefix_ = urlPrefix || '/cosmopolite';
this.namespace_ = namespace || 'cosmopolite';
this.shutdown_ = false;
this.subscriptions_ = {};
var scriptUrls = [
@@ -53,6 +55,18 @@ Cosmopolite = function(callbacks, urlPrefix, namespace) {
}, this);
};
Cosmopolite.prototype.shutdown = function() {
this.shutdown_ = true;
if (this.socket_) {
var socket = this.socket_;
this.socket_ = null;
socket.close();
}
if (this.$) {
this.$('window').off('message');
}
};
/**
* Subscribe to a subject.
*
@@ -141,8 +155,15 @@ Cosmopolite.prototype.onLoad_ = function() {
return;
}
this.$ = jQuery.noConflict(true);
if (this.shutdown_) {
// Shutdown during startup
return;
}
this.registerMessageHandlers_();
this.createChannel_();
if ('onReady' in this.callbacks_) {
this.callbacks_['onReady']();
};
};
/**
@@ -153,13 +174,13 @@ Cosmopolite.prototype.onLoad_ = function() {
Cosmopolite.prototype.onReceiveMessage_ = function(data) {
switch (data) {
case 'login_complete':
this.socket.close();
this.socket_.close();
break;
case 'logout_complete':
localStorage.removeItem(this.namespace_ + ':client_id');
localStorage.removeItem(this.namespace_ + ':google_user_id');
this.$('#google_user').empty();
this.socket.close();
this.socket_.close();
break;
default:
console.log('Unknown event type:', data);
@@ -311,9 +332,12 @@ Cosmopolite.prototype.createChannel_ = function() {
* @param {!Object} data Server response including channel token
*/
Cosmopolite.prototype.onCreateChannel_ = function(data) {
if (this.shutdown_) {
return;
}
var channel = new goog.appengine.Channel(data['token']);
console.log('Opening channel...');
this.socket = channel.open({
this.socket_ = channel.open({
onopen: this.$.proxy(this.onSocketOpen_, this),
onclose: this.$.proxy(this.onSocketClose_, this),
onmessage: this.$.proxy(this.onSocketMessage_, this),
@@ -332,11 +356,11 @@ Cosmopolite.prototype.onSocketOpen_ = function() {
* Callback from channel library for closure; reopen.
*/
Cosmopolite.prototype.onSocketClose_ = function() {
if (!this.socket) {
if (!this.socket_) {
return;
}
console.log('Channel closed');
this.socket = null;
this.socket_ = null;
this.createChannel_();
};
@@ -405,7 +429,7 @@ Cosmopolite.prototype.onServerEvent_ = function(e) {
*/
Cosmopolite.prototype.onSocketError_ = function(msg) {
console.log('Socket error:', msg);
this.socket.close();
this.socket_.close();
};
/* Exported values */

View File

@@ -1,6 +1,6 @@
<html>
<head>
<script type="text/javascript" src="/cosmopolite/static/cosmopolite.js" charset="UTF-8"></script>
<script src="/cosmopolite/static/cosmopolite.js" charset="UTF-8"></script>
<style>
a {
text-decoration: none;

88
static/test.html Normal file
View File

@@ -0,0 +1,88 @@
<html>
<head>
<meta charset="utf-8">
<title>Cosmopolite tests</title>
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-git.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="https://code.jquery.com/qunit/qunit-git.js"></script>
<script src="/cosmopolite/static/cosmopolite.js" charset="UTF-8"></script>
<script>
QUnit.begin(localStorage.clear.bind(localStorage));
QUnit.done(localStorage.clear.bind(localStorage));
var randstring = function() {
var ret = [];
for (var i = 0; i < 16; i++) {
var ran = (Math.random() * 16) | 0;
ret.push(ran.toString(16));
}
return ret.join('');
};
test('Construct/shutdown', function() {
expect(2);
var cosmo = new Cosmopolite({});
ok(true, 'new Cosmopolite() succeeds');
cosmo.shutdown();
ok(true, 'shutdown() succeeds');
});
asyncTest('onLogin or onLogout', function() {
expect(1);
var callbacks = {
'onLogin': function(user, logout_url) {
ok(true, 'onLogin fired');
cosmo.shutdown();
start();
},
'onLogout': function(login_url) {
ok(true, 'onLogout fired');
cosmo.shutdown();
start();
}
};
var cosmo = new Cosmopolite(callbacks);
});
asyncTest('Message round trip', function() {
expect(2);
var subject = randstring();
var message = randstring();
console.log('subject:', subject);
console.log('message:', message);
var callbacks1 = {
'onReady': function() {
console.log('onReady 1');
cosmo1.sendMessage(subject, message);
},
};
var callbacks2 = {
'onReady': function() {
console.log('onReady 2');
cosmo2.subscribe(subject, -1);
},
'onMessage': function(e) {
console.log('onMessage');
equal(e['subject'], subject, 'subject matches');
equal(e['message'], message, 'message matches');
cosmo1.shutdown();
cosmo2.shutdown();
start();
},
};
var cosmo1 = new Cosmopolite(callbacks1, null, randstring());
var cosmo2 = new Cosmopolite(callbacks2, null, randstring());
});
</script>
</body>
</html>