Jest Less Import Error
Recently encountered UT errors in a frontend project. At first I was completely confused, but gradually unraveled the issue through careful analysis. Documenting this here.
Error Phenomenon
Error CODE
Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
/xxx/xx/B.less:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){.searchRow {
^
SyntaxError: Unexpected token .
31 |
32 |
> 33 | import styles from 'app/xxx/xx/B.less';
| ^
Initial Analysis
Why does a specific component’s LESS file cause issues
This error seemed strange because many components import LESS files, so why did only this one fail? At first I thought there might be some invisible corrupted characters or spaces in the LESS file that weren’t visible to the naked eye. But after reformatting and checking, I couldn’t find anything.
So I compared it with other components and found one difference with the failing LESS file - it was imported by two components. For example, component A has style A.less, component A itself imports style A.less, and component B also imports A.less. I quickly copied B.less out and reran UT - it passed.
Why did the Main component UT fail
Since it was confirmed to be a component LESS import issue, this part was easier to analyze. The Main component imports route configuration, and the route configuration file imports major components. So when UT runs, it executes these imports and thus reports the error.
Runtime OK but UT not OK - Jest configuration? Since runtime doesn’t report errors, it means the code is fine. So I looked at the current jest configuration and had an epiphany:
Modules imported via absolute app paths don't go through `identity-obj-proxy`, and the failing line was an app path import, so the LESS wasn't successfully mocked.
I tried adding the following rule:
Reran UT - it passed.
Best Solution
Although the above configuration addition can solve the problem, what’s the best solution? This is worth considering.
The above issue reveals that the current Jest configuration does have shortcomings. If you import LESS from app paths, UT will fail. But realistically speaking, is there currently a need to import LESS from absolute app paths? No
.
Because as shown above, it actually imports duplicate LESS files. Just in terms of bundle size, it essentially packages duplicate LESS files. Since there’s CSS module, the two don’t interfere with each other. But since the goal is to reuse this style, the current issue is just using the wrong approach.
Correct Approach
If you need to reuse such LESS:
One method is to put it in the root component’s index.less, where CSS is global.
If not placed there, it can be placed at the common parent component level of both components. For example, if these two components are component A and component B, they have a common parent component C, so put the style on C. Then A and B can naturally reuse it.
Related Knowledge Points Summary
- CSS Modularization
CSS modularization is now a very mature CSS style management solution. Why call it management? Because with it, it actually solves the long-standing annoying CSS conflict issues. At the same time, CSS modularization also provides an outlet for global styles. This makes management quite elegant.
- import styles from ‘index.less’
This import method turns CSS usage into JS usage. So if we move positions or rename CSS, it can be automatically modified. This unifies CSS and JS. Isn’t that great.
identity-obj-proxy
in jest
This module is designed to solve the use of non-JS resources in our UT tested components, such as CSS, PNG, SVG, etc. In testing, many things need to be mocked. Tests always aim to check our core logic with the lowest fabrication cost and most realistic testing points.
Summary
At this point, this problem is solved and understood. Happy. There are still many pitfalls in frontend development. But all methods follow the same principles. Let’s encourage each other.