Server
Intercept socket.io messages and simulates socket.io server responses.
new Server( io )
When server is instantiated with socket.io io
object it intercepts a socket.io connection and allows to mock socket.io server behaviour. On instantiation we:
- empty
io.managers
object which is a cache of socket.ioio.Manager
instances; - override
io.Manager.prototype
to work with current instance of the mocked server.
import io from "socket.io-client";
import fixtureSocket from "can-fixture-socket";
const mockServer = new fixtureSocket.Server( io );
Parameters
- io
{Object}
:Imported
socket.io-client
object.
Use
- Instantiate a server to intercept socket.io connection:
import io from "socket.io-client";
import fixtureSocket from "can-fixture-socket";
const mockServer = new fixtureSocket.Server( io );
- Mock socket.io server behaviour:
mockServer.on( "connection", function() {
mockServer.emit( "notifications", [ { text: "A new notification" } ] );
} );
mockServer.on( "some event", function( data, ackCb ) {
console.log( "Client send some ", data );
ackCb( "thanks" );
} );
- Test your client app:
const socket = io( "http://localhost:8080/ws" );
socket.emit( "some event", "some data", function( data ) {
assert.equal( data, "thanks", "Server acknowledged our event" );
} );
Examples
CRUD service with fixture store
Lets see how we can test a possible implementation of a CRUD service that utilizes socket.io ACK callbacks. We will use fixture store to emulate our CRUD storage and link it to our mocked server.
import fixture from "can-fixture";
// First, lets create fixture store:
const fixtureStore = fixture.store( [
{ id: 1, title: "One", rank: "good" },
{ id: 2, title: "Two", rank: "average" },
{ id: 3, title: "Three", rank: "good" }
], new canSet.Algebra( {} ) );
// And instantiate a mocked server:
import io from "socket.io-client";
import fixtureSocket from "can-fixture-socket";
const mockServer = new fixtureSocket.Server( io );
Fixture store is designed to work with XHR requests, thus its methods take two arguments: request
and response
. See [can-fixture.Store.prototype.getListData] for more details. Our mocked server can listen to socket events and its event listener expects data and an optional ACK callback. To convert a request handler to an event listener we can use requestHandlerToListener:
Now we can create socket event listeners for our CRUD operations:
const toListener = fixtureSocket.requestHandlerToListener;
mockServer.on( "messages find", toListener( fixtureStore.getListData ) );
mockServer.on( "messages get", toListener( fixtureStore.getData ) );
mockServer.on( "messages remove", toListener( fixtureStore.destroyData ) );
mockServer.on( "messages create", toListener( fixtureStore.createData ) );
mockServer.on( "messages update", toListener( fixtureStore.updateData ) );
There is also a helper storeToListeners to create all listeners at once:
var listeners = fixtureSocket.storeToListeners(messagesStore);
mockServer.on({
"messages find": listeners.getListData,
"messages get": listeners.getData,
"messages remove": listeners.destroyData,
"messages create": listeners.createData,
"messages update": listeners.updateData
});
Now lets implement a CRUD model on our client. We define that all our ACK callbacks take an error as the first argument, and data as the second one.
const socket = io( "localhost" );
socket.emit( "messages find", { rank: "good" }, function( err, response ) {
if ( err ) {
console.log( "Error: ", err );
return;
}
console.log( `We found ${response.count} good items`, response.data );
assert.equal( response.count, 3 );
} );
Now lets test the rest of the methods:
socket.emit( "messages get", { id: 1 }, function( err, data ) {
s;
assert.deepEqual( data, { id: 1, title: "One" }, "received the item" );
} );
socket.emit( "messages update", { id: 2, title: "TwoPlus" }, function( err, data ) {
assert.deepEqual( data, { id: 2, title: "TwoPlus" }, "received the updated item" );
} );
socket.emit( "messages get", { id: 999 }, function( err, data ) {
assert.deepEqual( err,
{ error: 404, message: "no data" },
"received 404 when looking for a non-existent item id"
);
} );