vue-jest icon indicating copy to clipboard operation
vue-jest copied to clipboard

Support Nuxt3 Auto-Imports

Open xxSkyy opened this issue 3 years ago • 19 comments

Nuxt 3 provides auto import for script-setup for composable functions (not only)

Info about: https://www.storyblok.com/mp/nuxt3-best-features

Example: https://codesandbox.io/s/dazzling-butterfly-7eo67

It'd be great to support it, for now it throws errors like ReferenceError: ref is not defined if you won't import it manually

xxSkyy avatar Dec 19 '21 17:12 xxSkyy

Is this still an issue? It might be working since many fixes landed in @vue/vue3-jest.

lmiller1990 avatar May 17 '22 23:05 lmiller1990

@lmiller1990 It is. with latest jest packages and @vue/vue3-jest I'm still receiving errors like ReferenceError: computed is not defined if it's not imported in component.

xxSkyy avatar May 19 '22 10:05 xxSkyy

For #1 - does Nuxt auto import ref, computed etc? In the post it says

If you're familiar with

What does it refer to when it says "any of the composable functions that Nuxt 3 brings to you"? I thought this means things inside of composables - not raw Vue reactivity APIs (could be wrong, I haven't used Nuxt 3 much).

I looked at your example #2 link - looks like a regular Nuxt starter? What should I be seeing?

Either way, any form of Nuxt magic is going to be a problem. We might need to sync with the Nuxt team - I don't think Test Utils should attempt to replicate Nuxt, rather, we should find out what they are doing to register things and see if we can hook into it, so we can get any changes they make for free.

lmiller1990 avatar May 20 '22 02:05 lmiller1990

Any news on this ??

MatthD avatar Nov 03 '22 13:11 MatthD

We need to find out how Nuxt does this and see if they can share the code that auto injects. Vue Jest just converts code to work with Jest; it doesn't know about things like Nuxt auto injections, etc.

Another thing you could try is simply import the functions, in the meantime.

Someone should file an issue in the Nuxt repo and link it to this issue, we need to work with Nuxt team to solve this.

lmiller1990 avatar Nov 04 '22 01:11 lmiller1990

ref and computed are not handled by the nuxt auto-importer. They are handled by the vue SFC compiler. These should work and are supported by vue-jest.

https://github.com/vuejs/core/blob/f67bb500b6071bc0e55a89709a495a27da73badd/packages/compiler-sfc/src/compileScript.ts#L216 https://github.com/vuejs/core/blob/f67bb500b6071bc0e55a89709a495a27da73badd/packages/reactivity-transform/src/reactivityTransform.ts

Regarding the Nuxt feature, Auto import is implemented as Nuxt plugin, but that is unrelated to the vue script setup syntactic sugar that is used for computed and ref.

See here. https://github.com/nuxt/framework/blob/6d830c7629c516dbb37c252863144f18192b9237/packages/nuxt/src/imports/module.ts#L83

I imagine vitest already supports the ability to load the Nuxt plugins. It is recommended by Nuxt.

https://v3.nuxtjs.org/getting-started/testing/

I think Nuxt should develop a transformer if they intend to support Nuxt plugins with jest. They claim to support jest, but perhaps the support is incomplete.

I think @xxSkyy misidentified the problem. Is @MatthD having the same issue with computed and ref?

jolting avatar Nov 04 '22 17:11 jolting

Recently I've tested Vitest with Nuxt 3 and with some configuration auto-import works great.

xxSkyy avatar Nov 05 '22 14:11 xxSkyy

@xxSkyy That's really nice to here, can you share some info around "some configuration"? What did you need to do?

Maybe we can do something similar here?

lmiller1990 avatar Nov 07 '22 02:11 lmiller1990

@lmiller1990 sure, overall I've used unplugin-auto-import. Here's my vitest.config.ts

import { defineConfig } from "vitest/config"
import Vue from "@vitejs/plugin-vue"
import AutoImport from "unplugin-auto-import/vite"

export default defineConfig({
  plugins: [
    Vue(),
    AutoImport({
      imports: [
        "vue",
        // could add 'vue-router' or 'vitest', whatever else you need.
      ],
    }),
  ],
  test: {
    globals: true,
    environment: "jsdom",
    deps: {
      inline: [/@nuxt\/test-utils-edge/],
    },
  },
})

This plugin has wide variety of compatible environments so probably there are possibility that you can benefit from it. For sure it doesn't solve everything, like if component uses useNuxtApp to get some plugin in it it has to be mocked, but I believe overall it's enough, and can be expanded by other deps you have.

xxSkyy avatar Nov 07 '22 09:11 xxSkyy

Right, I see, it probably just injects the entire Vue API globally. Bit of a hack, shame there isn't a way to access "the guts" of Nuxt and do whatever they do 1:1. Maybe in the future, we can.

For vue-jest, I guess we have a few options.

  1. Userland hack. I wonder if something like this would work:
beforeEach(() => {
  global.computed = vue.computed
})

Eg, inject all the things manually.

If that cannot be made to work, Vue Jest could expose something:

// jest.config.js
export default {
  global: {
    'vue-jest': {
      inject: {
        computed: vue.computed
      }
    }
  }
}

Just some ideas, userland work around would be best, since we don't want to re-create functionality here if we can avoid it.

I still think the best solution is to collab with Nuxt, if someone wants to open an issue there to investigate, that would be great. That said, for new projects, Vite is the default, so it seems less likely people want to use Jest with Nuxt 3.

lmiller1990 avatar Nov 07 '22 22:11 lmiller1990

@xxSkyy I'm trying this in a Nuxt3 app and I get

// cypress.config.ts

import { defineConfig } from 'cypress'
import vue from '@vitejs/plugin-vue'
import AutoImport from "unplugin-auto-import/vite"

export default defineConfig({
  "component": {
    "devServer": {
      "framework": "vue",
      "bundler": "vite",
      "viteConfig": {
        "plugins": [vue(), AutoImport()],
        test: {
          globals: true,
          deps: {
            inline: ['/@nuxt\/test-utils-edge/']
          }
        }
      }
    }
  }
})

Yields a TypeError: (0 , vite_1.default) is not a function error as soon as I add AutoImport() to the array.

speg avatar Nov 10 '22 02:11 speg

@lmiller1990 it should be possible to load the unplugins and apply the transformers

jolting avatar Nov 10 '22 02:11 jolting

Is there a list of things we'd need to handle? From what I've gathered

  • $nuxt global
  • component auto import*
  • composable auto import*

Could not see this specifically in their docs, maybe I need to read more.

lmiller1990 avatar Nov 10 '22 02:11 lmiller1990

@speg I didn't test it with cypress so I'm not sure. Blind guess - maybe update your vite. Here you have my example configured repo with nuxt3 and vitest working https://gitlab.com/xxSkyy/nuxt3-vitest-example

xxSkyy avatar Nov 10 '22 10:11 xxSkyy

~Is there any news on this? I can add the vue imports using the AutoImport plugin but it would be nice to have a way to also include the components, composables, utils etc.~

Update: nvm you can use the dir field on the AutoImport options

gbyesiltas avatar May 16 '23 15:05 gbyesiltas

@gbyesiltas https://github.com/danielroe/nuxt-vitest

dsvgl avatar May 16 '23 16:05 dsvgl

@gbyesiltas https://github.com/danielroe/nuxt-vitest

@dsvgl Thanks! It does work, though it runs the whole nuxt environment with the plugins etc. which is a bit concerning for our project where we have our unit tests more isolated

gbyesiltas avatar May 19 '23 07:05 gbyesiltas

Recently I've tested Vitest with Nuxt 3 and with some configuration auto-import works great.

can you share? Currently started with. Nuxt3, Vitest & Pinia. Keep hitting walls. Mainly with Nuxt things like useRoute not being found by the test unless we import useRoute in that component.

v3nt avatar Sep 20 '23 14:09 v3nt

@lmiller1990 sure, overall I've used unplugin-auto-import. Here's my vitest.config.ts

import { defineConfig } from "vitest/config"
import Vue from "@vitejs/plugin-vue"
import AutoImport from "unplugin-auto-import/vite"

export default defineConfig({
  plugins: [
    Vue(),
    AutoImport({
      imports: [
        "vue",
        // could add 'vue-router' or 'vitest', whatever else you need.
      ],
    }),
  ],
  test: {
    globals: true,
    environment: "jsdom",
    deps: {
      inline: [/@nuxt\/test-utils-edge/],
    },
  },
})

This plugin has wide variety of compatible environments so probably there are possibility that you can benefit from it. For sure it doesn't solve everything, like if component uses useNuxtApp to get some plugin in it it has to be mocked, but I believe overall it's enough, and can be expanded by other deps you have.

Thank you, your solution helped me, I am still running into a problem with Composables, vitest is angry at them unless explicitly import them into each component under test, any ideas how to solve it?

vitest.config.ts so far:

`import vue from "@vitejs/plugin-vue"; import { defineProject, mergeConfig } from "vitest/config"; import baseConfig from "../vitest.base"; import AutoImport from "unplugin-auto-import/vite";

export default mergeConfig( baseConfig, defineProject({ plugins: [ vue({ template: { compilerOptions: { isCustomElement: (tag) => { return tag.startsWith("v-"); }, }, }, }), AutoImport({ imports: ["vue"], }), ],

server: {
  host: "0.0.0.0",
},
test: {
  globals: true,
  environment: "jsdom",
},

}), );`

Vittorio-QA avatar Feb 12 '24 20:02 Vittorio-QA