We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.

roshan • 3 years ago

1. I had to rename .js files to .cjs files i.e. config/jest/fileTransform.cjs & cssTransform.cjs
=> change their mapping in jest.config
=> used the comment from Syed - to update the content of fileTransform.cjs & cssTransform.cjs

2. renamed jest.config.js to jest.config.cjs

3. also moved vite.svg from public to assets

4. npm i jest-environment-jsdom --save-dev ( since that has been removed out of jest 28 onwards )

Thanks a lot for this.

Dominik Remetei • 2 years ago

For anyone struggling to still get this running, remember to update the import in `config/jest/setupTests.js`.

```
// config/jest/setupTests.js
require("@testing-library/jest-dom/extend-expect");

window.matchMedia = (query) => ({
matches: false,
media: query,
onchange: null,
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
addListener: jest.fn(),
removeListener: jest.fn(),
});

Object.defineProperty(URL, "createObjectURL", {
writable: true,
value: jest.fn(),
});
```

Rafael Pereira • 3 years ago

I'm looking forward to try this since my tests are taking too much time in the pipeline or locally. Thanks for the write up!

Rafael Pereira • 3 years ago

I had an error in jest:

Invalid return value:
`process()` or/and `processAsync()` method of code transformer

Solved by refactoring the return of the transformers to be an object with `code` key, example:

- return `module.exports = ${assetFilename};`;
+ return {
+ code: `module.exports = ${assetFilename};`
+ }

Syed • 3 years ago

// fileTransform.js

'use strict';

const path = require('path');
const camelcase = require('camelcase');

// This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html

module.exports = {
process(src, filename) {
const assetFilename = JSON.stringify(path.basename(filename));
if (filename.match(/\.svg$/)) {
// Based on how SVGR generates a component name:
// https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
const pascalCaseFilename = camelcase(path.parse(filename).name, {
pascalCase: true,
});
const componentName = `Svg${pascalCaseFilename}`;
return {
code: `const React = require('react');
module.exports = {
__esModule: true,
default: ${assetFilename},
ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
return {
$$typeof: Symbol.for('react.element'),
type: 'svg',
ref: ref,
key: null,
props: Object.assign({}, props, {
children: ${assetFilename}
})
};
}),
};`,
};
}

return {
code: `module.exports = ${assetFilename};`,
};
},
};
Syed • 3 years ago

// cssTransform.js

'use strict';

module.exports = {
process(src, filename) {
return { code: `module.exports = {};` };
},
getCacheKey() {
// The output is always the same.
return 'cssTransform';
},
};
roshan • 3 years ago

Thanks.. this was helpful

aditya tyagi • 2 years ago

If anyone wants the latest updated version, I have it here: https://github.com/adityatyagi/everything-react/tree/vite-with-jest-swc

Thank you Hung Viet Nguyen for this amazing blog!

Ookli • 2 years ago

its been so long, would be great to update this article to a more recent changes

helioalves • 3 years ago

Hi Hung Nguyen ,

I've finally switched from CRA to Vite but I'm not facing some issues with mocking modules.

Whenever I have a tests that needs to mock a module it fails, the module is never mocked. I've read that's because when we mock something it is done after we import the module.

I'v'e event tried to switch to Vitest, however I have the same issue with mocking. I know you've switched to Vitest too in bestofjs-webui but looking at the tests, you are not mocking.

I'm wondering if in other projects you've worked on you were able to mock with Vitest/(Vitest/Jest)?

Thanks

Alex Void • 3 years ago

Gone through all the steps but the error stays the same: "Jest failed to parse a file." Terminal showed another error before I renamed .js -> .cjs

Kojo • 3 years ago

Thank you. You are AMAZING.

helioalves • 3 years ago

Great article and very detailed, thank you very much. I've bookmarked this as a reference for later :)

I'm working on a project that is still using webpack 4 :( and I was planing to move it to Vite.

You said that you work with Vite in your projects. I'd like to know if you ever moved a project from CRA/webpack to Vite, if so, was it particularly challenging? Did you encounter many problems?

Hung Nguyen • 3 years ago

@helioalves
Yes. I have. You can refer to this PR: https://github.com/bestofjs.... In the PR description I describe briefly what I need to do for the migration.
It only took me a few hours, but the benefit is 🤯
It does not have many challenges and it's pretty straight forward.

Reference: https://twitter.com/hung_de...

kztmk_media_peple • 3 years ago

