Exploring the compatibility of Next.js with jest for utilizing third-party ESM npm packages

Caught between the proverbial rock and a hard place.

My app was built using:

  • t3-stack: v6.2.1 - T3 stack
  • Next.js: v12.3.1
  • jest: v29.3.1

Followed Next.js documentation for setting up jest with Rust Compiler at https://nextjs.org/docs/testing#setting-up-jest-with-the-rust-compiler

Introduced https://wagmi.sh/ (React Hooks for Ethereum) to my project, smooth sailing until component testing began.

In order to test, created a mocked wagmi client in a test file by importing necessary packages like this:

import { Client, createClient, WagmiConfig, useConnect } from "wagmi";

Upon running the test, encountered an issue:

.../node_modules/wagmi/dist/index.js:2 import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister"; ^^^^^^

SyntaxError: Cannot use import statement outside a module

Explored various options in jest.config.js including filters and transformIgnorePatterns but no solution for transforming wagmi esm enabled library.

Referenced jest docs and implemented ECMAScript Modules support by adding extensionsToTreatAsEsm: [".ts", ".tsx"] to jest.config.js which allowed running tests with nodejs flag:

NODE_OPTIONS=--experimental-vm-modules npx jest -- src/__tests__/Wallet.test.tsx

Success! Everything worked flawlessly!

Later needed to mock a hook and revisited jest docs on mocking modules in ESM mode, hit a roadblock as I couldn't mock hooks despite trying numerous setups detailed in the issue here.

Reverted to original setup sans ESM support where jest.mock function worked as intended.

However, faced a new challenge of not being able to import wagmi due to its ESM compatibility without ESM support activated.

The question now is how to import npm packages that are ESM modules?

Answer №1

I wanted to share my own experience and solution for a common issue:

The main problem arose from the fact that jest does not fully support node ESM mode at this time, causing issues when loading ES modules.

Additionally, there is a specific file in the Next.js distribution version, next/dist/build/jest/jest.js, which complicates overriding the testPathIgnorePatterns configuration option.

To address these challenges, you have two options:

  • Utilize
    NODE_OPTIONS=--experimental-vm-modules
    with jest, although it may limit the usage of jest.mock functionality (as discussed here).
  • Alternatively, you can modify the Next.js jest config file, as detailed in this discussion. This approach involves transpiling ESM modules before running tests, which was the path I chose.

Answer №2

Encountered the same issue when working with NextJS and Wagmi.

To address the issue, I followed the solution provided above by using

NODE_OPTIONS=--experimental-vm-modules
in the test command and adding
extensionsToTreatAsEsm: [".ts", ".tsx"]
to my jest.config.js. However, I faced a new problem:

Reference error: jest is not defined
. To resolve this, I installed @jest/globals using pnpm add @jest/globals and imported jest in every test file as follows:
import { jest } from "@jest/globals"

This is how my final jest.config.js looks like:

const nextJest = require('next/jest')

const createJestConfig = nextJest({
  dir: './',
})

const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testEnvironment: 'jest-environment-jsdom',
  extensionsToTreatAsEsm: [".ts", ".tsx"],
  transform: {},
}

module.exports = createJestConfig(customJestConfig)

For running tests, I use the following command:

"test": "NODE_OPTIONS=--experimental-vm-modules jest --ci --silent",

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to get the Gtranslate function to function properly within the drop-down menu

Currently, I am using Gtranslate.io languages on my website with flags displayed without a drop-down menu. Everything is running smoothly but now I am looking to enhance the user experience by placing the flags inside a drop-down list. I want English to ...

What is the best way to implement custom pagination in Material UI?

<Pagination count={35} variant="outlined" shape="rounded" color="primary"/> Although the default background and text colors are set, I am unable to customize them. I have attempted to change the colors without success. ...

How can we ensure that React state remains unaltered when modifying an array set to state?

Hope you're having a wonderful day! I'm encountering a significant problem with React. I have a state that contains an array. Within a function, I create a copy of the state in a new variable. However, any modifications made to this new variable ...

Tips for adjusting the time format within Ionic 3 using TypeScript

I currently have a time displayed as 15:12:00 (HH:MM:SS) format. I am looking to convert this into the (3.12 PM) format. <p class="headings" display-format="HH:mm" > <b>Time :</b> {{this.starttime}} </p> In my TypeScript code t ...

