cypress-socketio-chat
Example testing real-time Socket.io chat using Cypress.io
The original chat program copied from dkhd/node-group-chat as described in Build A Group-Chat App in 30 Lines Using Node.js blog post.
Blog posts
Testing a Socket.io chat application can be done in several ways. Read the following blog posts to see the alternatives.
Title | Description |
---|---|
Test a Socket.io Chat App using Cypress | Simulates the second user by connecting to the chat server from the plugins file |
Run Two Cypress Test Runners At The Same Time | Launches two test runners, giving them separate specs to run |
Sync Two Cypress Runners via Checkpoints | Launches two test runners, which stay in sync by communicating via their own Socket.io server |
Code Coverage For Chat App | Instruments and measures the fullstack code coverage |
Flip through the presentation slides E2E Testing For A Real-Time Chat Web Application
Specs
Name | Description |
---|---|
first-spec | Tests that the user can post a message and see it |
random-name-spec.js | Creates a random user name for the test |
client-api-spec.js | Invokes events as a 2nd user using app actions |
socket-spec.js | Mimics the 2nd user by connecting to the Socket.io server from the plugin file |
socket-from-browser-spec.js | Mimics the 2nd user by connecting to the Socket.io server from the spec file |
mock-socket-spec.js | The test forces the app to use a mock socket object instead of the real connection, see video |
disconnect-spec.js | Checks if the user disconnects correctly |
Running 2 Cypress instances
This repo also shows how to run 2 Cypress instances at the same time to "really" chat with each other.
- start the server with
npm start
- execute
npm run chat:run
which starts the two Cypress processes
Look at the package.json file to see the commands we use to run the first and second user specs - they are listed in cy-first-user.json and cy-second-user.json config files.
The test runners wait for each other using a common Socket.io server created in the chat.js script. This is a separate Socket.io server from the application.
The first server logs in and reports that it is ready for the second test to start
// cypress/pair/first-user.js
/// <reference types="cypress" />
// this test behaves as the first user to join the chat
it('chats with the second user', () => {
const name = 'First'
const secondName = 'Second'
cy.visit('/', {
onBeforeLoad(win) {
cy.stub(win, 'prompt').returns(name)
},
})
// make sure the greeting message is shown
cy.contains('#messages li i', `${name} join the chat..`).should('be.visible')
cy.task('checkpoint', 'first user has joined')
})
The second test runner executes its own test. It first waits for the checkpoint before visiting the page
// cypress/pair/second-user.js
/// <reference types="cypress" />
// this test behaves as the second user to join the chat
it('chats with the first user', () => {
cy.task('waitForCheckpoint', 'first user has joined')
const name = 'Second'
// we are chatting with the first user
const firstName = 'First'
cy.visit('/', {
onBeforeLoad(win) {
cy.stub(win, 'prompt').returns(name)
},
})
})
Code coverage
Added instrumenting front-end code using istanbul-lib-instrument
module, see index.js file. Read the blog post Code Coverage For Chat App.
Note: I did not use Istanbul middleware because it seemed to not support ES6 syntax (the middleware module had no releases for a long time).