0

I want to test in Chai does some event was emitted after some time. My class :

export default class GeneratorService {
  constructor() {
      this.evn = new Events();
      this.generate();
  }

  generate() {
      this.check();
  }

  check() {
      setTimeout(() => {
            this.evn.events.emit('done', 'value');
      }, 2000);
  }

}

I have no idea how can I test does event done was emitted after 2s.

bdddd
  • 103
  • 1
  • 10
  • Look at this answer: https://stackoverflow.com/questions/11235815/is-there-a-way-to-get-chai-working-with-asynchronous-mocha-tests – Below the Radar Nov 30 '18 at 15:49
  • Possible duplicate of [Is there a way to get Chai working with asynchronous Mocha tests?](https://stackoverflow.com/questions/11235815/is-there-a-way-to-get-chai-working-with-asynchronous-mocha-tests) – Jared Smith Nov 30 '18 at 15:59

1 Answers1

2

By passing one argument to it (usually called done) and then calling that argument when you want to finish your test.

This way you are signalling Mocha that this is an async test, and you want to wait until you call done() to finish the test, which you will do in an event listener for the "done" event from your GeneratorService instance.

Here's an example:

const chai = require('chai')
const EventEmitter = require('events').EventEmitter

chai.should()

class Client {
  constructor() {
    this.evt = new EventEmitter()
  }

  fireDone() {
    setTimeout(() => {
      this.evt.emit('done')
    }, 2000)
  }
}

describe('Client', function () {
  // increase mocha's default timeout to 3000ms, otherwise
  // the test will timeout after 2000ms.
  this.timeout(3000)

  const client = new Client()

  it('emits done after 2000 ms', function(done) {
    const now = Date.now()

    client.evt.on('done', function end(value) {
      (Date.now() - now).should.be.at.least(2000)
      // Do more assertions here; perhaps add tests for `value`.          

      // Here we call done, signalling to mocha
      // that this test is finally over.
      done()

      // remove listener so it doesn't re-fire on next test.
      client.evt.removeListener('done', end)
    })

    client.fireDone()
  })
})

Note: I replaced GeneratorService with Client and made it more compact for brevity.

Also, you can probably use Mocha's default 2000ms timeout limit to check that the event is indeed fired within 2 seconds, which negates the need to add the time comparison I check I've added in my example: (Date.now() - now).should.be.at.least(2000).

nicholaswmin
  • 21,686
  • 15
  • 91
  • 167
  • Thanks. It's my 1st mocha/chai project, idk yet who's problem it is. Why you pass `err` to `done()`? It's giving me error bcz `err` is `undefined` = `Error: done() invoked with non-Error: value`. – bdddd Dec 03 '18 at 09:34
  • Revised; You should call `done(err)` with the `err` argument being of type `Error` in case you want to signal to mocha that you want to end this test with an error (it failed). Otherwise just `done()`. – nicholaswmin Dec 03 '18 at 12:00