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.
var io = require("socket.io-client");
var fixtureSocket = require("can-fixture-socket");
var mockServer = new fixtureSocket.Server(io);
Parameters
- io
{Object}
:Imported
socket.io-client
object.
Use
- Instantiate a server to intercept socket.io connection:
var io = require("socket.io-client");
var fixtureSocket = require("can-fixture-socket");
var 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:
var 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.
var fixture = require("can-fixture");
// First, lets create fixture store:
var 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:
var io = require("socket.io-client");
var fixtureSocket = require("can-fixture-socket");
var 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:
var 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.
var 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");
});