nikolalsvk/pusher-js-mock

View on GitHub
src/__tests__/pusher-js-mock.spec.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { PusherMock } from "../index";
import PusherChannelMock from "../pusher-channel-mock";
import PusherPresenceChannelMock from "../pusher-presence-channel-mock";
import { createClient } from "./pusher-presence-channel-mock.spec";
import PusherMockInstance from "../pusher-js-mock-instance";

describe("PusherMock", () => {
  let pusherMock: PusherMock;

  beforeEach(() => {
    PusherMockInstance.reset();
    pusherMock = new PusherMock();
  });

  it("initializes channels object", () => {
    expect(pusherMock.channels).toEqual({});
  });

  describe("#channel", () => {
    it("returns instance of PusherChannelMock", () => {
      expect(pusherMock.channel("my-channel")).toBeDefined();
    });

    it("adds new channel to channels object", () => {
      pusherMock.channel("my-channel");
      expect(pusherMock.channels).toMatchObject({ "my-channel": {} });
    });

    it("returns the correct type of channel based on channel name", () => {
      expect(pusherMock.channel("public-channel")).toBeInstanceOf(
        PusherChannelMock
      );
      expect(pusherMock.channel("presence-channel")).toBeInstanceOf(
        PusherPresenceChannelMock
      );

      pusherMock.unsubscribe("public-channel");
      pusherMock.unsubscribe("presence-channel");
    });

    describe("channel is already added to channels object", () => {
      beforeEach(() => {
        pusherMock.channel("my-channel");
      });

      it("returns instance of PusherChannelMock", () => {
        expect(pusherMock.channel("my-channel")).toBeDefined();
      });

      it("adds new channel to channels object", () => {
        expect(pusherMock.channels).toMatchObject({ "my-channel": {} });
      });
    });
  });

  describe("#allChannels", () => {
    beforeEach(() => {
      pusherMock.channel("public-channel");
      pusherMock.channel("presence-channel");
    });

    it("returns an array of channel mock instances", () => {
      const allChannels = pusherMock.allChannels();

      expect(allChannels).toHaveLength(2);
      expect(allChannels[0]).toBeInstanceOf(PusherChannelMock);
      expect(allChannels[1]).toBeInstanceOf(PusherPresenceChannelMock);
    });
  });

  describe("#connection", () => {
    it("returns instance of connection", () => {
      expect(pusherMock.connection).toBeDefined();
    });

    it("binds events to connection", () => {
      const listener = jest.fn();
      pusherMock.connection.bind("test-event", listener);

      pusherMock.connection.emit("test-event");

      expect(listener).toHaveBeenCalledTimes(1);
    });
  });

  describe("#bind", () => {
    it("binds event to all channels", () => {
      const listener = jest.fn();
      const myChannel = pusherMock.channel("my-channel");
      const myOtherChannel = pusherMock.channel("my-other-channel");
      const myThirdChannel = pusherMock.channel("my-third-channel");

      pusherMock.bind("test-event", listener);

      myChannel.emit("test-event");
      expect(listener).toHaveBeenCalledTimes(1);

      myOtherChannel.emit("test-event");
      expect(listener).toHaveBeenCalledTimes(2);

      myThirdChannel.emit("test-event");
      expect(listener).toHaveBeenCalledTimes(3);
    });
  });

  describe("#unbind", () => {
    it("removes name: callback from callbacks object", () => {
      const callback = () => {};

      const myChannel = pusherMock.channel("my-channel");
      const myOtherChannel = pusherMock.channel("my-other-channel");
      const myThirdChannel = pusherMock.channel("my-third-channel");

      pusherMock.bind("test-event", callback);
      expect(myChannel.callbacks).toEqual({
        "test-event": [callback]
      });
      expect(myOtherChannel.callbacks).toEqual({
        "test-event": [callback]
      });
      expect(myThirdChannel.callbacks).toEqual({
        "test-event": [callback]
      });

      pusherMock.unbind("test-event", callback);

      expect(myChannel.callbacks).toEqual({
        "test-event": []
      });
      expect(myOtherChannel.callbacks).toEqual({
        "test-event": []
      });
      expect(myThirdChannel.callbacks).toEqual({
        "test-event": []
      });
    });
  });

  describe("#subscribe", () => {
    it("returns instance of PusherChannelMock", () => {
      expect(pusherMock.channel("my-channel")).toBeDefined();
    });

    it("adds new channel to channels object", () => {
      pusherMock.subscribe("my-channel");
      expect(pusherMock.channels).toMatchObject({ "my-channel": {} });
    });

    it("subscribes to a presence channel", () => {
      pusherMock.subscribe("presence-channel");

      expect(pusherMock.channels).toMatchObject({ "presence-channel": {} });
    });
  });

  describe("#unsubscribe", () => {
    describe("channel name is inside channels object", () => {
      it("removes channel from channels object", () => {
        pusherMock.subscribe("my-channel");
        pusherMock.unsubscribe("my-channel");
        expect(pusherMock.channels).toEqual({});
      });
    });

    describe("channel name is not inside channels object", () => {
      it("removes channel from channels object", () => {
        pusherMock.unsubscribe("my-channel");
        expect(pusherMock.channels).toEqual({});
      });
    });

    describe("presence channels", () => {
      it("removes only own callbacks from the callbacks object", async () => {
        // arrange
        const client = new PusherMock("my-id");
        const otherClient = createClient("your-id", {});

        const channel = client.subscribe("presence-channel");
        const otherChannel = otherClient.subscribe("presence-channel");

        const listener = jest.fn();
        const otherListener = jest.fn();

        // act
        channel.bind("some-event", listener);
        otherChannel.bind("some-event", otherListener);

        otherClient.unsubscribe("presence-channel");
        PusherMockInstance.channels["presence-channel"].emit("some-event", {
          data: "testing"
        });

        // assert
        expect(listener).toHaveBeenCalledWith({ data: "testing" });
        expect(otherListener).not.toHaveBeenCalled();
        expect(
          PusherMockInstance.channels["presence-channel"].callbacks
        ).toEqual({ "some-event": [listener] });

        // expect channel removed
        client.unsubscribe("presence-channel");
        expect(PusherMockInstance.channels).toEqual({});
      });
    });
  });

  describe("authorizer", () => {
    it("should set a default ID and info if presence channel used and no auth config passed", () => {
      pusherMock.subscribe("presence-channel");
      expect(pusherMock.id).toBeDefined();
      expect(pusherMock.info).toBeDefined();
    });

    it("should leave id and info undefined if auth errored", () => {
      pusherMock.config = {
        authorizer: () => ({
          authorize: (socketId, callback) => {
            callback(true, undefined as any);
          }
        })
      };

      pusherMock.subscribe("presence-channel");

      expect(pusherMock.id).toBeUndefined();
      expect(pusherMock.info).toBeUndefined();
    });
  });
});