Update image attributes (such as src, alt, etc.) after a successful AJAX request (and also help me troubleshoot my AJAX

The image link I am currently using is: echo "<br/><div class='right' id='post" . $id . "'> <img id='thumb' src='/images/like.png' title='Like it?' alt='Like button' onC ...

Preserve setTimeout() Functionality Across Page Refreshes and Navigations

I am trying to display an alert message after a 15-minute delay, but the functionality is disrupted when the page refreshes or if I navigate to a different page. This all takes place on a single web page. When a specific button is clicked, it should trig ...

Encountered an issue retrieving audio during recording with Recorder.js

I've come across a scenario where I'm utilizing the Recorder.js Demo for recording audio. Interestingly, it works perfectly on Linux but encounters an issue when used on Windows. A pop-up alert stating "Error getting audio" shows up. Here's ...

Implement a function to trigger and refresh components in various Vuejs2 instances simultaneously

I currently have index.html with two Vue instances in different files: <!DOCTYPE html> <html lang="en"> <body> <div id="appOne"> </div> <div id="appTwo"> </div> </body> </html ...

Utilizing jQuery to Adjust Tab Transparency

I'm trying to add some opacity to my jQuery tabs, but so far I've only been successful with accordions. Any tips or tricks for achieving this effect with tabs? Styling with CSS .ui-tabs{ background-image: none; background: rgba(204, 204 ...

What is the process for integrating TypeScript compiling into a JavaScript application?

My project includes a build.js file that is responsible for building the project. It has two main objectives: Compile .ts files and store them in a new directory. Create an asar archive containing the compiled files. Since typescript (or tsc) is availabl ...

"Learn how to implement a feature that allows for the acceptance of string input in discord

I am struggling to find the right solution for my issue. I am trying to implement a change_nick command but unsure about what type/number option to utilize. This is how I'm creating my command: commands.create ( { ...

Disable the function when the mouse is moved off or released

My custom scrolling implementation in a ticker using Jquery is due to the fact that standard scrolling doesn't function well with existing CSS animations. The goal is to enable movement of the ticker when clicking and dragging on the controller, a div ...

"Implementing autocomplete feature with initial data in Angular 4 using FormControl

I have incorporated material.angular.io components into my app, particularly autocomplete. I am customizing it to function as a multi-select, but I am encountering an issue with loading initial values: export class CaseActivityTimeEditComponent implements ...

Error encountered: Unsuccessful fetch during deployment on Vercel platform using Next.js

I'm currently developing a website with the help of next.js and utilizing Route Handlers. Strangely, everything seems to be working smoothly when I execute the npm run build command locally. However, upon deploying the site to Vercel, an unexpected er ...

AJAX code fetching dynamic content without relying on file loading

When I load my program, the dynamic code does not appear on the page until I reload it again. I attempted to use the onload event in the body to load content from an XML file using AJAX, but it only works after closing and reopening the program, not dynam ...

Blip Scripts: Converting JSON to JavaScript - Dealing with Undefined Arrays

I am currently working on a project to develop a bot on Blip. There are certain parts where I need to send a request to an API and then use a JavaScript script to extract elements from the JSON response. The JSON response I received from the API is stored ...

Vue.js: Attaching a function to a Template

I am struggling to find a way to bind my screen height to a calculated value in my code. Unfortunately, the current implementation is not working as expected. I would greatly appreciate any guidance on how to resolve this issue. <template> <b ...

Executing a background.js function in response to an event trigger within the active tab in a Chrome extension

I am facing an issue where I am getting an error saying "resetTime is not defined" when running the code below. I have tried passing the function as an argument, but that did not solve the problem. Do I need to come up with a new logic to reset the time ...

Validate that the input is an array

Looking for a way to determine if a function parameter is an array or not, and then process it accordingly. If the parameter is not an array, convert it into an array before performing the desired function. For example: interface employee { first: st ...

Best Practice for Delivering JavaScript Files with Node.js Ajax?

In my current project, I am developing a node application that serves client-side JavaScript code to a static webpage. The goal is to have the code evaluated within the webpage, similar to the concept demonstrated in this example, but using Node.js instead ...