How to use node-fetch with Jest and Typescript?
Asked Answered
W

3

6

I'm trying to setup a very simple NPM codebase that I can use to drive an API to do some testing.

The line of code causing the error is just import fetch from "node-fetch";, see the code.

For the setup/configuration, I'm following this repository (suggestions for a better template to use would be appreciated): https://github.com/bromix/typescript-jest-example

When I try to use the node-fetch library in my code (either in a test.ts file in the /test directory or a .ts file in the /src directory) - I get the following error:

FAIL  test/Api.test.ts
  ● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

...

    Details:

    C:\ardc\rats\node_modules\node-fetch\src\index.js:9
    import http from 'node:http';
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 1 | import fetch from "node-fetch";
        | ^
      2 |
      3 | const apiBase = "https://api.raid.org.au/v1";
      4 |

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1796:14)
      at Object.<anonymous> (src/RaidApi.ts:1:1)

I gather there's something weird about node-fetch v3.x having upgraded to be an esmodule, as stated in this answer here: https://mcmap.net/q/417432/-node-fetch-3-0-0-and-jest-gives-syntaxerror-cannot-use-import-statement-outside-a-module

But I've tried frobbing a bunch of different things in package.json and tsconfig.json but I can't get it work.

What change do I need to make so my tests can use node-fetch to make request calls?

The whole point of the repo is just to make these HTTP calls, so there's no compatibility problems to consider with changing module type or whatever needs doing.

My workaround is to downgrade to node-fetch 2.6.7 as shown here. But if this esmodule stuff is the way forward, I'd like to figure out how to make it work.


You can see the entire failing project here: https://github.com/ardc-shorn/rats/tree/0cdf2cf1ff4bc9e7ef0fa6113db9b9ff9f6cc6c9

But, to have a self-cointained question, here's the important config.

package.json: {
  "name": "rats",
  "version": "0.0.1",
  "description": "RAiD API Test Suite",
  "scripts": {
    "build": "tsc",
    "test": "jest"
  },
  "devDependencies": {
    "@types/jsonwebtoken": "8.5.8",
    "jsonwebtoken": "8.5.1",
    "node-fetch": "3.2.6",
    "@types/jest": "28.1.1",
    "jest": "28.1.1",
    "ts-jest": "28.0.5",
    "typescript": "4.7.3",
    "ts-node": "10.8.1"
  }
}

tsconfig.json: {
  "include": ["./src/**/*"],
  "exclude": ["node_modules"],
  "compilerOptions": {
    "target": "ES5",
    "module": "CommonJS",
    "outDir": "./out",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

jest.config.js:
  module.exports = {
    preset: 'ts-jest',
    testEnvironment: 'node',
  };
Wachtel answered 16/6, 2022 at 6:59 Comment(1)
If you want to use the ES module version of node-fetch, you need to have an ES module yourself - update the package file and the module the compiler's targeting (as well as every import, unless you want to use an experimental option). You'll also need to tweak ts-jest accordingly: kulshekhar.github.io/ts-jest/docs/guides/esm-support.Tholos
G
0

Your project isn't an ECMAScript-Module, so you are unable to resolve them. The only exception is if they include an alternate build for CJS, or whatever pre-ESM module type your using. Its actually pretty easy to figure this out with a quick DDG/Google search.

In reference 2 my Pre-ESM comment: your using CJS, as a consequence; you can only use an ESM package if it contains a transpiled CJS build (I guess they could hand write them both, but why?). Any package that does this will clearly state that they support both ESM & CJS in their package's docs (README.md file). If for some reason you want to check another way than their docs, you would be able to quickly tell by looking at any package.json files the project contains. A quick sign is seeing more than one package.json file, &/or seing an "exports" property in the package.json

Groth answered 18/6, 2022 at 2:13 Comment(0)
K
4

I my case, it looks like there was some issue with the latest node-fetch 3.x packaged and ts-jest.

I went back to "node-fetch": "^2.6.7" and problem was solved

more details about the ts-jest / node-fetch issue

Kobi answered 19/7, 2022 at 9:19 Comment(0)
C
1

In my case I do not have to apply a downgrade at the package node-fetch, the next solution solve me this issue:

Mock the node-fetch module:

import 'node-fetch';

jest.mock('node-fetch', () => jest.fn());

Example:

// File: src/test/someTestFile.test.ts
... imports
import 'node-fetch';

jest.mock('node-fetch', () => jest.fn());
... some other mocks

describe("Some Unit test", () => {
  ... some tests
});
// File: package.json
{
  ...
  "scripts": {
    ...
    "test": "jest src/",
    ...
  },
  "dependencies": {
    ...
    "node-fetch": "^3.2.10",
    ...
  }
  ...
}
Cravens answered 4/10, 2022 at 14:25 Comment(2)
At this particular time, I have a Junior seniority on typescript. I am a python guy for many years now, so feel free to expose any code smells or some incorrect behavior.Cravens
Works great, after a lot of tries, easy the simpliest way to set up jest with node-fetchBuckboard
G
0

Your project isn't an ECMAScript-Module, so you are unable to resolve them. The only exception is if they include an alternate build for CJS, or whatever pre-ESM module type your using. Its actually pretty easy to figure this out with a quick DDG/Google search.

In reference 2 my Pre-ESM comment: your using CJS, as a consequence; you can only use an ESM package if it contains a transpiled CJS build (I guess they could hand write them both, but why?). Any package that does this will clearly state that they support both ESM & CJS in their package's docs (README.md file). If for some reason you want to check another way than their docs, you would be able to quickly tell by looking at any package.json files the project contains. A quick sign is seeing more than one package.json file, &/or seing an "exports" property in the package.json

Groth answered 18/6, 2022 at 2:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.