Skip to content

Commit

Permalink
test: migrate call and callback tests
Browse files Browse the repository at this point in the history
Refs: #145
Refs: #146
Refs: #53
PR-URL: #200
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
  • Loading branch information
nechaido committed Jun 2, 2017
1 parent 27cac40 commit 8bbb479
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 209 deletions.
23 changes: 21 additions & 2 deletions test/fixtures/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,25 @@ const login = 'login';
const password = 'password';
const sessionId = '12892e85-5bd7-4c77-a0c5-a0aecfcbc93a';

const interfaces = {};
const expectedErrorMessage = 'Zero division';

const interfaces = {
calculator: {
answer(connection, callback) {
callback(null, 42);
},
divide(connection, divident, divisor, callback) {
if (!divisor) {
callback(new Error(expectedErrorMessage));
} else {
callback(null, divident / divisor);
}
},
doNothing(connection, callback) {
callback(null);
}
}
};

const authCallback = (
connection, application, strategy, credentials, callback
Expand Down Expand Up @@ -42,5 +60,6 @@ module.exports = {
login,
password,
sessionId,
authCallback
authCallback,
expectedErrorMessage
};
98 changes: 98 additions & 0 deletions test/node/connection-call.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
'use strict';

const test = require('tap');

const jstp = require('../..');

const app = require('../fixtures/application');

const application = new jstp.Application(app.name, app.interfaces);

let server;
let client;

test.beforeEach((done) => {
server = jstp.tcp.createServer(0, [application], app.authCallback);
server.listen(() => {
const port = server.address().port;
client = jstp.tcp.createClient({ host: 'localhost', port });
done();
});
});

test.afterEach((done) => {
client.disconnect();
server.close();
done();
});

test.test('must perform call with no arguments and no return value', (test) => {
client.connectAndHandshake(app.name, null, null, (error, connection) => {
connection.callMethod('calculator', 'doNothing', [], (error) => {
test.assertNot(error, 'callMethod must not return an error');
test.end();
});
});
});

test.test('must perform call with no arguments and return value', (test) => {
client.connectAndHandshake(app.name, null, null, (error, connection) => {
connection.callMethod('calculator', 'answer', [], (error, result) => {
test.assertNot(error, 'callMethod must not return an error');
test.equal(result, 42);
test.end();
});
});
});

test.test('must perform call with arguments and return value', (test) => {
client.connectAndHandshake(app.name, null, null, (error, connection) => {
connection.callMethod('calculator', 'divide', [20, 10],
(error, result) => {
test.assertNot(error, 'callMethod must not return an error');
test.equal(result, 2);
test.end();
}
);
});
});

test.test('must perform call that returns an error', (test) => {
client.connectAndHandshake(app.name, null, null, (error, connection) => {
connection.callMethod('calculator', 'divide', [10, 0], (error) => {
test.assert(error, 'callMethod must return an error');
test.equal(error.message,
new jstp.RemoteError(new Error(app.expectedErrorMessage)).message);
test.end();
});
});
});

test.test('must return error on call to nonexistent interface', (test) => {
client.connectAndHandshake(app.name, null, null, (error, connection) => {
connection.callMethod(
'__nonexistent_interface__',
'__nonexistent_method__',
[],
(error) => {
test.assert(error, 'callMethod must return an error');
test.equal(error.code, jstp.ERR_INTERFACE_NOT_FOUND,
'error must be an ERR_INTERFACE_NOT_FOUND');
test.end();
}
);
});
});

test.test('must return error on call to nonexistent method', (test) => {
client.connectAndHandshake(app.name, null, null, (error, connection) => {
connection.callMethod('calculator', '__nonexistent_method__', [],
(error) => {
test.assert(error, 'callMethod must return an error');
test.equal(error.code, jstp.ERR_METHOD_NOT_FOUND,
'error must be an ERR_METHOD_NOT_FOUND');
test.end();
}
);
});
});
207 changes: 0 additions & 207 deletions test/unit/connection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,213 +135,6 @@ describe('JSTP Connection', () => {
});
});