Thanks for your great article. I followed this article, but I've got error as follows.

App.test.tsx: Support for the experimental syntax 'jsx' isn't currentry enabled.

If you find I made mistake, let me know.

Thanks again.

Hung Nguyen • 3 years ago

Hi, please make sure you configure jest to transform your `.jsx` using swc
`"^.+\\.(ts|js|tsx|jsx)$": "@swc/jest",`

Please refer to step 8 of this tutorial.

kztmk_media_peple • 3 years ago

Thank you for your advice. I copied from your github code, but I have another errors. Jest 29 have a lot of change from 27. I will try to clear all errors.

Shokhboz Abdullayev • 3 years ago

Great example! But with Vite 3.0.0 there are changes like "type": "module" in package.json. So I had to use .cjs extension for all .js files. Hope it helps others who stuck ;)

Viral Butani • 3 years ago

I am getting same error, but my JS files are ESM module. by chance do you know what is causing this error as they work fine in vite.js dev server.

Aaron Campbell • 3 years ago

I'm hitting this issue, since fileTransform.js requires "camelcase":

Error: Your application tried to access camelcase, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound.

If I yarn add camelcase --dev, it changes to this issue:

Error: require() of ES Module [...]\node_modules\camelcase\index.js from [...]config\jest\fileTransform.js not supported.
Instead change the require of index.js in [...]config\jest\fileTransform.js to a dynamic import() which is available in all CommonJS modules.

It sounds to me like camelcase may no longer support require() syntax, unless this has something to do with Yarn PnP, which my project uses. The solution for me was just to remove that part of fileTransform.js, since my project doesn't directly import svg files.

Hung Nguyen • 3 years ago

There are 2 issues here:
1. Missing `camelcase`. I confirmed that in my tutorial and the final code at
https://github.com/nvh95/je... are missing `camelcase` package. However, it's already a dependency of `jest`, so it will still work fine in the example. However, I will update it shortly to explicitly install `camelcase`.
2. `camelcase` version 7 (newest to the time comment), drop support for CommonJS. ( https://github.com/sindreso... ). So you should install version 6 instead of 7 to avoid the trouble some
`yarn add -D camelcase@6`.

In conclusion, in the future, if your project needs to support `.svg`, you just need to bring back the old code and install `yarn add -D camelcase@6`.

Thanks for your feeback.

Aaron Campbell • 3 years ago

Thanks!!

novascreen • 3 years ago

Any idea on how I might deal with `import.meta.hot` for HMR? can't replace that with `process.env` and define. It's obviously not needed in a test, but the file it's in still fails to parse.

Hung Nguyen • 3 years ago

I think the idea is to avoid these syntax that Jest doesn't understand and use `process.env` instead. I am not sure in which circumstance you need to use `import.meta.hot`

Radu Cebotari • 3 years ago

Hi Hung! Have you figured out how to make them work together? I tried using jest transformations to replace import.meta.env with process.env but it seems that the code gets interpreted before the replacement occurs and I get an error.
The solution with babel doesn't work for me because I use the typescript compiler directly. I tried vitest, but it runs my test twice as slow compared to jest.
Mocking the file that uses import.meta.env didn't work either because it tries to parse it anyway.

Hung Nguyen • 3 years ago

Radu Cebotari
Hi Radu, I have figured out how to make it work. I planed to write a part 2 of this series to handle import.meta.env/ process.env, but I was too busy to make https://www.jest-preview.co... (a library let you view your Jest test UI in a browser, please check it out).

For now, you can see the how I handle "import.meta.env/ process.env" with Vite here https://github.com/nvh95/je... Basically I convert "import.meta.env" to "process.env" and I was pretty happy with that approach.

Radu Cebotari • 3 years ago

Hung Nguyen
Thank you very much, it worked!
I was thinking of the solution from configuring jest as opposed to configuring vite.
Jest preview look very interesting, I will try it out!
Cheers

Viral Butani • 3 years ago

Thanks for the example, I am using vite 3.0 and have type : module in package json.
So I get following error when I try to run test:-

ERROR: module is not defined in ES module scope

I made sure the js files I have are ESM and not CJS.
In this case I should not rename it to .cjs file as all of them are working fine in vite.js. Could you please advise how can I resolve this issue?

Thanks.

Viral Butani • 3 years ago

I resolved it by just renaming the js files which has module.export and cjs related code in it. It works fine with ESM files with .js exension.