UNPKG

pusher-js-mock

Version:

Mock Pusher.js in your JavaScript tests with ease

310 lines (231 loc) 9.62 kB
<p align="center"> <img src='https://raw.githubusercontent.com/nikolalsvk/pusher-js-mock/master/logo.jpg' alt="pusher-js-mock logo" /> <h1 align="center">👋 Welcome to pusher-js-mock</h1> <p align="center"> <a href="https://badge.fury.io/js/pusher-js-mock" target="_blank"><img src="https://badge.fury.io/js/pusher-js-mock.svg" alt="npm version" /></a> <a href="https://github.com/nikolalsvk/pusher-js-mock/actions"><img alt="GitHub branch check runs" src="https://img.shields.io/github/check-runs/nikolalsvk/pusher-js-mock/master"></a> <a href="https://qlty.sh/gh/nikolalsvk/projects/pusher-js-mock"><img src="https://qlty.sh/badges/fafa3af3-7f17-4052-b73c-d442fd71d634/maintainability.svg" alt="Maintainability" /></a> <a href="https://qlty.sh/gh/nikolalsvk/projects/pusher-js-mock"><img src="https://qlty.sh/badges/fafa3af3-7f17-4052-b73c-d442fd71d634/test_coverage.svg" alt="Test Coverage"></a> <a href="https://www.codetriage.com/nikolalsvk/pusher-js-mock" target="_blank"><img src="https://www.codetriage.com/nikolalsvk/pusher-js-mock/badges/users.svg" alt="Open Source Helpers" /></a> </p> <p align="center"> Mock <a href="https://github.com/pusher/pusher-js">Pusher.js</a> in your JavaScript tests with ease. </p> </p> ## Installing Using yarn: ``` yarn add --dev pusher-js-mock ``` Or using npm: ``` npm install -D pusher-js-mock ``` ## Usage 🛠 - [Emitting an event 📶](#emitting-an-event-) - [Listening for an event 👂](#listening-for-an-event-) - [Emitting an event from connection 📶](#emitting-an-event-from-connection-) - [Listening for an event from connection 👂](#listening-for-an-event-from-connection-) - [Stubbing Pusher when imported from pusher-js package 📦](#stubbing-pusher-when-imported-from-pusher-js-package-) - [Stubbing Pusher when used as a global variable 🌍](#stubbing-pusher-when-used-as-a-global-variable-) - [Mocking presence channels](#mocking-presence-channels) - [Using custom authorizer](#using-custom-authorizer) - [Pusher events emitted by presence channels](#pusher-events-emitted-by-presence-channels) - [Using with Vitest](#using-with-vitest) For more detailed examples, check out [`examples` directory](https://github.com/nikolalsvk/pusher-js-mock/tree/master/examples) inside the project! Also, you can check out the [Docs](https://nikolalsvk.github.io/pusher-js-mock/) for even more information. ### Emitting an event 📶 If you need to mock a Pusher object in your tests that can subscribe to channel, it's best to use PusherMock. ```javascript import { PusherMock } from "pusher-js-mock"; // initializing PusherMock const pusher = new PusherMock(); // subscribing to a Pusher channel const channel = pusher.subscribe("my-channel"); // emitting an event channel.emit("event-name"); ``` ### Listening for an event 👂 If you want to check whether your callback is getting called properly, you can bind a callback to your channel, and then emit an event. ```javascript import { PusherMock } from "pusher-js-mock"; describe("listening for an event", () => { // initializing PusherMock const pusher = new PusherMock(); // subscribing to a Pusher channel const channel = pusher.subscribe("my-channel"); // define and attach a listener const listener = jest.fn(); channel.bind("event-name", listener); // emitting an event channel.emit("event-name"); // Expect listener to have been called expect(listener).toHaveBeenCalled(); }); ``` ### Emitting an event from connection 📶 The connection within pusher is mocked and can be used much like a channel channel. There's no need to subscribe to subscription as it's subscribed by default on pusher. ```javascript import { PusherMock } from "pusher-js-mock"; // initializing PusherMock const pusher = new PusherMock(); // emitting connection event pusher.connection.emit("event-name"); ``` ### Listening for an event from connection 👂 As with channels, you can also listen to connection for events. ```javascript import { PusherMock } from "pusher-js-mock"; describe("listening for an event", () => { // initializing PusherMock const pusher = new PusherMock(); // define and attach a listener const listener = jest.fn(); pusher.connection.bind("event-name", listener); // emitting an event pusher.connection.emit("event-name"); // Expect listener to have been called expect(listener).toHaveBeenCalled(); }); ``` ### Stubbing Pusher when imported from pusher-js package 📦 If you're using Pusher in your code in this or similar manner: ```javascript import Pusher from "pusher-js"; ``` You will need to mock Pusher in a specific way. I suggest you use [Jest](https://jestjs.io/) to test your code. To do this in Jest, you'll need something like this: ```javascript jest.mock("pusher-js", () => { const Pusher = require("pusher-js-mock").PusherMock; return Pusher; }); ``` If you have tips on how to mock this using other testing frameworks, please submit an issue or a pull request. ### Stubbing Pusher when used as a global variable 🌍 This shows how to stub a pusher if you're attaching it to window object in your project. If you're attaching a PusherFactory to a `window` object like this in your code: ```javascript window.PusherFactory = { pusherClient: function(pusherKey) { return new Pusher(pusherKey); } }; ``` It's best for you to use PusherFactoryMock. ```javascript import { PusherFactoryMock } from "pusher-js-mock"; // initialize instance of PusherFactoryMock const pusherFactoryMock = new PusherFactoryMock(); // replace it with the object that is attached to a window window.PusherFactory = pusherFactoryMock; // get the Pusher client reference pusher = pusherFactoryMock.pusherClient(); ``` This way you'll just replace your PusherFactory with PusherFactoryMock. ### Mocking presence channels This package also supports using presence channels for multiple clients. The mock will automatically detect when `presence-` is in the channel name and return a presence channel with `channel.members` filled out as expected. You can pass in IDs and info via a custom authorizer, just as you would with the real package. #### Using custom authorizer If you want, you can pass in a custom authorizer when creating a Pusher client. ```js // create-client.js import Pusher from "pusher-js"; import { getAuthSomehow } from "./getAuthSomehow"; export const createClient = ({ id, info }) => new Pusher("APP_KEY", { cluster: "APP_CLUSTER", // see https://github.com/pusher/pusher-js#authorizer-function authorizer: ({ name }) => ({ authorize: (socketId, callback) => { const auth = getAuthSomehow(id, info); callback(false, auth); } }) }); export default createClient; ``` ```js // create-client.spec.js import createClient from "../create-client"; // mock the authorize function and pusher jest.mock("pusher-js", () => require("pusher-js-mock")); jest.mock("../getAuthSomehow", () => ({ getAuthSomehow: (id, info) => ({ id, info }) })); it("should create a presence channel", async () => { // arrange: create pusher client const pusher = createClient({ id: "my-id", info: { role: "moderator" } }); // act: required to ensure pusher events are called, i.e. pusher:member_added const presenceChannel = await pusher.subscribe("presence-channel"); // assert: presenceChannel has the properties we expect it to. expect(presenceChannel.members.myID).toBe("my-id"); expect(presenceChannel.members.me).toEqual({ id: "my-id", info: { role: "moderator" } }); expect(presenceChannel.members.members).toEqual({ "my-id": { role: "moderator" } }); }); ``` [Check out a code example of using presence channels](https://github.com/nikolalsvk/pusher-js-mock/tree/master/examples/presence-channels) #### Pusher events emitted by presence channels The mocked Pusher instance will also emit pusher internal events `pusher:subscription_succeeded`, `pusher:member_added` and `pusher:member_removed` to the relevant clients: ```js it("should emit presence-channel events", async () => { const client = createClient({ id: "my-id" }); const channel = client.subscribe("presence-channel"); const listener = jest.fn(); /** * On bind, pusher:subscription_succeded will trigger * for the client subscribing. Other clients will be * notified via pusher:member_added as below. */ await channel.bind("pusher:subscription_succeeded", listener); expect(listener).toHaveBeenCalledTimes(1); /** * Create and subscribe a new client that will trigger the * pusher:member_added event. This only gets triggered for * clients are not the client subscribing */ channel.bind("pusher:member_added", listener); const otherClient = createClient({ id: "your-id" }); await otherClient.subscribe("presence-channel"); expect(listener).toHaveBeenCalledTimes(2); /** * Unsubscribe the otherClient to trigger pusher:member_removed. * This only gets triggered for clients that are not the client * unsubscribing. */ channel.bind("pusher:member_removed", listener); await otherClient.unsubscribe("presence-channel"); expect(listener).toHaveBeenCalledTimes(3); }); ``` ### Using with Vitest You can mock Pusher.js in Vitest environment like this: ```js vi.mock("pusher-js", () => { return { __esModule: true, default: require("pusher-js-mock").PusherMock }; }); ``` ### [Code of Conduct](CODE_OF_CODUCT.md) ### [Contributing](CONTRIBUTING.md) ### Credits Photo by [Octavian Rosca on Unsplash](https://unsplash.com/@tavi004)