Error message while using Jest, ts-jest, and TypeScript with ES Modules import: module not found

Having difficulties getting Jest to work with a TypeScript project that uses ES modules and the import syntax. I originally wrote my project using commonjs, and the Jest tests ran fine. However, when I switched to ES Modules for learning purposes, Jest is not happy ヽ(`Д´)ノ The tools I am working with: TypeScript, Jest, ts-jest

The issue arises with the import syntax.

Below are the different code variations I've attempted:

//  projectRoot/src/app.ts

export default someFunction = (): void => {
   // some code
}

If

// projectRoot/__tests__/app.test.ts

import someFunction from '../src/app';   // without file extension

/* This runs perfectly fine */

However,

// projectRoot/__tests__/app.test.ts

import someFunction from '../src/app.ts'   // with .ts

/*
● Test suite failed to run

   __tests__/app.test.ts:1:25 - error TS2691: An import path cannot end with a '.ts' extension. Consider importing '../src/app' instead.

    1 import information from '../src/app.ts';
*/

Additionally,

// projectRoot/__tests__/app.test.ts

import someFunction from '../src/app.js';   // with .js

/*
● Test suite failed to run

    Cannot find module '../src/app.js' from '__tests__/app.test.ts'
*/

As shown in the examples above, Jest (or perhaps ts-jest?) does not like it when I import the module with an extension, which is necessary for ES Modules. I have done some research online, but it seems like the Jest documentation is not very helpful for ES Modules. The same goes for ts-jest as seen in this issue.

My project structure:

/projectRoot
 ├── /src/app.ts
 ├── /__tests__/app.test.ts

The package.json file includes

"type": "module"

tsconfig.json:

{
  "compilerOptions": {
     "target": "ES2015",
     "module": "ESNEXT",
     "outDir": "./build",
     "strict": true,
     "moduleResolution": "node",
     "esModuleInterop": true,
     "skipLibCheck": true,
     "forceConsistentCasingInFileNames": true
  },
  "include": ["./src"],
  "exclude": ["node_modules", "**/*.test.ts"]
}

jest.config.js

export default {
    "roots": [
      //"<rootDir>/src"
      "<rootDir>"
    ],
    "testMatch": [
      "**/__tests__/**/*.+(ts|tsx|js)",
      "**/?(*.)+(spec|test).+(ts|tsx|js)"
    ],
    "transform": {
      "^.+\\.(ts|tsx)$": "ts-jest"
    },
    "preset": "ts-jest",
    "testEnvironment": 'node'
  }

Any help would be greatly appreciated. Thank you.

Answer №1

When you include the import statement provided below

// projectRoot/__tests__/app.test.ts

import someFunction from '../src/app.js';   // with .js

you can configure ts-jest to utilize this by adding the following to your jest.config.js file:

module.exports = {
  //... // your previous configurations
  extensionsToTreatAsEsm: ['.ts'],
  globals: {
    'ts-jest': {
      //... // your other configurations here
      useESM: true,
    },
  },
  moduleNameMapper: {
    '^(\\.{1,2}/.*)\\.js$': '$1',
  }

The details for this configuration can be found on the ts-jest documentation page: ESM-Support

Here is a snippet of sample code:

// components_ts.ts
export add(x: number, y: number): number {
    return x + y;
}
// render_ts.ts
import * as ComponentsTS from './components_ts.js'; // <-- Extension is JS

export function addedNumbers(): number {
    let addedNumbers: number = ComponentsTS.add(1, 2);
    return addedNumbers;
}
// render_ts.test.ts
import * as RenderTS from '../ts_files/render_ts';

it ('Test addNumbers function', () => {
    expect(RenderTS.addedNumbers()).toBe(3);
});

To run this, use the command npm jest

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

Is it possible to use a single type predicate for multiple variables in order to achieve type inference?

Is there a way to optimize the repeated calls in this code snippet by applying a map to a type predicate so that TSC can still recognize A and B as iterables (which Sets are)? if(isSet(A) && isSet(B)) { ...

Ensuring that a date is within a certain format in TypeScript

Can someone help me verify the validity of different date formats? I attempted the following method: let newdate = new Date(myStringDate); Date.parse(myStringDate) result = `${newdate.getDate()}/${newdate.getMonth() + 1}/${newdate.getFullYear()}` The re ...

Angular removing every query string parameters

Linked to but distinct from: How to maintain query string parameters in URL when accessing a route of an Angular 2 app? I am facing an issue with my basic Angular application where adding a query parameter results in its removal, both from the browser&apo ...

Tips and tricks for displaying JSON data in Angular 2.4.10

In my Angular project, I am facing an issue while trying to display specific JSON data instead of the entire JSON object. Scenario 1 : import { Component, OnInit } from '@angular/core'; import { HttpService } from 'app/http.service'; ...

What is the mechanism by which AngularJS manages all of my module dependencies with jest?

Updated: Since this is an older project, I didn't use any module loader. Instead, I imported all dependencies in my index.html using the script tag. The structure of my AngularJS looks like this: app.js angular.module('app', ['Loca ...

Learn how to hide the dropdown menu in Angular 8 by detecting clicks outside of the menu area

Is there a way to hide the custom dropdown menu whenever I click outside of it? After trying the code below, I noticed that it hides even if I click on an element inside the dropdown menu: <button class="btn btn-primary btn-sm mt-1" type="button" id= ...

Error: TypeScript is unable to locate the 'moment' module

My TypeScript React application was set up using npx create-react-app --template typescript. However, when I try to start the app with npm start, I encounter an error in one of my files: TypeScript error in /<path>/App.tsx: Cannot find module ' ...

Issue with retrieving all phone numbers from a contact in Ionic

Hope you're doing well! I'm encountering an issue with Ionic Contacts. Currently, I'm able to retrieve all the contacts using my code but I need help extracting all the phone numbers associated with each contact. For example, if John has 3 ...

Extract reference value from an HTML element

Is there a way to access the ref prop from an HTML element using Testing Library React? My current code snippet is as follows: it('element container ref should be null if prop noSwipe is passed', () => { const onCloseMock = jest.fn() ...

How can you define a function type for a rest parameter in Typescript?

At this point, I have a function that takes in two parameters: param 'a' as a string and 'b' as a function that returns a string. My intention is to call it using a rest parameter and specify the types accordingly. However, on line 10 ...

Invoking Component Function via Service

I am in the process of developing a file upload feature for my application. Once the files are successfully uploaded, I want to clear the list of uploaded files. To achieve this, I have created the following function in the file uploader component: clea ...

Using JavaScript to retrieve comma-separated values depending on a specific condition

Hey there, I am encountering a problem with filtering out values from an array of objects. Essentially, I have an array of objects const arr = [ { "id": null, "name": null, "role": "Authorized ...

In socket.io, the event occurs twice in a row

I am encountering an issue with my socket.io nodejs cluster setup in my project where the same event is triggered twice. Despite trying different versions of Socket.io, the problem persists and two instances of the same event are being emitted. The current ...

How to retrieve a Typescript variable within an ngIf conditional statement in Angular

How can I access a TypeScript variable inside an ngIf statement? TS: public data: string; HTML: <td> <div *ngIf="data === 'BALL' ; else noplay" >{{ play }}</div> <ng-template #noplay> {{ gotohome ...

What is the benefit of utilizing ngSubmit over just using a basic button and function?

Lately, I've been pondering whether to utilize ngSubmit or simply bind a (click)="submit()" on a button. There's been much debate about using submit and ngSubmit, but is it necessary to rely on the traditional HTML submit method? Particularly wh ...

Is there a way to inject 'cmd' into the browser for Sentry (@sentry/nextjs package) by using a personalized webpack setup in Next.js?

My package json includes the following dependencies: "webpack": "5.58.1", "@sentry/nextjs": "6.13.3", "typescript": "4.0.5", "next": "11.0.1", After running next build without ...

The functionality of the Ionic menu button becomes disabled once the user has successfully logged in

Having trouble clicking the button after taking a test. Situation: Once logged in -> user takes a test and submits -> redirected to home page. However, unable to click on "Menu button" on the home page. In my Login.ts file: if (this.checker == " ...

React error: The module "react-router-dom" does not have a member named "useNavigate" available for export

I'm attempting to include useNavigate for use as outlined in the top answer here: react button onClick redirect page import { useNavigate } from "react-router-dom"; However, I am encountering this error: export 'useNavigate' (impo ...

The new PropTypes package is incompatible with TypeScript's React context functionality

When utilizing React.PropTypes, the code functions correctly but triggers a warning about deprecation (Accessing PropTypes via the main React package is deprecated...): import * as React from 'react'; export class BackButton extends React.Compo ...

Typescript: Removing specific types from a type

In my quest to filter out specific types from a group, I encountered a challenge with exclusion. Take for instance the scenario below: type RemoveUndefined<T> = T extends undefined | infer R ? R : T; type numbersOnly = RemoveUndefined<undefined | ...