Skip to content

Prevent Error.captureStackTrace from erasing Error stack #5136

@bvaughn

Description

@bvaughn

I'm working on some custom Jest matchers for the React repo and I noticed a quirk that I believe is intentional, but doesn't seem optimal. Essentially the problem is this: I'm unable to throw an error from within a custom matcher without the stack being overridden by Jest via Error.captureStackTrace.

So a meaningful stack like this:

ReferenceError: asdf is not defined

  38 |   const foo = () => bar();
  39 |   const bar = () => baz();
> 40 |   const baz = () => asdf();
  41 |   expect(() => {
  42 |     foo();
  43 |   }).toWarnDev([

  at baz (path/to/test.js:40:28)
  at bar (path/to/test.js:39:35)
  at foo (path/to/test.js:38:35)
  at path/to/test.js:42:7
  at Object.matcher (path/to/matcher.js:47:11)
  at Object.<anonymous> (path/to/test.js:43:8)

Becomes a generic stack like this:

ReferenceError: asdf is not defined

  41 |   expect(() => {
  42 |     foo();
> 43 |   }).toWarnDev([
  44 |     'foo',
  45 |     'bar',
  46 |   ]);

  at Object.<anonymous> (path/to/matcher.js:43:8)

I'd like a way to preserve the original stack since it contains useful information. I don't object to the current default behavior, but it would be nice if there was a way to mark a specific error to be skipped. Looking at the source code though, it seems like there aren't really any good options:

  • A custom matcher can't throw an instance of JestAssertionError (since the class isn't exposed externally).
  • I could set the error.name to "PrettyFormatPluginError" but this is a pretty major hack for a few reasons (it relies on undocumented internals and it would modify the error message logged to the developer).
  • I could override Error.captureStackTrace, but this could not be done within the matcher; rather it would need to be done in a global beforeEach hook.

What would you think of an approach like the one React uses for error logging (eg a special property Jest checks for on an error like dangerousDontCaptureStack that prevents the stack from being overridden)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions