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

Cannot instantiate bugsnag client in jest test #452

Closed
keattang opened this issue Dec 20, 2018 · 22 comments
Closed

Cannot instantiate bugsnag client in jest test #452

keattang opened this issue Dec 20, 2018 · 22 comments

Comments

@keattang
Copy link

I have a react app and I am trying to test one of my components that pulls in my bugsnag client and uses it to create an ErrorBoundary using the react plugin.

However, when creating the bugsnag client I get the following error: TypeError: setInterval(...).unref is not a function.

The file the creates the client looks like this:

import React from 'react';
import Bugsnag from '@bugsnag/js';
import bugsnagReact from '@bugsnag/plugin-react';
import config from '../config';

const bugsnag = Bugsnag({
    apiKey: config.bugsnagKey,
    releaseStage: config.env,
    appVersion: config.version,
    notifyReleaseStages: ['production', 'staging'],
});
bugsnag.use(bugsnagReact, React);

export default bugsnag;

The error occurs when trying to create the client with Bugsnag({...})

I get the following stack trace:

at SessionTracker.start (node_modules/@bugsnag/node/dist/bugsnag.js:2138:75)
      at Object.init (node_modules/@bugsnag/node/dist/bugsnag.js:2028:20)
      at BugsnagClient.use (node_modules/@bugsnag/node/dist/bugsnag.js:163:30)
      at node_modules/@bugsnag/node/dist/bugsnag.js:1578:20
          at Array.forEach (<anonymous>)
      at module.exports (node_modules/@bugsnag/node/dist/bugsnag.js:1577:11)
      at Object.<anonymous> (src/utilities/bugsnag.js:91:9)
      at Object.<anonymous> (src/index.jsx:503:35)
      at Object.<anonymous> (test/components/App.spec.jsx:9:35)
@bengourley
Copy link
Contributor

This seems odd – are your jest tests running in Node?

You're in a bit of a grey area because jest tests usually run browser code in node, and this means that Bugsnag loads @bugsnag/node rather than @bugsnag/js, but since I imagine you are running in Node, timer.unref() should be defined.

What version of Node are you running?

There might be something we can do here – either to get it to load the browser notifier (depending on how much of the browser env gets stubbed/mocked by jest) or make the Node notifier behave a little better. In order to do so it would be good to have a bit more context or info about your setup. Please provide as much as you can! A stripped back project that we can run and reproduce this issue would be perfect. Thanks!

@keattang
Copy link
Author

  • Running Node v10.9.0
  • Tests are run from an npm/yarn script that simply calls jest
  • Running jest v23.6.0
  • Running yarn v1.10.1
  • jest config looks like this:
module.exports = {
    verbose: true,
    bail: true,
    collectCoverage: true,
    setupTestFrameworkScriptFile: '<rootDir>/test/setup.js',
    moduleNameMapper: {
        '\\.(css|scss)$': 'identity-obj-proxy',
        '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
            '<rootDir>/test/__mocks__/fileMock.js',
    },
};

Let me know if you need any more details. I'll let you know what I have a stripped back project to test against.

@keattang
Copy link
Author

@bengourley
Copy link
Contributor

Thanks for the repro, very helpful! We will take a look. Until we come back with a solution, I would suggest to following awful temporary monkeypatch in your tests!

setTimeout().__proto__.unref = function () {}

@keattang
Copy link
Author

Great thanks!

@txwkx
Copy link

txwkx commented Jan 8, 2019

Any updates on this matter?
Experiencing the same issue.

Test suite failed to run
• TypeError: setInterval(...).unref is not a function

Node v11.6.0
npm v6.5.0
Bugsnag v5.1.0

Running npm test from a CRA project.
The test suite is quite simple because it only checks if a component renders.

@curt-mitch
Copy link

+1 for this issue while running Jest in a Puppeteer environment.

Node v8.12.0
npm v6.5.0
Bugsnag v5.1.0
Jest v23.1.0
Puppeteer v1.11.0

@bengourley
Copy link
Contributor

Please use the browser: true option in Jest:

Respect Browserify's "browser" field in package.json when resolving modules. Some modules export different versions based on whether they are operating in Node or a browser.

In its package.json @bugsnag/js uses the browser field to export the browser bundle and the main field to export the Node bundle. Jest is weird because it looks like Node but runs tests in a browser-like jsdom environment. I don't know why it doesn't respect the browser field by default.

We'll still fix this error because it's confusing and unnecessary, but it's important that Jest loads the correct module!

@bengourley bengourley added the scheduled Work is starting on this feature/bug label Feb 8, 2019
@axelinternet
Copy link

I'm also experiencing this error. I tried setting the browser setting in package.json but without any success. However I have a Nextjs setup so it is possible those settings override that at some point. In the end I don't know if this is an optimal solution for me anyway since I have both Node and "browser" tests for my server side rendering process and is dependant on both the node and browser version of Bugsnag.

