Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Exception classes ignored #909

Closed
booleangate opened this issue Jan 21, 2017 · 4 comments
Closed

Custom Exception classes ignored #909

booleangate opened this issue Jan 21, 2017 · 4 comments

Comments

@booleangate
Copy link

Unless I'm missing something, custom exception classes are being ignored when checked with throw. Here's an example:

class NotImplemented extends Error { }
expect(() => { throw new NotImplemented(); }).to.not.throw(NotImplemented);

This expectation passes although it shouldn't.

@booleangate
Copy link
Author

Did some more testing and this is probably due to Babel. Changing the class definition to Object.create instead of class ... extends makes the expectation fail as expected.

function NotImplemented() {
    Error.prototype.constructor.apply(this, arguments);
}

NotImplemented.prototype = Object.create(Error.prototype);
NotImplemented.prototype.name = 'NotImplemented';
NotImplemented.prototype.constructor = NotImplemented;

expect(() => { throw new NotImplemented(); }).to.not.throw(NotImplemented);

Maybe this is worth noting somewhere in the docs?

I'll leave this issue open so it can be seen, but feel free to close it.

@keithamus
Copy link
Member

Hey @booleangate thanks for the issue.

This is because Babel does not support extending native types - as some older browsers don't do this.

Take a look at some of these: https://babeljs.io/docs/usage/caveats/#classes, babel/babel#4058, babel/babel#106, https://www.npmjs.com/package/babel-plugin-transform-builtin-extend

I'll close this; while we could document it I somewhat don't think it is not our responsibility to document issues with other tools and would be burdensome to do so. Babel has some small documentation about this on their site - it could arguably be more prominent but thats not for us to dictate 😄

Feel free to continue discussion here. If we come to a different resolution, we can always re-open this issue.

@booleangate
Copy link
Author

Indeed, documenting individual interoperability edge cases would be a nightmare. Relying on Google to bring up this PR for people with my particular issue is probably enough.

@asinner
Copy link

asinner commented Dec 5, 2019

Just FYI if you're using Typescript and reading this, you will run into this issue trying to check the error type using chai.throw(). Here is the Typescript doc on this particular issue.

In order to handle this I use the matching feature to ensure that the error it's throwing is the expected error (a similar approach will work in other compiled Javascript langs):

class NotFoundError extends Error {
  constructor(msg?: string) {
    super(`resource not found: ${msg}`)
  }
}

function example() {
  throw new NotFoundError()
}

expect(example).to.throw(Error, /resource not found/)

Even better, you can assign unique error codes for your classes as a way to identify them in tests and across application code:

class NotFoundError extends Error {
  public static ERR_CODE: 'ERR_NOT_FOUND'

  constructor(msg?: string) {
    super(NotFoundError.ERR_CODE + ' ' + msg)
  }
}

You could even create an intermediate class to extend from that handles the err code / msg interpolation before constructing the parent Error class.

Your test code

expect(example).to.throw(Error, new RegExp(NotFoundError.ERR_CODE))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants