I'm using React and have a file tree like this:
src/
common/
common-comp1/
common-comp1.js
common-comp1.test.js
index.js
common-comp2/
common-comp2.js
common-comp2.test.js
index.js
index.js
app/
app-comp1/
app-comp1.js
app-comp1.test.js
index.js
app-comp2/
app-comp2.js
app-comp2.test.js
index.js
index.js
All of the index.js files are barrel files that export * from '...';
. I have path aliases set up so that I can import CommonComp1 from 'common';
in src/app/app-comp1/app-comp1.js
.
Unfortunately, this loads/transforms the code from src/common/common-comp2/*
as well, even though app-comp1.js
doesn't import it. This is fine when I build the app with webpack, because I need everything to be imported and transformed anyway.
However, with tests, with some 350 components, this makes running a single test suite very slow on startup. I only want to import/transform the files necessary to run the tests. Is there a way to lazy-load every export/import? I thought maybe I could do this by mocking my barrel files and exporting a Proxy
that only requires/memoizes components when they are imported directly, by calling jest.requireActual()
. I started to do this, but then realized I'd have to parse the entire file tree for import and export names, which sounds tedious. (At least I think I would have to do this.)
I thought I might also try proxying require()
itself (I attempted this several weeks ago for a different issue), but iirc, it is a constant or declared non-configurable/non-writable.
Thoughts?
You can mock the barrel file in your test using the module factory parameter, and set only the exports you want.
if common-comp1.js exports as default do it like this:
app-comp1.test.js:
jest.mock('common',()=>{
const CommonComp1 = jest.requireActual('common/common-comp1').default;
return {__esModule: true, CommonComp1}
})
if common-comp1.js exports are named then do it like this:
app-comp1.test.js:
jest.mock('common',()=>{
const allNamedExports = jest.requireActual('common/common-comp1');
return {__esModule: true, ...allNamedExports}
})
for a more automated version you could have __mocks__/index.js
files generated by a script.
that script would go through each index.js file import it, get the name of the exports and put them in a module.exports object getter.
Like this:
__mocks__/common.js
:
module.exports={
get CommonComp1() {
return jest.requireActual('../common/common-comp1').CommonComp1;
}
get OtherExportFromCommonComp1() {
return jest.requireActual('../common/common-comp1').OtherExportFromCommonComp1;
}
get CommonComp2() {
return jest.requireActual('../common/common-comp2').CommonComp2;
}
}