• 03-Jan-2023
Lightrun Team
Author Lightrun Team
Share
This is a glossary of all the common issues in Facebook JEST

Troubleshooting Common Issues in Facebook JEST

Lightrun Team
Lightrun Team
03-Jan-2023

Project Description

 

Jest is a JavaScript testing framework developed and maintained by Facebook. It is a popular choice for testing React applications, and it can also be used for testing applications built with other JavaScript libraries or frameworks. Jest is designed to be easy to use, fast, and flexible, and it provides a number of features to help you write and run high-quality tests. Some of the key features of Jest include:

  • Automated test running and reporting: Jest can run your tests and report the results in a user-friendly format.
  • Snapshot testing: Jest can take a snapshot of your component’s output and save it, allowing you to later verify that the component’s output has not changed.
  • Mock functions: Jest includes a powerful library for mock functions, which can be used to stub out functions in your code during tests.
  • Code coverage reporting: Jest can generate a code coverage report, showing you which parts of your code are being tested and which are not.

Overall, Jest is a powerful and easy-to-use tool that can help you improve the quality of your JavaScript code.

Troubleshooting Facebook JEST with the Lightrun Developer Observability Platform

 

Getting a sense of what’s actually happening inside a live application is a frustrating experience, one that relies mostly on querying and observing whatever logs were written during development.
Lightrun is a Developer Observability Platform, allowing developers to add telemetry to live applications in real-time, on-demand, and right from the IDE.
  • Instantly add logs to, set metrics in, and take snapshots of live applications
  • Insights delivered straight to your IDE or CLI
  • Works where you do: dev, QA, staging, CI/CD, and production

Start for free today

The following issues are the most popular issues regarding this project:

Jest did not exit one second after the test run has completed

 

If you encounter an error while running integration tests with a Sequelize Model, the ideal solution is to call close on the instance connected to it during your afterAll callback. Making this simple change can prevent that pesky test from stalling your whole process:

# dbConnection.js
export default new Sequelize({...}); // The Sequelize instance.
# some.spec.js
import dbConnection from './dbConnection';

const { SomeModel } = dbConnection.models;

describe('...', () => {
  beforeEach(async () => {
      await SomeModel.create({...});
  });
  ...
});

afterAll(async done => {
  // Closing the DB connection allows Jest to exit successfully.
  dbConnection.close();
  done();
});

 

Jest mock/spy returns undefined even when set up

 

Firstly you should examine the jest.config.js file; a setting of resetMocks: true had been put into place, meaning that every time one test ran after another, mock functions would be compulsorily reset and return undefined as their output instead.

It appears react-scripts automatically sets a resetMocks flag totrue in the jest configuration. However, users have the flexibility of customizing this setting by directly altering relevant parameters within theirpackage.json file.

JavaScript heap out of memory after upgrade to Jest 26

 

The issue of a memory leak has been an existing difficulty since 2019, and we have now implemented measures to record the information in order to discover solutions. Previous issues were related to graceful-fs, however, it appears that some users have managed to solve this by temporarily removing graceful-js after running jest tests. Additionally, troubleshooting threads suggest compileFunction within vm package as another potential source for the problem. Notably, both Jest testrunner along with webpack-dev server alongside babel & create react app all make effective use of reactive dependency ‘graceful js’. A regression may have occurred in Jest’s latest release, as we are once again facing the memory leak issue. After a large number of tests were conducted on our environment and CI machine, heap overflows appeared- despite attempts to limit this with 1 worker or runInBand solutions – due to an increase that surpassed its allocated memory.

Collecting coverage and graceful-fs, two filesystem-related issues, have been identified as the source of these problems. Solutions to file importations have already been achieved by addressing them both.

The cause:
Using imports of the format import * from 'whatever'

The solution:
Using the format import { whatINeed } from 'whatever' instead dramatically reduced memory accumulation.

JEST tests complete successfully but returns exit status 1

 

Snapshots: 3 obsolete, 26 passed, 26 total obsolete – are the cause of the error, after their removal, the error is gone.

How can I have all my tests and mocks inside a folder “tests” next to my “app” source code

 

As you work on resolving the issue, utilize this solution for now. Tests folder contains a helpful resource:

