1

I have a global object which has the ability to assign functions for events, like:

obj.on('event', () => {});

After exact public API is called these events are fired as well.

Now I need to write async tests with mocha.js/chai.js and run it in the node.js environment.

I stuck in a situation when two events subscriptions should be tested at once.

All code is written in TypeScript and later transpiled into JavaScript.

The code in a global object:

public someEvent(val1: string, val2: Object) {
 // some stuff here...
 this.emit('event_one', val1);
 this.emit('event_two', val1, val2);
}

The code in a test file (my latest realization):

// prerequisites are here...
describe('test some public API', () => {
 it('should receive a string and an object', (done) => {
  // counting number of succesfull calls
  let steps = 0;

  // function which will finish the test
  const finish = () => {
   if ((++steps) === 2) {
    done();
   }
  };

  // mock values
  const testObj = {
   val: 'test value'
  };

  const testStr = 'test string';

  // add test handlers
  obj.on('event_one', (key) => {
   assert.equal(typeof key, 'string');
   finish();
  });

  obj.on('event_two', (key, event) => {
   assert.equal(typeof key, 'string');
   expect(event).to.be.an.instanceOf(Object);
   finish();
  });

  // fire the event
  obj.someEvent(testStr, testObj);
 });
});

So, my question is - is there any built-in functionality to make this test to look more elegant?

Another question is how to provide some meaningful error information instead of default error string?

Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

scipios
  • 13
  • 1
  • 5
  • If `event_one` and `event_two` and not logically connected you should probably do 2 separate tests – nikksan Sep 04 '18 at 19:27
  • But these events are fired one after another. And I need to check that values were not mutated somehow on the way and to ensure that both of events are fired. – scipios Sep 04 '18 at 19:30
  • if you know the execution order you can nest them and call `done()` after the second event has fired, but still if they are 2 separate events without correlation between them you should write 2 separate tests, you can ensure that both tests pass – nikksan Sep 04 '18 at 19:44
  • Can you give me an example? Also, do you have any ideas on how to handle timeout error? Thank you! – scipios Sep 04 '18 at 19:49
  • you should add spies on your implementation. This link helps a bit https://stackoverflow.com/questions/27209016/how-to-test-event-emitters-in-node – LostJon Sep 04 '18 at 20:18
  • i would suggest using sinon as well :) – LostJon Sep 04 '18 at 20:19
  • Thank you! I will take a look! – scipios Sep 04 '18 at 20:20

1 Answers1

0

Thanks to LostJon's comments!

My solution is to add sinon.js library to the project and to use sinon.spy.

The solution would be like this:

import * as sinon from 'sinon';

...

// prerequisites are here...
describe('test some public API', () => {
 it('should receive a string and an object', (done) => {
  const spyOne = sinon.spy();
  const spyTwo = sinon.spy();

  // mock values
  const testObj = {
   val: 'test value'
  };

  const testStr = 'test string';

  // add test handlers
  obj.on('event_one', spyOne);
  obj.on('event_two', spyTwo);

  // fire the event
  obj.someEvent(testStr, testObj);

  // assert cases
  assert(spyOne.calledOnce, `'event_one' should be called once`);
  assert.equal(typeof spyOne.args[0][0], 'string');

  assert(spyTwo.calledOnce, `'event_two' should be called once`);
  assert.equal(typeof spyTwo.args[0][0], 'string');
  assert.equal(typeof spyTwo.args[0][1], 'object');
 });
});
scipios
  • 13
  • 1
  • 5