@bengourley
Copy link
Contributor

browser: true needs to be under the jest key package.json, can you confirm it was there?

{
  "name": "my-package",
  "version": "1.0.0",
  "jest": {
    "browser": true
  }
}

@axelinternet
Copy link

Yes unfortunately that was the case. I also tried playing around with using jests environment setting in the test file but with the same result

/**
 * @jest-environment jsdom
 */

test('Some test', () => {})})

Result

  ● Test suite failed to run

  TypeError: setInterval(...).unref is not a function

     5 | import bugsnag from '@bugsnag/js'
     6 |
  >  7 | const bugsnagClient = bugsnag({ apiKey: 'key',
       |                       ^
     8 |   notifyReleaseStages: ['production', 'staging'],
     9 |   appType: 'node'
    10 | })

I use Jest 24.40 and Bugsnag 6.0.0

@remotealex
Copy link

Same issue here using CRA (--typescript)

@domharrington
Copy link

domharrington commented May 7, 2019

I ended up doing something like this to stub out bugsnag within the test environment:

const bugsnag = require('@bugsnag/js');
const bugsnagExpress = require('@bugsnag/plugin-express');

let bugsnagClient;

if (process.env.NODE_ENV !== 'testing') {
  bugsnagClient = bugsnag('xxxxxx');
  bugsnagClient.use(bugsnagExpress);
} else {
  bugsnagClient = {
    getPlugin() {
      return {
        requestHandler(req, res, next) {
          req.bugsnag = { notify() {} };
          return next();
        },
        errorHandler(req, res, next) {
          return next();
        },
      };
    },
  };
}

Also using jest to run node.js tests.

@bengourley
Copy link
Contributor

Thanks @domharrington! If you're running Node tests – and you're not doing this already – you should make sure Jest is using the Node environment because by default it uses jsdom. Set this with something like (or command line flag, or @ test annotation):

{
  "name": "my-package",
  "version": "1.0.0",
  "jest": {
    "testEnvironment": "node"
  }
}

Though if you're using Jest for Node and browser tests in the same codebase you'd probably want to set it dynamically. See the testEnvironment docs for more details.

@axelinternet can you share more information on your setup or provide a sample repo where I can reproduce the problem? Is your code being bundled or built before your tests are run?

@remotealex I've filled a PR against create-react-app to allow you to set the correct config, feel free to 👍 that issue so that it gets more attention!

@bengourley
Copy link
Contributor

Oh and here's a link to said PR facebook/create-react-app#7024 😄

@bengourley
Copy link
Contributor

Another solution that I haven't yet mentioned is that if your code is not "universal" i.e. you don't run the same thing in Node and in the Browser, and you don't need to automatic detection of whether to load the Node/Browser notifier, you can import the exact notifier you want:

const bugsnag = require('@bugsnag/browser')
// or
const bugsnag = require('@bugsnag/node')

So if your tests are running in jsdom, pull in @bugsnag/browser and if they are running in Node, pull in @bugsnag/node.

Also consider if Bugsnag should be loaded in your tests at all! If you are testing the ErrorBoundary component with Jest then that seems a good enough reason, but if you aren't using any of the features and are just switching off error reporting, maybe the scope of your tests should be reduced to not include an error reporter?

I'm going to close this off as there are multiple workable solutions. The fact that you get an error at all is a good canary that the wrong library has been loaded, and hopefully anybody who gets this error in future will find this issue.

Any further problems, let us know!

@abhilashktiwari
Copy link

abhilashktiwari commented Jun 6, 2019

👍

import bugsnag from '@bugsnag/browser';

works for me in project and testing(using jest and enzyme) as well.
👍

@andreimc
Copy link

@bengourley this still happens on node with @bugsnag/js if you follow the instructions on the bugsnag website jest won't run

@mattdyoung
Copy link
Contributor

@andreimc - have you tried the suggestion Ben made previously here yet?
#452 (comment)

@phillipsam phillipsam removed the scheduled Work is starting on this feature/bug label Aug 5, 2019
@dlin-me
Copy link

dlin-me commented Jul 13, 2020

Adding testEnvironment: "node" to my jest.config.js solved my problem. Adding it to the package.json file did not work.

@kylemh
Copy link

kylemh commented Sep 12, 2020

Agreed on not needing Bugsnag during tests, but documentation usually instantiates Bugsnag globally or as an IIFE. To avoid caring about Bugsnag during tests while following Bugsnag docs, simply add:

jest.mock('@bugsnag/js'); in your Jest setup file (the file that the jest.config.js maps to via setupFilesAfterEnv).

@evocateur
Copy link

Another way to do this, using moduleNameMapper in jest.config.js:

module.exports = {
  moduleNameMapper: {
    '@bugsnag/js': '@bugsnag/browser'
  }
}

(or package.json jest field):

  "jest": {
    "moduleNameMapper": {
      "@bugsnag/js": "@bugsnag/browser"
    }
  }

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