4

I have a object that is subscribed to the uncaught error event and I am trying to test its behaviour. First I tried with jasmine-node, but now when I am trying to go with jasmine I found trouble. Could anyone help me.

describe('Constructor tests', function () {
    it('error is passed to the callback', function (done) {
    const error = new Error("testError-0");

    let errorHandler = new AllErrorHandler((arg1) => {
        expect(arg1).toBe(error);
        errorHandler.dispose();
        done();
    });

    setTimeout(() => {
        throw error;
    }, 0)
});

Thanks in advance.

Yordan Kanchelov
  • 511
  • 9
  • 26

1 Answers1

3

I got this working when executed directly via jasmine when the jasmine ./tests/alLErrorException.spec.js command is run. The following changes were required:

Always setup the listeners, even when the _callback should not be executed.

constructor(callback, startListening = true) {
  if (!callback) {
    throw new Error("Missing callback function");
  }

  this._callback = callback;
  this._listening = startListening;
  this._setupEvents();
}

Add a function to intercept uncaughtException events and to call the _callback if we are _listening:

_handler() {
  if(this._listening) {
    this._callback.apply(null, arguments);
  }
}

Remove all other uncaughtException event handlers in _setupEvents:

_setupEvents(attatch = true) {
    this._listening = attatch ? true : false;

    if (attatch) {
        if (typeof window !== "undefined") {
            window.addEventListener("error", this._callback);
        } else {
            // Added this line
            process.removeAllListeners('uncaughtException');
            process.addListener('uncaughtException', this._handler.bind(this));
        }
    } else {
        if (typeof window !== "undefined") {
            window.removeEventListener("error", this._callback);
        } else {
            process.removeListener('uncaughtException', this._callback);
        }
    }
}

This is required because jasmine sets up it's own uncaughtException handler and reports an error even though the error was caught by the AllErrorHandler class.

Here is a paste of the full source for the AllErrorHandler class with the required changes.

bitshift
  • 498
  • 2
  • 13
  • First, thank you for the advice and answer you gave me. But ain't it wrong to removeAll uncaughtException Listeners only to pass some test? Is there a practice to let's say add a function that will remove all listeners and call it only when the jasmine works? – Yordan Kanchelov Dec 05 '17 at 14:33
  • @JordanKanchelov I would say it is wrong. A more detailed approach would involve retrieving the list of existing handlers and potentially calling them as well. If you do this, jasmine will report an error on the tests. Also, IMO, that's beyond the scope of this question. – bitshift Dec 05 '17 at 15:08
  • your solution work, but I am searching a way to do this right and will keep the accept answer for now if anyone else finds another way or framework to bypass this, because removing the listeners is not a desired behavior and could potentially break any other user logic. – Yordan Kanchelov Dec 05 '17 at 16:37
  • Take a look at this https://nodejs.org/api/events.html#events_emitter_listeners_eventname and this https://nodejs.org/api/events.html#events_emitter_prependlistener_eventname_listener. You can use prependListener to add your listener before the others. Or you can get the existing listeners and call them manually yourself. – bitshift Dec 05 '17 at 16:40