Search code examples
javascriptwebsocketmocha.jsassertfeathersjs

How to write my code to test a websocket event?


I am trying to test that data gets added to my database after a websocket event has fired.

In the application I am working with there is already a working example of this.

it('some test name', function (done) {
    this.timeout(12000)

    var socket = io.connect('http://localhost:3000', {
      'transports': [
        'websocket',
        'flashsocket',
        'jsonp-polling',
        'xhr-polling',
        'htmlfile'
      ]
    })

    socket.emit('some-room-event', {
      participant: 'p1',
      room: 12,
      active: true
    })

    setTimeout(function () {
      app.service('rooms').get(12)
         .then(function (room) {
           assert(room.active === true)
           socket.disconnect()
           done()
         }).catch(function (err) {
           socket.disconnect()
           done(err)
         })
    }, 11000)
  })

I am coming from a ruby background and slotting into the project so I am quite new. It feels a bit like the use of a timeout is a code smell and it just feels wrong. You don't want to increase the duration it takes to run your tests by an arbitrary wait time.

I have read a lot of articles around this, but it's pretty confusing. Is there a better way to structure this code and potentially get rid of the setTimeout?

I am using feathersjs, mocha and assert.


Solution

  • It looks like the event that is being tested is just a normal websocket event that does something to the rooms service.

    An arbitrary timeout in the test is definitely not the best way to solve the issue that the websocket event does not acknowledge when it has completed whatever it was supposed to do. What I think you could do is to listen to a Feathers service event when the room is updated or patched (although it is a little odd that the socket event isn't just using the official socket.emit('rooms::update', data) to update the room state):

    it('some test name', function (done) {
      var socket = io.connect('http://localhost:3000', {
        'transports': [
          'websocket',
          'flashsocket',
          'jsonp-polling',
          'xhr-polling',
          'htmlfile'
        ]
      });
    
      app.service('rooms').once('updated', function(room) {
        assert(room.active);
        done();
      });
    
      socket.emit('some-room-event', {
        participant: 'p1',
        room: 12,
        active: true
      });
    });