nikolalsvk/pusher-js-mock

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

Summary

Maintainability
A
0 mins
Test Coverage
import { PusherMock, PusherPresenceChannelMock } from "../";

describe("PusherPresenceChannelMock", () => {
  let channelMock: PusherPresenceChannelMock;

  beforeEach(() => {
    channelMock = new PusherPresenceChannelMock();
  });

  it("sets a name (with a default fallback)", () => {
    expect(channelMock.name).toBe("presence-channel");
    const namedChannelMock = new PusherPresenceChannelMock(
      "presence-custom-name"
    );
    expect(namedChannelMock.name).toBe("presence-custom-name");
  });

  it("initializes members object", () => {
    expect(channelMock.members).toEqual({
      count: 0,
      members: {},
      me: null,
      myID: null
    });
  });
});

/**
 * Creates a mocked client for testing
 * @param id The ID to attach to the client
 * @param info The user info object
 */
export const createClient = (id: string, info: any = {}) =>
  new PusherMock("key", {
    authorizer: () => ({
      authorize: (_socketId, callback) => {
        callback(false, { id, info });
      }
    })
  });

describe("Proxied PusherPresenceChannelMock", () => {
  let client: PusherMock;
  let otherClient: PusherMock;
  let proxiedChannelMock: PusherPresenceChannelMock;
  let otherProxiedChannelMock: PusherPresenceChannelMock;

  const PRESENCE_CHANNEL = "presence-channel";

  beforeEach(() => {
    client = createClient("my-id", {});
    otherClient = createClient("your-id", {});

    proxiedChannelMock = client.subscribe(PRESENCE_CHANNEL);
    otherProxiedChannelMock = otherClient.subscribe(PRESENCE_CHANNEL);
  });

  it("doesn't proxy class members it doesn't care about", () => {
    expect(proxiedChannelMock.subscribed).toBe(true);
  });

  it("add new members to the channel", () => {
    expect(proxiedChannelMock.members.count).toBe(2);
    expect(proxiedChannelMock.members.get("my-id")).toEqual({
      id: "my-id",
      info: {}
    });
    expect(proxiedChannelMock.members.get("your-id")).toEqual({
      id: "your-id",
      info: {}
    });
  });

  it("correctly proxies the channel object per client", () => {
    expect(proxiedChannelMock.members.myID).toBe("my-id");
    expect(proxiedChannelMock.members.me).toEqual({ id: "my-id", info: {} });
    expect(proxiedChannelMock.IS_PROXY).toBeDefined();
  });

  it("allows multiple clients to subscribe", () => {
    expect(proxiedChannelMock.members.myID).toBe("my-id");
    expect(otherProxiedChannelMock.members.myID).toBe("your-id");

    expect(proxiedChannelMock.members.count).toBe(2);
  });

  it("should not emit a members callback when that member emits an event", () => {
    const listener = jest.fn();
    proxiedChannelMock.bind("custom-event", listener);

    const otherListener = jest.fn();
    otherProxiedChannelMock.bind("custom-event", otherListener);

    proxiedChannelMock.emit("custom-event");
    expect(listener).toHaveBeenCalledTimes(0);
    expect(otherListener).toHaveBeenCalledTimes(1);

    otherProxiedChannelMock.emit("custom-event");
    expect(listener).toHaveBeenCalledTimes(1);
    expect(otherListener).toHaveBeenCalledTimes(1);

    // cleanup
    proxiedChannelMock.unbind("custom-event", listener);
    otherProxiedChannelMock.unbind("custom-event", otherListener);
  });

  describe("#trigger", () => {
    it("is an alias for emit", () => {
      const callback = jest.fn();
      proxiedChannelMock.bind("event", callback);

      proxiedChannelMock.trigger("event");

      expect(callback).not.toHaveBeenCalled();
    });

    it("emits pusher:member_added manually", () => {
      client = new PusherMock();
      const proxiedChannel = client.subscribe("presence-some-id");

      const callback = jest.fn();
      proxiedChannel.bind("pusher:member_added", callback);

      proxiedChannel.trigger("pusher:member_added", { data: "testing" });

      expect(callback).not.toHaveBeenCalledWith({ data: "testing" });
    });
  });

  describe("Shared instance multiple clients", () => {
    it("should trigger events cross-client", () => {
      // binding to the same event
      const listener = jest.fn();
      proxiedChannelMock.bind("client-event", listener);
      const otherListener = jest.fn();
      otherProxiedChannelMock.bind("client-event", otherListener);

      // should receive the others events
      proxiedChannelMock.emit("client-event");
      expect(listener).toHaveBeenCalledTimes(0);
      expect(otherListener).toHaveBeenCalledTimes(1);

      otherProxiedChannelMock.emit("client-event");
      expect(listener).toHaveBeenCalledTimes(1);
      expect(otherListener).toHaveBeenCalledTimes(1);

      // should work the same way with trigger
      proxiedChannelMock.trigger("client-event");
      expect(listener).toHaveBeenCalledTimes(1);
      expect(otherListener).toHaveBeenCalledTimes(2);

      expect(proxiedChannelMock.members.myID).toBe("my-id");
      expect(otherProxiedChannelMock.members.myID).toBe("your-id");

      // cleanup
      client.unsubscribe("presence-channel");
      otherClient.unsubscribe("presence-channel");
    });
  });

  describe("#bind", () => {
    it("should not bind if client.id is undefined", () => {
      client.id = undefined;
      proxiedChannelMock.bind("never-bound-event", () => {});
      expect(proxiedChannelMock.callbacks["never-bound-event"]).toBeUndefined();
    });
  });

  describe("#subscribe", () => {
    it("should trigger internal events such as pusher:subscription_succeeded", async () => {
      const listener = jest.fn() as any;
      const client = createClient("my-id", {});
      const channel = client.subscribe("presence-channel");

      await channel.bind("pusher:subscription_succeeded", listener);

      expect(listener).toHaveBeenCalledTimes(1);

      channel.unbind("pusher:subscription_succeeded", listener);
    });

    it("should trigger external events such as pusher:member_added", async () => {
      const listener = jest.fn() as any;
      const client = createClient("my-id", {});
      const otherClient = createClient("your-id", {});
      const channel = client.subscribe("presence-channel");

      await channel.bind("pusher:member_added", listener);
      await otherClient.subscribe("presence-channel");

      expect(listener).toHaveBeenCalledTimes(1);
      channel.unbind("pusher:member_added", listener);
    });
  });

  describe("#unsubscribe", () => {
    it("should trigger external events such as pusher:member_removed", () => {
      const listener = jest.fn() as any;
      const client = createClient("my-id", {});
      const otherClient = createClient("your-id", {});
      const channel = client.subscribe("presence-channel");

      channel.bind("pusher:member_removed", listener);
      otherClient.subscribe("presence-channel");
      otherClient.unsubscribe("presence-channel");

      expect(listener).toHaveBeenCalledTimes(1);
      channel.unbind("pusher:member_removed", listener);
    });
  });
});