<strong>mocks.js</strong> file with such data for example:

exports.api = {
  getWeather: Promise.resolve({sky: 'Sunny', rain: '10%'}),
  somethingElse: Promise.resolve([{_id:'yg321i14', name:'example'},{...
}

In order to call an API from any component that has imported a function from root/api, simply execute the following procedure:

jest.mock('root/api', () => require('../mocks').api)

To provide quick relief, a stopgap solution has been suggested. Yet two brief lines remain to be implemented in order to satisfy the need for mocking components:

jest.mock('root/components/SomeComponentFolder/SomeComponent')
const SomeComponent = require('root/components/SomeComponentFolder/SomeComponent')

 

“Received: serializes to the same string” on object equality checking

 

An efficient workaround is available to address the issue at hand:

expect(JSON.stringify(result.current)).toEqual(JSON.stringify(expected));

 

Jest with TypeScript and ES modules can’t import “named imports” from cjs modules

 

After a thorough investigation, it has been revealed that jest’s file resolution process is distinct from Node.js’ – they both use cjs-module-lexer to decipher exported functions of CJS libraries; however, the same package could potentially behave differently between the two environments and cause confusion in this regard. To investigate further and gain better insight into possible discrepancies associated with such behavior variations among these modules, examples have been taken on a case-by-case basis.

glob

Glob’s export code appears deceptively simple, appearing as module.exports = glob. However, beneath this facade lies a complex relationship that cjs-module-lexer cannot decipher because it is designed to match regex for the performance prerequisite of NodeJS – an undertaking that ends in failure when done outside this particular environment.

enzyme

Enzyme’s export code looks like this:

module.exports = {
  render: _render2['default'],
  shallow: _shallow2['default'],
  mount: _mount2['default'],
  ShallowWrapper: _ShallowWrapper2['default'],
  ReactWrapper: _ReactWrapper2['default'],
  configure: _configuration.merge,
  EnzymeAdapter: _EnzymeAdapter2['default']
}; Unfortunately,cjs-module-lexer is unable to extract any exported functions beyond the first.

tslib

With the appropriate node configuration, tslib effectively supports both cjs and es6 modules. The success of no errors when running indicates a proper implementation occurs with ESMs (Node Compatible) functioning through the exports property.

import { __assign } from "tslib";

const d = __assign({ a: "a" });
console.log(d.a);

However when running the following test in Jest ESM:

import { __assign } from "tslib";

test.only("General config is working", async () => {
  const d = __assign({ a: "a" });
  expect(d.a).toBe("a");
});

You’ll get the following error:

FAIL  src/tslib.test.js
  ● Test suite failed to run

    SyntaxError: The requested module 'tslib' does not provide an export named '__assign'

      at Runtime.linkAndEvaluateModule (node_modules/jest-runtime/build/index.js:669:5) It appears that Jest and NodeJS have different interpretation of the same file, leading to an incorrect determination by cjs-module-lexer as to what is being exported.

Summary

By delving into this issue, we can strive to resolve it for tslib. To fully fix the matter for glob, however, will necessitate addressingcjs-module-lexer as well.

jest.mock does not mock an ES module without Babel

 

Jest’s jest.mock function is designed to allow you to mock out the dependencies of a module during testing. However, by default, it will only work for CommonJS modules, which are not the same as ECMAScript (ES) modules.

If you are using an ES module and you want to mock it with jest.mock, you will need to make sure that you have Babel configured to transform your code to a format that Jest can understand. Specifically, you will need to have the @babel/preset-env and @babel/plugin-transform-modules-commonjs presets installed and configured in your Babel configuration.

Once you have these presets set up, you should be able to use jest.mock to mock out your ES modules in your tests. For example:

// my-module.js
export default function myModule() {
  // ...
}

// my-module.test.js
import myModule from './my-module';

jest.mock('./my-module');

test('mocks myModule', () => {
  myModule.mockImplementation(() => 'mocked result');
  expect(myModule()).toBe('mocked result');
});

 

Jest failing with “Call retries were exceeded”, using –runInBand works-around issue

 

After appending the --runInBandflag, success was achieved. No further information is required as long as the desired outcome of seeing green tests has been fulfilled.

spyOn getter only works for static getters and not for instance getters

 

Working with Mobx and TypeScript can present some unwanted challenges due to an unpleasant bug. As a workaround, the property may be set directly despite any typescript errors that arise in the process:

// @ts-ignore
instance.foo = false;

 

doc : jest fake timers : expect on setTimeout not working

 

After activating the fake timers, you can spy on global activities:

jest.spyOn(global, 'setTimeout');

Utilizing modern fake timers can be an effective way to test a given task without relying on the exact millisecond timing. For example, jest.advanceTimersByTime() provides much control over when tasks are run and in what order they occur in using jest.runAllTimers(). Additionally one can verify them with tools such as toHaveBeenNthCalledWith().

jest cannot find tests when projects are defined in configuration

 

To provide a resolution to your issue, this solution may prove useful:

{
roots: ["<rootDir>/src/", "<rootDir>/__tests__/"],
}

Without such a folder, any other material will be disregarded.

Async callback was not invoked within the 5000ms timeout – Error Message Improvement

 

Despite rigorous testing, an unfortunate reality remains: the mocked return values of certain tests may unintentionally bleed into other tests due to a lack of proper resetting. While not a definitive answer, we hope this information will prove useful for those seeking solutions similar to this one:

afterEach(() => { 
  jest.clearAllMocks(); 
  jest.resetAllMocks();
});

 

moduleNameMapper should work on resolved import paths

 

The challenge of this issue was swiftly resolved by leveraging the typeface library and providing a precise path to the css file:

import 'typeface-montserrat/index.css'

Despite its impressive capabilities, moduleNameMapper will only identify modules that have been imported with a .css file in the path.

Allow to share global state between tests from globalSetup

 

While the desired use case may appear to be a challenging feat, it is worth investigating this potential solution. Initial testing suggests we could utilize integration tests with an in-memory server; thereby providing us with a possible approach moving forward:

const server = await startServer()

The need to launch a “server” instance over multiple test files is challenging, especially since the associated ‘startServer’ function requires five to ten seconds of startup time. With this in mind, it would be encouraging if someone could provide assurance that an effective solution exists for this dilemma.

Retrieve global variable after running jest programmatically

 

If you are looking for a potential solution, consider adding an afterAll hook in the setupFilesAfterEnv. This will enable serializable data to be passed between processes or create your own test environment and use its teardown.

Introduce a more flexible and better typed way to mock APIs

 

For a more sophisticated approach, this version offers the ability to mock types that include properties that do not involve functions.

type GenericFunction = (...args: any[]) => any

type PickByTypeKeyFilter<T, C> = {
  [K in keyof T]: T[K] extends C ? K : never
}

type KeysByType<T, C> = PickByTypeKeyFilter<T, C>[keyof T]

type ValuesByType<T, C> = {
  [K in keyof T]: T[K] extends C ? T[K] : never
}

type PickByType<T, C> = Pick<ValuesByType<T, C>, KeysByType<T, C>>

type MethodsOf<T> = KeysByType<Required<T>, GenericFunction>

type InterfaceOf<T> = PickByType<T, GenericFunction>

type PartiallyMockedInterfaceOf<T> = {
  [K in MethodsOf<T>]?: jest.Mock<InterfaceOf<T>[K]>
}

export function mock<T>(...mockedMethods: MethodsOf<T>[]): jest.Mocked<T> {
  const partiallyMocked: PartiallyMockedInterfaceOf<T> = {}
  mockedMethods.forEach(mockedMethod =>
    partiallyMocked[mockedMethod] = jest.fn())
  return partiallyMocked as jest.Mocked<T>
}

 

More issues from Facebook repos

 

Troubleshooting facebook-react | Troubleshooting facebook-create-react-app | Troubleshooting facebook-metro | Troubleshooting facebook-prophet | Troubleshooting facebook-flipper

Share

It’s Really not that Complicated.

You can actually understand what’s going on inside your live applications. It’s a registration form away.

Get Lightrun

Lets Talk!

Looking for more information about Lightrun and debugging?
We’d love to hear from you!
Drop us a line and we’ll get back to you shortly.

By submitting this form, I agree to Lightrun’s Privacy Policy and Terms of Use.