DEV Community

Aditya
Aditya

Posted on • Originally published at adityanaik.dev on

1 1

How to test your react websocket implementation using cypress

Set up demo application

I scaffold a standard react application

$ npx create-react-app ws-demo
Enter fullscreen mode Exit fullscreen mode

Clean up and update app.js to set up a websocket client.

import React, { useState } from 'react'

const App = () => {
  const [message, setMessage] = useState('websocket is closed')

  return (
    <div className="App">
      <p id="websocket">{message}</p>
      <WebsocketHandler setMessage={setMessage} />
    </div>
  )
}

export default App

// WebsocketHandler does what the name suggests - launch/close websocket client and receive messages

const websocketUrl = 'ws://127.0.0.1:5000'
const WebsocketHandler = ({ setMessage }) => {
  const ws = new WebSocket(websocketUrl)
  ws.onopen = () => {
    console.log('conn open')
    ws.send('connection is open')
  }
  ws.onmessage = (message) => {
    setMessage(message.data)
    console.log('onmessage triggered', message)
    ws.send('message received')
  }
  ws.onclose = () => {
    console.log('connection closed')
  }
  return null
}
Enter fullscreen mode Exit fullscreen mode

As you can see, I have a WebsocketHandler component which handles websocket and sets state in app.js when it receives the message.

Set up and scaffold Cypress

Cypress is a fantastic testing framework.
It is easy to set up and can be picked up pretty quickly.

Setting up Cypress is pretty straight forward - just run:

$ npm install cypress
or
$ yarn add cypress
Enter fullscreen mode Exit fullscreen mode

I will also install the recommended dependency

$ npm install -D start-server-and-test
Enter fullscreen mode Exit fullscreen mode

start-server-and-test is a cool tool that basically

Starts server, waits for URL, then runs test command; when the tests end, shuts down server

as explained on their github repo.

I install that package and use it in the package.json script -

"cy:test": "start-server-and-test start http://localhost:3001 cy:open"
Enter fullscreen mode Exit fullscreen mode

Install the manual-web-socket package

I am going to install a websocket testing package manual-web-socket
(github) and use it.

Writing the test

My Cypress test will follow the following steps-

  • Require manual-web-socket package
  • Use the nifty onBeforeLoad to access websocket services and attach them to our beloved win object in cypress
  • Finally, set up a mock connection
    • Change connection status to OPEN
    • send a message, and assert that it shows up in our react app

The test itself (with comments) -

/// <reference types="Cypress" />

const manualWebSocket = require('manual-web-socket') // import the package

describe('Tests websocket', () => {
  it('Successfully processes websocket message from server', () => {
    cy.visit('/')
      .get('[id=websocket]')
      .should('have.text', 'websocket is closed')

    cy.visit('/', {
      onBeforeLoad(win) {
        var script = win.document.createElement('script')
        script.innerText = manualWebSocket.getScript()
        win.document.head.appendChild(script)
        win.mws.track(['ws://127.0.0.1:5000']) // we start tracking ws connection here
      },
    }).then((win) => {
      const mws = win.mws
      const trackedConnection = mws.trackedConnections.getByUrl(
        // get connection by URL
        'ws://127.0.0.1:5000'
      )
      trackedConnection.readyState = mws.readyState.OPEN // set the ws state to OPEN
      const connOpenMessage = 'connection open with client'
      const payload = { data: 'Cypress is connected via websocket' }
      trackedConnection.addServerScenario(
        // addServerScenario to mock ws server on the other side
        'connection open with client',
        (connection, message) => {
          connection.reciveMessage(payload)
        }
      )
      trackedConnection.send(connOpenMessage) // send message to ws client
      cy.get('[id=websocket]').should(
        'have.text',
        'Cypress is connected via websocket' // Assert the change in client state
      )
      trackedConnection.readyState = mws.readyState.CLOSED // close ws connection
    })
  })
})
Enter fullscreen mode Exit fullscreen mode

The test goes green.

👋 One last chance before you go!

It takes one minute to join DEV and is worth it for your career.

You get 3x the value by signing in instead of lurking

Join now

Top comments (0)

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay