Non-existent files cannot be mocked using variable dynamic imports, but can with non-variable dynamic imports
Describe the bug
When you try to mock a variable dynamic import that has a relative path, the mock is not found. Non-variable dynamic imports work fine and can be mocked.
E.g. If I have an import that looks like
import("../something/index.ts");
I can mock it with
vi.mock("../something/index.ts", ()=>({default: "foo"}));
but if the import is like
const bar = "something"
import("../${bar}/index.ts");
then the exact same mock does not work.
I've searched through all open issue that match the keyword dynamic, and couldn't find anything. There was this closed issue, but it was about dynamically importing a node modules package (non-variable): #1294
Reproduction
https://stackblitz.com/edit/vitest-dev-vitest-mxfhkv?file=src%2Fb-c%2Ffoo.ts
System Info
System:
OS: Windows 10 10.0.22000
CPU: (8) x64 Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
Memory: 6.55 GB / 31.79 GB
Binaries:
Node: 18.9.1 - C:\Program Files\nodejs\node.EXE
npm: 7.24.2 - D:\ado\VueApplication.ContentEditor.Lawbler\node_modules\.bin\npm.CMD
Browsers:
Chrome: 117.0.5938.63
Edge: Spartan (44.22000.120.0), Chromium (117.0.2045.31)
Internet Explorer: 11.0.22000.120
npmPackages:
@vitejs/plugin-vue: ^4.1.0 => 4.1.0
@vitest/coverage-v8: ^0.33.0 => 0.33.0
@vitest/ui: ^0.30.1 => 0.30.1
@vitest/web-worker: ^0.30.1 => 0.30.1
vite: ^4.4.2 => 4.4.2
vitest: ^0.33.0 => 0.33.0
Used Package Manager
npm
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [X] The provided reproduction is a minimal reproducible example of the bug.
Looks like the issue only exists in stackblitz (after adding index.ts file). When installed, I don't see any errors.
By the way, the only correct way to mock it is the last vi.mock.
Ok, I checked again - and it works even in stackblitz. Can you confirm that there is no problem?
Hi, I checked again and I'm seeing this in my stackblitz reproduction still
The first two vi.mock calls were just me checking all the possible types of dynamic import calls to see what succeeds and fails. I've removed everything to be more clear in this reproduction here
https://stackblitz.com/edit/vitest-dev-vitest-mxfhkv?file=src%2Fb-c%2Ffoo.test.ts
Which is still showing me the error
In stackblitz I tried to see if updating from vitest 0.34.5 to 0.35.6 would fix it, but same error
Oh wait, I think I understand your comment now. So in order to mock a variable dynamic import, the file being mocked has to exist on the system. Once I add the /src/a-b/index.ts file like you mention then vitest works as expected. I think I got the wrong impression because mocking non-existent files works for non-variable dynamic imports. Is this a limitation of node?
Just to provide some additional context, I'm trying to mock functions which dynamically import entire directories of plugins, and would like to test these functions using a set of mocked plugins. but creating a distinct, empty file for my tests would be very brittle and fill the plugin folder with empty files.
file being mocked has to exist on the system
This is only true for imports with a dynamic name because Vite wraps this call with a function that checks for existing modules. If you just have await import('../a-b/index.ts'), then you can mock non-existing file.
I suppose then the title of this issue is misleading. It should read "Non-existent files cannot be mocked using variable dynamic imports, but can with non-variable dynamic imports". Would you like me to update the title?
And the followup question would be if this is caused by something in vite, is this really a bug, or would it be expected behaviour? It would mean we just wouldn't be able to write tests for our plugin system, but we do already have a work around by adding a small handful of fake plugins we've just hard coded to ignore.
Would you like me to update the title?
Yes, the title seems to be misleading
And the followup question would be if this is caused by something in vite, is this really a bug, or would it be expected behaviour?
I actually don't have an answer for this right now. Vite does this because it needs to analyze the bundle and know all the possible files. For Vitest it doesn't matter, but this code would've failed in production which Vitest can catch. If we patch Vite somehow, then this wouldn't work 🤔
And another fix, actually, is to use environment other than jsdom or happy-dom. Due to nature of this wrapper, it's not injected when running in non-browser environment.