Rafael Barros Rafael Barros - 3 months ago 13
Javascript Question

How to mock readline.on('SIGINT')?

I have this piece of code:

function getMsg() {
return new Promise(function (resolve, reject) {
var input = [];
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', function (cmd) {
if (cmd.trim()) {
input.push(cmd);
} else {
rl.close();
}
});
rl.on('close', function () {
rl.close();
resolve(input.join('\n'));
});
rl.on('SIGINT', reject);
});
}


I'm trying to test this function, my attempt, so far, is this:

it('should reject if SIGINT is sent', function () {
sandbox.stub(readline, 'createInterface', function () {
return {
on: function (action, callback) {
callback();
},
prompt: function () {},
close: function () {}
};
});

return getMsg().then(null).catch(function () {
expect(true).to.be.equal(true);
});
});


But of course, that doesn't simulate a
SIGINT
, how do I do this?

Answer

I think you need a different setup:

const EventEmitter = require('events').EventEmitter
...
it('should reject if SIGINT is sent', function () {
  let emitter = new EventEmitter();
  sandbox.stub(readline, 'createInterface', function () {
    emitter.close = () => {};
    return emitter;
  });

  let promise = getMsg().then(function() {
    throw Error('should not have resolved');
  }, function (err) {
    expect(true).to.be.equal(true);
  });

  emitter.emit('SIGINT');

  return promise;
});

The object returned by readline.createInterface() inherits from EventEmitter, so that's what the stub will return. The additional close function is simply added to it to prevent errors when it gets called.

You can't return the promise returned by getMsg directly, because that doesn't give you a chance to emit the SIGINT "signal" (really just an event, but for testing purposes it'll work just fine). So the promise is stored.

The test should fail with the "fulfilled" handler gets called, which had to be done explicitly, otherwise Mocha thinks the test passed.

Next, the SIGINT is sent (which should trigger the rejection handler as intended), and the promise is returned.