stomp-client
Version:
A STOMP protocol implementation in node.js
189 lines (153 loc) • 6.46 kB
JavaScript
var util = require('util'),
Events = require('events').EventEmitter,
nodeunit = require('nodeunit'),
testCase = require('nodeunit').testCase,
StompFrame = require('../lib/frame').StompFrame;
// Mock net object so we never try to send any real data
var connectionObserver = new Events();
connectionObserver.writeBuffer = [];
connectionObserver.write = function(data) {
this.writeBuffer.push(data);
};
module.exports = testCase({
setUp: function(callback) {
callback();
},
tearDown: function(callback) {
connectionObserver.writeBuffer = [];
callback();
},
'test StompFrame utility methods work correctly': function (test) {
var frame = new StompFrame({
'command': 'HITME',
'headers': {
'header1': 'value1',
'header2': 'value2'
},
'body': 'wewp de doo'
});
test.equal(frame.command, 'HITME');
// setCommand
frame.setCommand('SOMETHINGELSE');
test.equal(frame.command, 'SOMETHINGELSE');
// setHeader
frame.setHeader('header2', 'newvalue');
test.equal(frame.headers['header2'], 'newvalue');
frame.setHeader('new-header', 'blah');
test.equal(frame.headers['new-header'], 'blah');
// TODO - Content-length assignment? Why is this done?
// appendToBody
frame.appendToBody('pip pop');
test.equal(frame.body, 'wewp de doopip pop');
test.done();
},
'test stream writes are correct on arbitrary frame definition': function (test) {
var frame = new StompFrame({
'command': 'HITME',
'headers': {
'header1': 'value1',
'header2': 'value2'
},
'body': 'wewp de doo'
});
// Command before headers, content-length auto-inserted, and terminating with null char (line feed chars for each line too)
var expectedStream = [
'HITME\n',
'header1:value1\n',
'header2:value2\n',
'content-length:11\n',
'\n',
'wewp de doo',
'\u0000'
];
frame.send(connectionObserver);
test.deepEqual(expectedStream.join(''), connectionObserver.writeBuffer.join(''), 'frame stream data is correctly output on the mocked wire');
test.done();
},
'check validation of arbitrary frame with arbitrary frame construct': function (test) {
var validation,
frameConstruct = {
'headers': {
'blah': { required: true },
'regexheader': { required: true, regex: /(wibble|wobble)/ }
}
};
var frame = new StompFrame({
'command': 'COMMAND',
'headers': {},
'body': ''
});
// Invalid header (required)
validation = frame.validate(frameConstruct);
test.equal(validation.isValid, false);
test.equal(validation.message, 'Header "blah" is required for COMMAND');
test.equal(validation.details, 'Frame: {"command":"COMMAND","headers":{},"body":""}');
frame.setHeader('blah', 'something or other'); // Set it now so it doesn't complain in later tests
// Invalid header (regex)
frame.setHeader('regexheader', 'not what it should be');
validation = frame.validate(frameConstruct);
test.equal(validation.isValid, false);
test.equal(validation.message, 'Header "regexheader" has value "not what it should be" which does not match against the following regex: /(wibble|wobble)/ (Frame: {"command":"COMMAND","headers":{"blah":"something or other","regexheader":"not what it should be"},"body":""})');
// Now make the header valid
frame.setHeader('regexheader', 'wibble');
validation = frame.validate(frameConstruct);
test.equal(validation.isValid, true);
frame.setHeader('regexheader', 'wobble');
validation = frame.validate(frameConstruct);
test.equal(validation.isValid, true, 'still valid!');
test.done();
},
'test content-length header is present when suppress-content-length is not': function(test) {
var frame = new StompFrame({
'command': 'SEND',
'body' : 'Content length is 20'
});
frame.send(connectionObserver);
//Check the headers for the content-length header
var writtenString = connectionObserver.writeBuffer.join('');
var containsContentLengthHeader = (writtenString.split("\n").indexOf("content-length:20") == -1 ? false : true);
test.equal(containsContentLengthHeader, true, "Content length header should exist since we are not suppressing it");
test.done();
},
'test content-length is not present when suppress-content-length is provided': function(test) {
var frame = new StompFrame({
'command': 'SEND',
'headers': {
'suppress-content-length': true
},
'body' : 'Content length is 20'
});
frame.send(connectionObserver);
//Check the headers for the content-length header
var writtenString = connectionObserver.writeBuffer.join('');
var containsContentLengthHeader = (writtenString.split("\n").indexOf("content-length:20") == -1 ? false : true);
test.equal(containsContentLengthHeader, false, "Content length header should not exist since we are suppressing it");
test.done();
},
'test stream write correctly handles single-byte UTF-8 characters': function(test) {
var frame = new StompFrame({
'command': 'SEND',
'body' : 'Welcome!'
});
frame.send(connectionObserver);
var writtenString = connectionObserver.writeBuffer.join('');
//Assume content-length header is second line
var contentLengthHeaderLine = writtenString.split("\n")[1];
var contentLengthValue = contentLengthHeaderLine.split(":")[1].trim();
test.equal(Buffer.byteLength(frame.body), contentLengthValue, "We should be truthful about how much data we plan to send to the server");
test.done();
},
'test stream write correctly handles multi-byte UTF-8 characters': function(test) {
var frame = new StompFrame({
'command': 'SEND',
'body' : 'Ẇḗḽḉớḿẽ☃'
});
frame.send(connectionObserver);
var writtenString = connectionObserver.writeBuffer.join('');
//Assume content-length header is second line
var contentLengthHeaderLine = writtenString.split("\n")[1];
var contentLengthValue = contentLengthHeaderLine.split(":")[1].trim();
test.equal(Buffer.byteLength(frame.body), contentLengthValue, "We should be truthful about how much data we plan to send to the server");
test.done();
}
});