Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation does not specify how to set up room broadcasts #15

Open
codejedi365 opened this issue Feb 21, 2021 · 0 comments
Open

Documentation does not specify how to set up room broadcasts #15

codejedi365 opened this issue Feb 21, 2021 · 0 comments

Comments

@codejedi365
Copy link

I found that the documentation lacked specificity on how to set up room based broadcasts with the MockedServerSocket implementation. Digging through the code of socket.io-mock plus trial and error allowed me to come up with this code below to officially send information back and forth for testing my ReactApp. The undocumented trick is the need to set up an onEmit() function for that specific event type which will serialize the data and check for room subscription outside of configuring the actual event emit handler.

Disclaimer: If this is exactly how to setup regular socket.io for the server in JS/TS, then I'm unfamiliar since our project has a python based backend implementation of server side socket.io and also I'm not the backend developer.

My solution

This tests a ReactApp that implements socket.io-client

// FILE: ./src/__tests__/App.test.tsx
import React from "react"
import App from "../App"
import { render, cleanup, act, RenderResult, waitFor, prettyDOM } from "@testing-library/react"
import { io } from "socket.io-client"
import MockedServerSocket from "socket.io-mock"
// See Issue #14 for details on type implementation
import { SocketMock, SocketClient } from "../typescript-declarations/socketio-mock"

jest.mock("socket.io-client")
const mockIO = (io as unknown) as jest.MockedFunction<() => SocketClient>

// Generic function to configure MockServerSocket before an event is emitted from the server
// Also handles room subscription verification
function prepareServerSocket2EmitEvent(this: SocketMock, eventType: string): SocketMock {
  this.onEmit(eventType, (payload?: unknown, roomKey?: string) => {
    if (this.joinedRooms.includes(roomKey || "")) {
      this.emit(eventType, JSON.stringify(payload))
    }
  })
  return this
}

describe("<App />", () => {
  let fakeServerSocket: SocketMock
  let fakeSocketClient: SocketClient

  beforeEach(() => {
    fakeServerSocket = new MockedServerSocket()
    fakeSocketClient = fakeServerSocket.socketClient

    // Since fakeServerSocket does not automatically emit a connect message as socketio io() does, simulate it here.
    fakeServerSocket.on("connect", (obj: unknown) => {
      fakeServerSocket.emit("connect", { status: "success" })
    })

    // My server API event method of joining rooms
    fakeServerSocket.on("subscribe", (url: unknown) => {
      if (typeof url === "string") {
        fakeServerSocket.join(url)
      }
    })

    // Since fakeSocketClient does not automatically send connect event as a call
    // to socket.io-client's io() does automatically, emulate it here
    mockIO.mockImplementation(() => {
      fakeSocketClient.emit("connect")
      return fakeSocketClient
    })
  })

  afterEach(async () => {
    await cleanup()
    jest.clearAllMocks()
  })

  describe("socket.io", () => {
    it("should dispatch a event when user is subscribed", async () => {
      const eventType = "new"
      let renderResult: RenderResult<typeof import("@testing-library/dom/types/queries")> | null = null

      await act(async () => {
        // App will autoconnect, subscribe to /myroom, & define handler for eventType which updates component
        renderResult = render(<App />)
      })
      prepareServerSocket2EmitEvent.call(fakeServerSocket, eventType)
      await act(async () => {
        fakeServerSocket.broadcast.to("/myroom").emit(eventType, { class: "custom" })
      })
      await waitFor(() => {
        // Wait for App to react to received event data object
        expect(prettyDOM(renderResult?.container)).toMatchSnapshot()
      })
    })
  })
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant