Kappa
Kappa

Reputation: 303

Skip implementation in Jest

Currently I have the following piece of code:

function handleConnection(socket: Socket): void {
  info(`Connection started with socketId: ${socket.id}`)

  socket.on("joinRoom", (request: string) => handleJoinRoom(socket, request));

  socket.on("shareData", (request: IShareDataRequest) => handleShareData(socket, request));

  socket.on("disconnect", () => handleDisconnect(socket));
}

I want to write a test for each and every events like joinRoom, shareData and disconnect. To isolae the tests I want to only test the second socket.on("shareData", () => ...) call and skip the first socket.on("joinRoom", () => ...) call. I've tried with multiple mockImplementationOnce methods with no success.

The test I wrote:

it('should emit data to room', () => {
    const listenMock = listen();
    const socketMock = {
      on: jest.fn()
        .mockImplementationOnce(() => null)
        .mockImplementationOnce((event: string, callback: Function) => callback({ roomId: "abcdefg" })),
      to: jest.fn().mockReturnValue({
        emit: jest.fn()
      })
    }
    jest.spyOn(listenMock, "on").mockImplementationOnce((event: string, callback: Function) => callback(socketMock))

    startSocket();

    expect(socketMock.to).toHaveBeenCalledWith("abcdefg");
    expect(socketMock.to().emit).toHaveBeenCalledWith("receiveData", expect.any(Object));
  })

ShareData function:

function handleShareData(socket: Socket, request: IShareDataRequest): void {
  socket.to(request.roomId).emit("receiveData", request);
}

I would really appreciate if anyone could help me out with this.

Upvotes: 0

Views: 1352

Answers (1)

Teneff
Teneff

Reputation: 32158

You can try the following approach:

// define the mockSocket
const mockSocket = {
  // without any implementation
  on: jest.fn()
};

describe("connection handler", () => {
  // I personally like separating the test setup
  // in beforeAll blocks 
  beforeAll(() => {
    handleConnection(mockSocket);
  });

  // you can write assertions that .on
  // should have been called for each event
  // with a callback
  describe.each(["joinRoom", "shareData", "disconnect"])(
    "for event %s",
    event => {
      it("should attach joinRoom handlers", () => {
        expect(mockSocket.on.mock.calls).toEqual(
          expect.arrayContaining([[event, expect.any(Function)]])
        );
      });
    }
  );

  describe("joinRoom handler", () => {
    beforeAll(() => {
      // jest mock functions keep the calls internally
      // and you can use them to find the call with 
      // the event that you need and retrieve the callback
      const [_, joinRoomHandler] = mockSocket.on.mock.calls.find(
        ([eventName]) => eventName === "joinRoom"
      );

      // and then call it
      joinRoomHandler("mockRequestString");
    });

    it("should handle the event properly", () => {
      // your joinRoom handler assertions would go here
    });
  });
});

Upvotes: 1

Related Questions