regression: import can't be found in v0.23.0
Describe the bug
I tried to reproduce in isolation but I couldn't, sorry.
In VTU, we have a test that mocks vue to use @vue/compat instead
https://github.com/vuejs/test-utils/blob/main/tests/features/compat.spec.ts#L5
This test fails with vitest v0.23.0, whereas it works with v0.22.1.
It complains the defineComponent (a function exposed by vue and vue/compat) is not a function.
FAIL tests/features/compat.spec.ts [ tests/features/compat.spec.ts ]
TypeError: defineComponent is not a function
❯ src/components/RouterLinkStub.ts:18:30
16|
17| // TODO: Borrow typings from vue-router-next
18| export const RouterLinkStub = defineComponent({
| ^
19| name: 'RouterLinkStub',
20|
❯ async /home/runner/work/test-utils/test-utils/src/index.ts:11:31
❯ async /home/runner/work/test-utils/test-utils/tests/features/compat.spec.ts:7:31
Reproduction
The Renovate PR is showcasing the error
https://github.com/vuejs/test-utils/runs/8177607839?check_suite_focus=true
System Info
System:
OS: macOS 12.5
CPU: (10) arm64 Apple M1 Max
Memory: 9.64 GB / 64.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.17.0 - ~/.volta/tools/image/node/16.17.0/bin/node
Yarn: 1.22.17 - ~/.volta/tools/image/yarn/1.22.17/bin/yarn
npm: 8.19.1 - ~/.volta/tools/image/npm/8.19.1/bin/npm
Browsers:
Chrome: 105.0.5195.52
Firefox: 103.0.2
Safari: 15.6
npmPackages:
@vitejs/plugin-vue: 3.0.3 => 3.0.3
@vitejs/plugin-vue-jsx: 2.0.0 => 2.0.0
vite: 3.0.9 => 3.0.9
vitest: 0.23.0 => 0.23.0
Used Package Manager
pnpm
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.
Wow, it's not even possible to run @vue/compat in Node without inlining it 😞 Did Vue team consider making it compatible with Node by bundling .mjs and using exports field? That way you wouldn't even need to inline it. Adding another index.mjs would be great for performance:
{
"exports": {
"*": {
"development": "./index.dev.mjs"
"import": "./index.mjs",
"require": "./index.js"
},
}
}
// index.mjs
export * from './dist/vue.esm.js'
Anyway, I guess the problem might be somewhere in #1944, since we made exports in CJS a bit stricter now. Maybe exports is not primitive object?
https://github.com/vitest-dev/vitest/blob/a98c845487298ecc59226e1cb2543eeada376c9c/packages/vite-node/src/client.ts#L408
So, the problem was actually this line:
https://github.com/vitest-dev/vitest/blob/a98c845487298ecc59226e1cb2543eeada376c9c/packages/vite-node/src/client.ts#L411
@vue/compat exports a compatVue instance, so it's available only on default export.
To be honest, I think this should be fixed on Vue side. Instead of extending Vue it should put named exports on exports: https://unpkg.com/browse/@vue/[email protected]/dist/vue.cjs.js#L13272 (this will work in Vitest, but won't work in Node tho 😛 )
Although we do have interopDefault for external modules:
https://github.com/vitest-dev/vitest/blob/a98c845487298ecc59226e1cb2543eeada376c9c/packages/vite-node/src/client.ts#L364
@sheremet-va Thanks for looking into this 🙏
To be honest I don't really get all these subtleties. Do you think this is something fixable in vitest so v0.23 works as v0.22?
I guess we can open an issue/PR on vue/compat side, but:
- I don't feel qualified to explain the what and why
- I don't think we can hope for a quick merge and release (even if I can try to fast-track it, Evan is currently busy IRL)
@cexbrayat I will make PR to fix this on Vitest side, and open issue to improve @vue/compat.
@sheremet-va You're the best, thanks!
@sheremet-va sadly, it looks like v0.23.1 does not fix the issue. See https://github.com/vuejs/test-utils/pull/1757
For anyone interested, the upstream issue is https://github.com/vuejs/core/issues/6602
The upstream issue is supposed to be fixed but the error persists with Vue v3.2.40 and Vitest v0.23.4
@sheremet-va The issue is still there with v0.24.2
Do you have an idea of what we can do now that Vue lists the cjs dependencies for the compat build? Is it something that needs to be fixed on Vue side or on Vitest side?
Vitest behaves like Node would behave in this scenario. If you run this in Node, it will output the same module that Node would:
import * as mockVue from '@vue/compat'
console.log(mockVue)
To work correctly, @vue/compat should expose an exports field with correct pointer to a ESM module (using .mjs extension). You can also bypass it:
- Add
resolve.mainFields: ['module']to your Vitest config - OR alias
@vue/compatto@vue/compat/dist/vue.esm-bundler.js
This will actually throw an error, because vue-compat doesn't export named extend function, but I don't know why you augment it in your local types, it's only available on default.
Thanks for your help @sheremet-va 🙏
I used the alias and Vue.Extend and was able to use the latest vitest release.
Let's close this, thanks again for looking into it.