How to test your react websocket implementation using cypress
Tags: react, websocket, cypress, testing
Published: 2020-06-20 15:39:07

---
title: How to test your react websocket implementation using cypress
published: true
date: 2020-06-20 00:00:00 UTC
tags: react, websocket, cypress, testing
canonical_url: https://adityanaik.dev/blog/2020/05/27/how-to-easily-test-react-stripe-elements-using-cypress/
---

### Set up demo application

I scaffold a standard react application

```bash
$ npx create-react-app ws-demo
```

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

```js
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
}
```

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](https://www.cypress.io/) 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:

```bash
$ npm install cypress
or
$ yarn add cypress
```

I will also install the recommended dependency

```bash
$ npm install -D start-server-and-test
```

[start-server-and-test](https://github.com/bahmutov/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 -

```json:title=package.json
"cy:test": "start-server-and-test start http://localhost:3001 cy:open"
```

### Install the manual-web-socket package

I am going to install a _websocket testing package_ [manual-web-socket](https://www.npmjs.com/package/manual-web-socket)
([github](https://github.com/vokial-the-death-knight/manual-web-socket)) 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) -

```js
/// <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
    })
  })
})
```

The test goes green.