describe('call', () => {
testPacketSending('call', (connection, transport) => {
let packetId;

const sendSpy = chai.spy((data) => {
const packet = jstp.parse(data);

expect(packet).to.have.all.keys(['call', 'method1']);
expect(packet.call).to.be.an('array');

packetId = packet.call[0];
expect(packet.call[1]).to.equal(constants.TEST_INTERFACE);
});

const callback = chai.spy((error, result) => {
expect(error).to.not.exist;
expect(result).to.equal(42);
});

transport.on('dataSent', sendSpy);

connection.callMethod(constants.TEST_INTERFACE, 'method1', [], callback);
expect(sendSpy).to.have.been.called();

transport.emitPacket({
callback: [packetId],
ok: [42]
});

expect(callback).to.have.been.called();
});

it('must process a method call with no arguments and result', () => {
emulateHandshakeOnServer();

const sendSpy = chai.spy.on(serverTransportMock, 'send');

serverTransportMock.emitPacket({
call: [1, constants.TEST_INTERFACE],
method1: []
});

expect(sendSpy).to.be.called.with(jstp.stringify({
callback: [1],
ok: []
}));

sendSpy.reset();
});

it('must process a method call with arguments and a result', () => {
emulateHandshakeOnServer();

const sendSpy = chai.spy.on(serverTransportMock, 'send');

serverTransportMock.emitPacket({
call: [1, constants.TEST_INTERFACE],
method2: [10, 20]
});

expect(sendSpy).to.be.called.with(jstp.stringify({
callback: [1],
ok: [30]
}));

sendSpy.reset();
});

it('must process a method call that returns an error', () => {
emulateHandshakeOnServer();

const sendSpy = chai.spy.on(serverTransportMock, 'send');

serverTransportMock.emitPacket({
call: [1, constants.TEST_INTERFACE],
method3: []
});

expect(sendSpy).to.be.called.with(jstp.stringify({
callback: [1],
error: [1, 'Error: Example error']
}));

sendSpy.reset();
});

it('must process a method that throws an error', () => {
emulateHandshakeOnServer();

const sendSpy = chai.spy.on(serverTransportMock, 'send');

expect(() => {
serverTransportMock.emitPacket({
call: [1, constants.TEST_INTERFACE],
method4: []
});
}).to.throw();

expect(sendSpy).to.be.called.with(jstp.stringify({
callback: [1],
error: [jstp.ERR_INTERNAL_API_ERROR]
}));

sendSpy.reset();
});

it('must return an error when an interface does not exist', () => {
emulateHandshakeOnServer();

const sendSpy = chai.spy.on(serverTransportMock, 'send');

serverTransportMock.emitPacket({
call: [1, 'dummy interface'],
method1: []
});

expect(sendSpy).to.be.called.with(jstp.stringify({
callback: [1],
error: [jstp.ERR_INTERFACE_NOT_FOUND]
}));

sendSpy.reset();
});

it('must return an error when a method does not exist', () => {
emulateHandshakeOnServer();

const sendSpy = chai.spy.on(serverTransportMock, 'send');

serverTransportMock.emitPacket({
call: [1, constants.TEST_INTERFACE],
methodThatDoesNotExist: []
});

expect(sendSpy).to.be.called.with(jstp.stringify({
callback: [1],
error: [jstp.ERR_METHOD_NOT_FOUND]
}));

sendSpy.reset();
});
});

describe('callback', () => {
testPacketSending('callback', (connection, transport) => {
const sendSpy = chai.spy((data) => {
const packet = jstp.parse(data);

expect(packet).to.contain.all.keys(['callback']);
expect(packet).to.contain.any.keys(['ok', 'error']);

if (packet.ok) {
expect(packet.callback).to.eql([10]);
expect(packet.ok).to.eql([42]);
} else {
expect(packet.callback).to.eql([11]);
expect(packet.error).to.eql([jstp.ERR_METHOD_NOT_FOUND]);
}
});

transport.on('dataSent', sendSpy);

connection.callback(10, null, [42]);
connection.callback(11, new jstp.RemoteError(jstp.ERR_METHOD_NOT_FOUND));

expect(sendSpy).to.have.been.called.twice;
});

it('must process a callback packet with a result', () => {
const callback = chai.spy((error, result) => {
expect(error).to.not.exist;
expect(result).to.equal('result');
});

performHandshakeFromClient(() => {
clientConnection.callMethod(
constants.TEST_INTERFACE, 'method', [], callback);

clientTransportMock.emitPacket({
callback: [1],
ok: ['result']
});

expect(callback).to.be.called();
});
});

it('must process a callback packet with an error', () => {
const callback = chai.spy((error) => {
expect(error).to.be.an.instanceof(jstp.RemoteError);
expect(error.code).to.equal(jstp.ERR_INTERNAL_API_ERROR);
});

performHandshakeFromClient(() => {
clientConnection.callMethod(
constants.TEST_INTERFACE, 'method', [], callback);

clientTransportMock.emitPacket({
callback: [1],
error: [jstp.ERR_INTERNAL_API_ERROR]
});

expect(callback).to.be.called();
});
});
});

describe('event', () => {
testPacketSending('event', (connection, transport) => {
const eventArgs = [ 'value' ];
Expand Down

0 comments on commit 8bbb479

Please sign in to comment.