vitest icon indicating copy to clipboard operation
vitest copied to clipboard

Non-existent files cannot be mocked using variable dynamic imports, but can with non-variable dynamic imports

Open AustinGrey opened this issue 2 years ago • 8 comments

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

AustinGrey avatar Sep 21 '23 23:09 AustinGrey

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.

sheremet-va avatar Oct 02 '23 12:10 sheremet-va

Ok, I checked again - and it works even in stackblitz. Can you confirm that there is no problem?

sheremet-va avatar Oct 02 '23 12:10 sheremet-va

Hi, I checked again and I'm seeing this in my stackblitz reproduction still image

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 image

In stackblitz I tried to see if updating from vitest 0.34.5 to 0.35.6 would fix it, but same error

AustinGrey avatar Oct 04 '23 00:10 AustinGrey

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.

AustinGrey avatar Oct 04 '23 00:10 AustinGrey

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.

sheremet-va avatar Oct 04 '23 07:10 sheremet-va

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.

AustinGrey avatar Oct 06 '23 02:10 AustinGrey

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.

sheremet-va avatar Oct 06 '23 07:10 sheremet-va