node-csv
node-csv copied to clipboard
I get `Cannot find module 'csv-stringify/sync'` by running ts-jest
Describe the bug
As the title says, I can't use csv-stringify/sync in my tests by running ts-jest. But I can build and run by ts-node.
Dependencies:
- CSV package
- csv-stringify: 6.0.4
Environment:
- Nodejs: v16.13.1
- TypeScript: 4.5.2
- Jest: 27.4.3
- ts-jest: 27.1.0
To Reproduce
I have prepared a repository for the explanation. If you want to see the whole thing(Jest configuration or tsconfig or like that), please check there: https://github.com/OldBigBuddha/cant-find-csv-stringify-in-jest-test
Main code:
// src/main.ts
import { stringify } from "csv-stringify/sync";
export function toCsv(data: any): string {
return stringify(data);
}
Test Code:
// tests/main.test.ts
import { toCsv } from "../src/main";
test("stringify", () => {
const data = [
{
name: "A",
age: 20,
},
{
name: "B",
age: 16,
},
{
name: "C",
age: 38,
},
{
name: "D",
age: 27,
},
];
const csv = toCsv(data);
expect(typeof csv).toEqual("string");
expect(csv).toEqual(`A,20
B,16
C,38
D,27
`);
});
These codes can be transpiled to JavaScript by tsc. But If you run it by ts-jest, it will fail because of Cannot find module 'csv-stringify/sync' from 'src/main.ts'
Additional context
Nothing.
UPDATE: I noticed that the test will pass with [email protected].
I made the branch for [email protected] in my sample repository.
I know that csv module's export was changed from [email protected]. I don't know much about exporting esm modules, but I'm pretty sure it's related.
This is probably related to https://github.com/facebook/jest/issues/9771. i.e. Jest is not using package.json's exports field.
In that case you'd have to use import 'csv-stringify/dist/cjs/sync' to make it work in Jest. Of course since it's only your test runner and not the host executing your project outside of tests I'll understand that's probably not going to work.
Edit: Maybe there's a chance you could use moduleNameMapper in your jest config to force Jest to load the correct module as a workaround until Jest supports Node.js' package.json exports field.
Thanks for advice!
I use v5.6.5 now, but I'll try it later.
Thanks @dantman for the advice. I was able to get my test working by adding a moduleNameMapper to my jest config:
...
moduleNameMapper: {
"^csv-stringify/sync":
"<rootDir>/node_modules/csv-stringify/dist/cjs/sync.cjs"
}
...
@scottgeye thank you so much for posting that. Works for csv-parse, too! '^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs',
I am also having this issue with v6.0.5
@scottgeye Thank you for posting the solution! I had the same issue on csv-parse/sync package as well.
My case is a bit of different, since the folder structure.
Just wanted to share here, in case other people has similar problem.
Here is my project folder structure:
├── projectRoot
│ └── package.json
│ └── jest.json
│ └── node_modules
│ └── csv-parse
│ └── ...
│ └── modules
│ └── module1
│ └── package.json
│ └── jest.json
│ └── module2
│ └── package.json
└ └── jest.json
I wanted to test module1 which has csv-parse/sync package imported, it was getting the error of can't find csv-parse/sync module.
I added moduleNameMapper to the config and it works fine when I run the test under module1 directory.
But in my team, we have a process to run unit tests at projectRoot level which gave me the same error again.
I needed to change the jest config file under projectRoot as well in order to make the unit tests passed either from projectRoot and module1 folders.
Here are the jest config files look like in my project:
- jest.json under
projectRootfolder:
const baseConfig = require('./jest.config.base')
module.exports = {
...baseConfig,
projects: ['<rootDir>'],
roots: ['<rootDir>'],
coverageDirectory: '<rootDir>/coverage/',
moduleNameMapper: {
"^csv-parse/sync": '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs'
},
}
- jest.json under
module1folder:
const path = require('path')
const baseConfig = require('../../jest.config.base')
const csvParseSyncPath = path.resolve(__dirname, '../../node_modules/csv-parse/dist/cjs/sync.cjs')
const packageName = require('./package.json').name
module.exports = {
...baseConfig,
displayName: packageName,
moduleNameMapper: {
"^csv-parse/sync": csvParseSyncPath
},
}
The jest config file is read at the folder level when the jest command is ran unless the config file path is specified.
In my case, I needed to change the jest config both under rootProject and module1 since jest command is ran under both folders.
+1. Though moduleNameMapper sol'n fixed it.
Doing some cleanup, closing.
I met the same issue when using csv-stringify/browser/esm. moduleNameMapper works for me!
Node: 16.19.1 Jest: 27.5.1 csv-stringify: 6.4.4
"moduleNameMapper": {
"axios": "axios/dist/node/axios.cjs",
"csv-stringify/browser/esm": "csv-stringify/dist/cjs/index.cjs"
}