Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
jest-websocket-mock
Advanced tools
Mock websockets and assert complex websocket interactions with Jest
The jest-websocket-mock package is a testing utility for mocking WebSocket connections in Jest tests. It allows developers to simulate WebSocket servers and clients, making it easier to test real-time applications without needing a live WebSocket server.
Mock WebSocket Server
This feature allows you to create a mock WebSocket server that can be used in your tests. The server can be started and stopped as needed.
const WS = require('jest-websocket-mock');
const server = new WS('ws://localhost:1234');
// Your test code here
server.close();
Mock WebSocket Client
This feature allows you to create a mock WebSocket client that can connect to the mock server. This is useful for testing client-side WebSocket logic.
const WS = require('jest-websocket-mock');
const server = new WS('ws://localhost:1234');
const client = new WebSocket('ws://localhost:1234');
client.onopen = () => {
console.log('Client connected');
};
server.on('connection', socket => {
console.log('Server received connection');
});
Simulate Server Messages
This feature allows the mock server to send messages to the client, simulating real server-client communication. This is useful for testing how the client handles incoming messages.
const WS = require('jest-websocket-mock');
const server = new WS('ws://localhost:1234');
const client = new WebSocket('ws://localhost:1234');
client.onmessage = event => {
console.log('Client received message:', event.data);
};
server.send('Hello, client!');
Simulate Client Messages
This feature allows the mock client to send messages to the server, simulating real client-server communication. This is useful for testing how the server handles incoming messages.
const WS = require('jest-websocket-mock');
const server = new WS('ws://localhost:1234');
const client = new WebSocket('ws://localhost:1234');
server.on('message', message => {
console.log('Server received message:', message);
});
client.onopen = () => {
client.send('Hello, server!');
};
The mock-socket package provides a way to mock WebSocket and WebSocketServer objects for testing purposes. It is similar to jest-websocket-mock but can be used with any testing framework, not just Jest.
The ws package is a WebSocket implementation for Node.js. While it is not specifically designed for mocking, it can be used to create WebSocket servers and clients for testing purposes. It requires more setup compared to jest-websocket-mock.
The socket.io-mock package is designed for mocking Socket.IO connections in tests. It is similar to jest-websocket-mock but is specifically for applications using the Socket.IO library.
A set of utilities and Jest matchers to help testing complex websocket interactions.
Examples: Several examples are provided in the examples folder. In particular:
npm install --save-dev jest-websocket-mock
WS
constructorjest-websocket-mock
exposes a WS
class that can instantiate mock websocket
servers that keep track of the messages they receive, and in turn
can send messages to connected clients.
import WS from "jest-websocket-mock";
// create a WS instance, listening on port 1234 on localhost
const server = new WS("ws://localhost:1234");
// real clients can connect
const client = new WebSocket("ws://localhost:1234");
await server.connected; // wait for the server to have established the connection
// the mock websocket server will record all the messages it receives
client.send("hello");
// the mock websocket server can also send messages to all connected clients
server.send("hello everyone");
// ...simulate an error and close the connection
server.error();
// ...or gracefully close the connection
server.close();
// The WS class also has a static "clean" method to gracefully close all open connections,
// particularly useful to reset the environment between test runs.
WS.clean();
The WS
constructor also accepts an optional options object as second argument:
jsonProtocol: true
can be used to automatically serialize and deserialize JSON messages:const server = new WS("ws://localhost:1234", { jsonProtocol: true });
server.send({ type: "GREETING", payload: "hello" });
mock-server
options verifyClient
and selectProtocol
are directly passed-through to the mock-server's constructor.WS
instanceA WS
instance has the following attributes:
connected
: a Promise that resolves every time the WS
instance receives a
new connection. The resolved value is the WebSocket
instance that initiated
the connection.closed
: a Promise that resolves every time a connection to a WS
instance
is closed.nextMessage
: a Promise that resolves every time a WS
instance receives a
new message. The resolved value is the received message (deserialized as a
JavaScript Object if the WS
was instantiated with the { jsonProtocol: true }
option).WS
instancesend
: send a message to all connected clients. (The message will be
serialized from a JavaScript Object to a JSON string if the WS
was
instantiated with the { jsonProtocol: true }
option).close
: gracefully closes all opened connections.error
: sends an error message to all connected clients and closes all
opened connections.on
: attach event listeners to handle new connection
, message
and close
events. The callback receives the socket
as its only argument.jest-websocket-mock
registers custom jest matchers to make assertions
on received messages easier:
.toReceiveMessage
: async matcher that waits for the next message received
by the the mock websocket server, and asserts its content. It will time out
with a helpful message after 1000ms..toHaveReceivedMessages
: synchronous matcher that checks that all the
expected messages have been received by the mock websocket server.test("the server keeps track of received messages, and yields them as they come in", async () => {
const server = new WS("ws://localhost:1234");
const client = new WebSocket("ws://localhost:1234");
await server.connected;
client.send("hello");
await expect(server).toReceiveMessage("hello");
expect(server).toHaveReceivedMessages(["hello"]);
});
test("the mock server sends messages to connected clients", async () => {
const server = new WS("ws://localhost:1234");
const client1 = new WebSocket("ws://localhost:1234");
await server.connected;
const client2 = new WebSocket("ws://localhost:1234");
await server.connected;
const messages = { client1: [], client2: [] };
client1.onmessage = (e) => {
messages.client1.push(e.data);
};
client2.onmessage = (e) => {
messages.client2.push(e.data);
};
server.send("hello everyone");
expect(messages).toEqual({
client1: ["hello everyone"],
client2: ["hello everyone"],
});
});
jest-websocket-mock
can also automatically serialize and deserialize
JSON messages:
test("the mock server seamlessly handles JSON protocols", async () => {
const server = new WS("ws://localhost:1234", { jsonProtocol: true });
const client = new WebSocket("ws://localhost:1234");
await server.connected;
client.send(`{ "type": "GREETING", "payload": "hello" }`);
await expect(server).toReceiveMessage({ type: "GREETING", payload: "hello" });
expect(server).toHaveReceivedMessages([
{ type: "GREETING", payload: "hello" },
]);
let message = null;
client.onmessage = (e) => {
message = e.data;
};
server.send({ type: "CHITCHAT", payload: "Nice weather today" });
expect(message).toEqual(`{"type":"CHITCHAT","payload":"Nice weather today"}`);
});
A verifyClient
function can be given in the options for the jest-websocket-mock
constructor.
This can be used to test behaviour for a client that connects to a WebSocket server it's blacklisted from for example.
Note : Currently mock-socket
's implementation does not send any parameters to this function (unlike the real ws
implementation).
test("rejects connections that fail the verifyClient option", async () => {
new WS("ws://localhost:1234", { verifyClient: () => false });
const errorCallback = jest.fn();
await expect(
new Promise((resolve, reject) => {
errorCallback.mockImplementation(reject);
const client = new WebSocket("ws://localhost:1234");
client.onerror = errorCallback;
client.onopen = resolve;
})
// WebSocket onerror event gets called with an event of type error and not an error
).rejects.toEqual(expect.objectContaining({ type: "error" }));
});
A selectProtocol
function can be given in the options for the jest-websocket-mock
constructor.
This can be used to test behaviour for a client that connects to a WebSocket server using the wrong protocol.
test("rejects connections that fail the selectProtocol option", async () => {
const selectProtocol = () => null;
new WS("ws://localhost:1234", { selectProtocol });
const errorCallback = jest.fn();
await expect(
new Promise((resolve, reject) => {
errorCallback.mockImplementationOnce(reject);
const client = new WebSocket("ws://localhost:1234", "foo");
client.onerror = errorCallback;
client.onopen = resolve;
})
).rejects.toEqual(
// WebSocket onerror event gets called with an event of type error and not an error
expect.objectContaining({
type: "error",
currentTarget: expect.objectContaining({ protocol: "foo" }),
})
);
});
test("the mock server sends errors to connected clients", async () => {
const server = new WS("ws://localhost:1234");
const client = new WebSocket("ws://localhost:1234");
await server.connected;
let disconnected = false;
let error = null;
client.onclose = () => {
disconnected = true;
};
client.onerror = (e) => {
error = e;
};
server.send("hello everyone");
server.error();
expect(disconnected).toBe(true);
expect(error.origin).toBe("ws://localhost:1234/");
expect(error.type).toBe("error");
});
it("the server can refuse connections", async () => {
const server = new WS("ws://localhost:1234");
server.on("connection", (socket) => {
socket.close({ wasClean: false, code: 1003, reason: "NOPE" });
});
const client = new WebSocket("ws://localhost:1234");
client.onclose = (event: CloseEvent) => {
expect(event.code).toBe(1003);
expect(event.wasClean).toBe(false);
expect(event.reason).toBe("NOPE");
};
expect(client.readyState).toBe(WebSocket.CONNECTING);
await server.connected;
expect(client.readyState).toBe(WebSocket.CLOSING);
await server.closed;
expect(client.readyState).toBe(WebSocket.CLOSED);
});
You can set up a mock server and a client, and reset them between tests:
beforeEach(async () => {
server = new WS("ws://localhost:1234");
client = new WebSocket("ws://localhost:1234");
await server.connected;
});
afterEach(() => {
WS.clean();
});
mock-socket
has a strong usage of delays (setTimeout
to be more specific). This means using jest.useFakeTimers();
will cause issues such as the client appearing to never connect to the server.
While running the websocket server from tests within the jest-dom environment (as opposed to node) you may see errors of the nature:
ReferenceError: setImmediate is not defined
You can work around this by installing the setImmediate shim from
https://github.com/YuzuJS/setImmediate and
adding require('setimmediate');
to your setupTests.js
.
When testing React applications, jest-websocket-mock
will look for
@testing-library/react
's implementation of act
.
If it is available, it will wrap all the necessary calls in act
, so you don't have to.
If @testing-library/react
is not available, we will assume that you're not testing a React application,
and you might need to call act
manually.
jest-websocket-mock
to interact with a non-global WebSocket objectjest-websocket-mock
uses Mock Socket
under the hood to mock out WebSocket clients.
Out of the box, Mock Socket will only mock out the global WebSocket
object.
If you are using a third-party WebSocket client library (eg. a Node.js
implementation, like ws
), you'll need
to set up a manual mock:
__mocks__
folder in your project root__mocks__
folder named after the library you want to
mock out. For instance, for the ws
library: __mocks__/ws.js
.ws
library:// __mocks__/ws.js
export { WebSocket as default } from "mock-socket";
NOTE The ws
library is not 100% compatible with the browser API, and
the mock-socket
library that jest-websocket-mock
uses under the hood only
implements the browser API.
As a result, jest-websocket-mock
will only work with the ws
library if you
restrict yourself to the browser APIs!
For a real life example, see the examples directory, and in particular the saga tests.
See the contributing guide.
FAQs
Mock websockets and assert complex websocket interactions with Jest
The npm package jest-websocket-mock receives a total of 109,575 weekly downloads. As such, jest-websocket-mock popularity was classified as popular.
We found that jest-websocket-mock demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.