can-fixture-socket
Simulate socket.io services.
Object
can-fixture-socket
intercepts socket.io messages and simulates socket.io server responses.
The can-fixture-socket
module exports an object with:
- Server, a constructor function which instance intercepts the socket.io connection;
- requestHandlerToListener, a helper to convert XHR request handler into SocketEventListener;
- storeToListeners, a helper to convert all Store request handlers into SocketEventListener.
With three simple steps you can test your real-time application that uses socket.io:
- create a mock server that intercepts socket.io;
- mock server behavior;
- test your application.
var fixtureSocket = require("can-fixture-socket");
// Import socket-io client:
var io = require("socket.io-client");
// Create a mock server that intercepts socket.io:
var mockServer = new fixtureSocket.Server(io);
// Mock server behavior
mockServer.on("connection", function(){
mockServer.emit("notifications", {test: "OK"})
});
// Client. Create socket.io connection:
var socket = io("http://localhost:8080/api");
// Test your application:
socket.on("connect", function(){
assert.ok(true, "socket connected");
});
socket.on("notifications", function(data){
assert.deepEqual(data, {test: "OK"}, "received notifications message");
});
Use basics
Lets say we wanted to test a simple app that connects to socket.io
, and
once connected, creates a message, and logs when the message is created.
That app could look like the following:
var socket = io();
socket.on("connect", function(){
socket.emit("messages create", {text: "A new message"});
});
socket.on("message created", function(data){
// data.text === "A new message"
console.log("Server sent out a new message we just created", data);
});
To test this, we'll first use can-fixture-socket.Server to intercept the socket connection:
var io = require("socket.io-client");
var fixtureSocket = require("can-fixture-socket");
var mockServer = new fixtureSocket.Server(io);
Now we can mock the socket server by creating socket event listeners and emitting socket events:
mockServer.on("messages create", function(data){
console.log("New message received", data);
mockServer.emit("message created", data);
});
To see this in action:
Acknowledgement callbacks
We also can use socket.io acknowledgement callbacks:
mockServer.on("users create", function(user, ackCb){
console.log("Simulating saving a new user to DB and return the new user id", user);
ackCB({
id: Math.random()
});
});
Client code:
var socket = io();
socket.on("connect", function(){
socket.emit("users create", {name: "Ilya", likes: "skiing"}, function (data) {
// data is what server calls the acknowledgement callback
// with (e.g. data.id is the new user id).
console.log(data.id);
});
});
Use with can-fixture.Store
With can-fixture store we can create a store of items and emulate a fully working CRUD service. Optionally, we can use Algebra to power our store filtering, pagination, and sorting abilities.
// Import can-fixture that provides `store` method for creating a store:
var fixture = require("can-fixture");
var canSet = require("can-set");
// Create a fixture store:
var messagesStore = fixture.store([
{id: 1, title: "One"},
{id: 2, title: "Two"},
{id: 3, title: "Three"}
], new canSet.Algebra({}));
We can mock the socket.io connection with the rich behavior of fixture stores using the requestHandlerToListener helper. requestHandlerToListener
converts a fixture store request handler to a socket.io event listener.
var fixtureSocket = require("can-fixture-socket");
var io = require("socket.io-client");
var mockServer = new fixtureSocket.Server(io);
mockServer.on("messages get", fixtureSocket.requestHandlerToListener( messagesStore.getData ));
Or we can use storeToListeners helper to convert all CRUD fixture store request handlers into socket.io event listeners:
var listeners = fixtureSocket.storeToListeners( messagesStore );
mockServer.on({
"messages remove": listeners.destroyData,
"messages create": listeners.createData,
"messages update": listeners.updateData
});
Use with FeathersJS
Feathers is a minimalist, service-oriented, real-time web framework for modern applications. It is a NodeJS framework built on top of Express. It allows you to build REST-ful services and works with three providers: standard HTTP communication, WebSockets and Primus.
The mocked server exposes [can-fixture-socket.Server.prototype.onFeathers] method to simulate FeathersJS CRUD services.
For example, given the following FeathersJS client app:
var socket = io("http://api.my-feathers-server.com");
var app = feathers()
.configure(hooks())
.configure(feathersSocketio(socket));
// Create FeathersJS CRUD service for "messages" resource:
var messagesService = app.service("messages");
We can simulate it with a store as follows:
var messagesStore = fixture.store([
{id: 1, title: "One"},
{id: 2, title: "Two"},
{id: 3, title: "Three"}
], new canSet.Algebra({}));
mockServer.onFeathersService("messages", fixtureStore);
Now you can test your FeathersJS app:
messagesService.find({}).then(function(data){
assert.equal(data.total, 3, "find should receive 3 items");
});
messagesService.get(1).then(function(data){
assert.deepEqual(data, {id: 1, title: "One"}, "get should receive an item");
});
messagesService.create({title: "Four"}).then(function(data){
assert.equal(data.title, "Four", "create should add an new item");
});