Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

regression: import can't be found in v0.23.0 #1978

Closed
6 tasks done
cexbrayat opened this issue Sep 5, 2022 · 11 comments · Fixed by #1979
Closed
6 tasks done

regression: import can't be found in v0.23.0 #1978

cexbrayat opened this issue Sep 5, 2022 · 11 comments · Fixed by #1979

Comments

@cexbrayat
Copy link
Contributor

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

@sheremet-va
Copy link
Member

sheremet-va commented Sep 5, 2022

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?

if (type !== 'Object' && type !== 'Module')

@sheremet-va
Copy link
Member

sheremet-va commented Sep 5, 2022

So, the problem was actually this line:

const constructor = sourceModule.constructor?.name

@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/compat@3.2.38/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:

const tryDefault = this.hasNestedDefault(mod)

@cexbrayat
Copy link
Contributor Author

@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)

@sheremet-va
Copy link
Member

@cexbrayat I will make PR to fix this on Vitest side, and open issue to improve @vue/compat.

@cexbrayat
Copy link
Contributor Author

@sheremet-va You're the best, thanks!

@cexbrayat
Copy link
Contributor Author

@sheremet-va sadly, it looks like v0.23.1 does not fix the issue. See vuejs/test-utils#1757

@cexbrayat
Copy link
Contributor Author

For anyone interested, the upstream issue is vuejs/core#6602

@cexbrayat
Copy link
Contributor Author

The upstream issue is supposed to be fixed but the error persists with Vue v3.2.40 and Vitest v0.23.4

@cexbrayat
Copy link
Contributor Author

@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?

@sheremet-va
Copy link
Member

sheremet-va commented Oct 19, 2022

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/compat to @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.

cexbrayat added a commit to cexbrayat/vue-test-utils-next that referenced this issue Oct 20, 2022
We were blocked by vitest-dev/vitest#1978
but thanks to @sheremet-va help (see vitest-dev/vitest#1978 (comment))
we now have a way to use the latest vitest releases.

It turns out that we needed to:
- alias `@vue/compat` to its ESM bundle
- use `Vue.extend` instead of `extend` in the `compat.spec.ts` file, as `extend` is not a named export
cexbrayat added a commit to vuejs/test-utils that referenced this issue Oct 20, 2022
We were blocked by vitest-dev/vitest#1978
but thanks to @sheremet-va help (see vitest-dev/vitest#1978 (comment))
we now have a way to use the latest vitest releases.

It turns out that we needed to:
- alias `@vue/compat` to its ESM bundle
- use `Vue.extend` instead of `extend` in the `compat.spec.ts` file, as `extend` is not a named export
@cexbrayat
Copy link
Contributor Author

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.

@github-actions github-actions bot locked and limited conversation to collaborators Jun 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants