thywill
Version:
A Node.js clustered framework for single page web applications based on asynchronous messaging.
213 lines (193 loc) • 6.62 kB
JavaScript
/**
* @fileOverview
* Vows tests for the Chat example application.
*
* These are cluster tests using Express, Redis, and multiple Thywill
* processes.
*/
var assert = require('assert');
var tools = require('../lib/tools');
var batchName, sendMessage, responseMessage;
// Obtain a test suit that launches Thywill instances in child processes,
// but where the Socket.IO clients haven't connected yet.
var suite = tools.application.vowsSuitePendingConnections('Application: Chat', {
applicationName: 'chat',
// The initial batches load the application page and then connect via
// Socket.IO. The matches are checked against the page contents. Here
// we're looking at the templates that should be included.
pageMatches: [
'<span class="channel">{{channelId}}</span>',
'<div class="chat-message disconnect-message">Chat partner disconnected.</div>',
'<div class="chat-message">{{data}}</div>',
'<div class="chat-message reconnect-message">Chat partner reconnected.</div>',
'<div id="waiting" class="notice">{{waitingText}}</div>'
],
// Data for the processes to launch.
processData: [
{
port: 10078,
clusterMemberId: 'alpha'
},
{
port: 10079,
clusterMemberId: 'beta'
}
],
// Set a long timeout for actions, because things sometimes lag on a small
// server when running a bunch of tests.
defaultTimeout: 5000
});
// Make the Socket.IO connection to alpha.
suite.addBatch({
'Make Socket.IO connection to alpha': {
topic: function () {
suite.clients[0].action({
type: 'connect',
socketConfig: {
'resource': 'chat/socket.io'
}
}, this.callback);
},
'successfully connected': function (error) {
assert.isUndefined(error);
}
}
});
// Delay to allow that to complete recording the user, setting data in Redis.
tools.addDelayBatch(suite, 100);
// Connect to beta and wait on the messages confirming a chat being set up
// that are sent to both alpha and beta connections. The response messages
// have a channelId in them based on connection Ids, so have to use a
// custom vow function to check the results.
batchName = 'Make Socket.IO connection to beta, catch chat setup messages to alpha and beta';
tools.application.addConnectAndAwaitResponsesBatch(batchName, suite, {
applicationId: 'chat',
actionIndex: 1,
responseIndexes: [0, 1],
vows: {
'expected responses on connect': function (unusedError, results) {
assert.isNull(results[0].error);
assert.isNull(results[1].error);
// Check the one to see if the contents are expected.
assert.strictEqual(results[0].socketEvent.args[0], 'chat');
var data = results[0].socketEvent.args[1].data;
assert.strictEqual(data.action, 'startChat');
// The two messages are published to the room, so they should be the same.
assert.deepEqual(results[0].socketEvent, results[1].socketEvent);
}
}
});
// Send a message, see it returned to both clients.
batchName = 'Send chat message from alpha';
sendMessage = {
action: 'message',
message: 'test'
};
responseMessage = sendMessage;
tools.application.addSendAndAwaitResponsesBatch(batchName, suite, {
applicationId: 'chat',
actionIndex: 0,
responseIndexes: [0, 1],
sendMessage: sendMessage,
responseMessage: responseMessage
});
// Disconnect beta, see disconnection message show up at alpha.
batchName = 'Disconnect beta, check disconnect notice for alpha';
tools.application.addDisconnectAndAwaitResponsesBatch(batchName, suite, {
applicationId: 'chat',
actionIndex: 1,
responseIndexes: 0,
responseMessage: {
action: 'disconnected'
}
});
// Reload page for page, as that needs to happen prior to reconnecting.
suite.addBatch({
'Reload application page for beta': {
topic: function () {
suite.clients[1].action('/chat/', this.callback);
},
'page fetched': function (error, page) {
assert.isNull(error);
assert.isObject(page);
assert.strictEqual(page.statusCode, 200);
}
}
});
// Reconnect beta, see reconnection message show up at alpha.
batchName = 'Connect beta, check connect notice for alpha';
tools.application.addConnectAndAwaitResponsesBatch(batchName, suite, {
applicationId: 'chat',
actionIndex: 1,
responseIndexes: 0,
responseMessage: {
action: 'reconnected'
}
});
// Delay to let things settle down following reconnection.
tools.addDelayBatch(suite, 100);
// Beta kicks alpha.
batchName = 'Beta issues kick, check kicked notice for alpha';
sendMessage = {
action: 'kick'
};
responseMessage = {
action: 'kicked'
};
tools.application.addSendAndAwaitResponsesBatch(batchName, suite, {
applicationId: 'chat',
actionIndex: 1,
responseIndexes: 0,
sendMessage: sendMessage,
responseMessage: responseMessage
});
// Delay to let things settle down following kick.
tools.addDelayBatch(suite, 500);
// Beta asks to find partner.
var message = tools.wrapAsMessage({
action: 'findPartner'
});
suite.addBatch({
'Beta issues request for new partner': {
topic: function () {
suite.clients[1].action({
type: 'emit',
args: ['fromClient', 'chat', message.toObject()]
}, this.callback);
},
'request sent': function (error) {
assert.isUndefined(error);
}
}
});
// Delay to let things settle down following request.
tools.addDelayBatch(suite, 500);
// Alpha searches for partner, gets paired up with beta again.
batchName = 'Alpha issues findPartner, check to see if paired with beta again';
sendMessage = {
action: 'findPartner'
};
tools.application.addSendAndAwaitResponsesBatch(batchName, suite, {
applicationId: 'chat',
actionIndex: 0,
responseIndexes: [0, 1],
sendMessage: sendMessage,
vows: {
'expected responses on connect': function (unusedError, results) {
assert.isNull(results[0].error);
assert.isNull(results[1].error);
// Check the one to see if the contents are expected.
assert.strictEqual(results[0].socketEvent.args[0], 'chat');
var data = results[0].socketEvent.args[1].data;
assert.strictEqual(data.action, 'startChat');
// The two messages are published to the room, so they should be the same.
assert.deepEqual(results[0].socketEvent, results[1].socketEvent);
}
}
});
// Ensure that clients are closed and child processes are killed.
tools.application.closeVowsSuite(suite);
//-----------------------------------------------------------
// Exports - Vows test suite
//-----------------------------------------------------------
module.exports.suite = suite;