nuxt / test-utils

🧪 Test utilities for Nuxt
http://nuxt.com/docs/getting-started/testing
MIT License
323 stars 84 forks source link

Vitest with `@nuxt/test-utils-edge` doesn't load SCSS import in monorepo with error: `TypeError: render is not a function` #352

Closed mrauhu closed 1 year ago

mrauhu commented 2 years ago

Environment

Reproduction

How to recreate

  1. Open a link.
  2. Wait for a development server is start and the Nuxt Welcome page is loaded.
  3. Press Ctrl + C in Terminal.
  4. Run npm test.

https://stackblitz.com/edit/github-owtwqh-hjptpo?file=packages%2Fapp%2Fsrc%2Fapp.vue,packages%2Fapp%2Fsrc%2Fassets%2Fstyles%2Findex.scss,packages%2Fapp%2Ftests%2Fapp.spec.ts

Describe the bug

Vitest with @nuxt/test-utils-edge doesn't work with SCSS imports in Vue files, if a Nuxt application is a package in the monorepo.

Additional context

If rootDir property of the test setup() function is not the project root directory with node_modules, then SASS render() function can't be found, because rootDir will be used as root directory by Vite CSS plugin:

https://github.com/vitejs/vite/blob/0765ab812f410d5b925a742419ea2b1586b0da23/packages/vite/src/node/plugins/css.ts#L1413

const render = loadPreprocessor(PreprocessLang.sass, root).render

https://github.com/vitejs/vite/blob/0765ab812f410d5b925a742419ea2b1586b0da23/packages/vite/src/node/utils.ts#L908

export const requireResolveFromRootWithFallback = (
  root: string,
  id: string
): string => {
  // Search in the root directory first, and fallback to the default require paths.
  const fallbackPaths = _require.resolve.paths?.(id) || []
  const path = _require.resolve(id, {
    paths: [root, ...fallbackPaths]
  })
  return path
}

Logs

TypeError: render is not a function ```shell ERROR TypeError: render is not a function 02:36:45 ❯ result ../../node_modules/vite/dist/node/chunks/dep-0fc8e132.js:42791:13 02:36:45 ❯ scss ../../node_modules/vite/dist/node/chunks/dep-0fc8e132.js:42790:30 02:36:45 ❯ compileCSS ../../node_modules/vite/dist/node/chunks/dep-0fc8e132.js:42336:34 02:36:45 ❯ Object.transform ../../node_modules/vite/dist/node/chunks/dep-0fc8e132.js:41917:55 ❯ transform ../../node_modules/vite/node_modules/rollup/dist/es/shared/rollup.js:21941:16 ❯ ModuleLoader.addModuleSource ../../node_modules/vite/node_modules/rollup/dist/es/shared/rollup.js:22166:30 02:36:45 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { 02:36:45 "code": "PLUGIN_ERROR", "frame": undefined, "hook": "transform", "id": "/home/projects/github-owtwqh-hjptpo/packages/app/src/assets/styles/index.scss", "plugin": "vite:css", "watchFiles": [ "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/entry.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/vue/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/ohmyfetch/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/vue/dist/vue.runtime.esm-bundler.js", "/home/projects/github-owtwqh-hjptpo/node_modules/ohmyfetch/dist/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/index.mjs", "virtual:nuxt:/home/projects/github-owtwqh-hjptpo/packages/app/.nuxt/4krzpx/paths.mjs", "virtual:nuxt:/home/projects/github-owtwqh-hjptpo/packages/app/.nuxt/4krzpx/css.mjs", "virtual:nuxt:/home/projects/github-owtwqh-hjptpo/packages/app/.nuxt/4krzpx/plugins/client.mjs", "virtual:nuxt:/home/projects/github-owtwqh-hjptpo/packages/app/.nuxt/4krzpx/root-component.mjs", "virtual:nuxt:/home/projects/github-owtwqh-hjptpo/packages/app/.nuxt/4krzpx/app-component.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/ufo/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/ufo/dist/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/head/runtime/lib/vueuse-head.plugin.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/head/runtime/plugin.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/plugins/router.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/components/nuxt-root.vue", "/home/projects/github-owtwqh-hjptpo/packages/app/src/app.vue", "virtual:nuxt:/home/projects/github-owtwqh-hjptpo/packages/app/.nuxt/4krzpx/components.plugin.mjs", "virtual:nuxt:/home/projects/github-owtwqh-hjptpo/packages/app/.nuxt/4krzpx/nitro.client.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/runtime-dom/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/destr/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/@vueuse/head/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/defu/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/h3/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js", "vite/preload-helper", "/home/projects/github-owtwqh-hjptpo/node_modules/ohmyfetch/dist/chunks/fetch.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/destr/dist/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/nuxt.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/components/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/@vueuse/head/dist/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/defu/dist/defu.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/head/runtime/components.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/head/runtime/composables.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/h3/dist/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/head/runtime/index.mjs", "virtual:nuxt:/home/projects/github-owtwqh-hjptpo/packages/app/.nuxt/4krzpx/meta.config.mjs", "virtual:nuxt:/home/projects/github-owtwqh-hjptpo/packages/app/.nuxt/4krzpx/middleware.mjs", "virtual:nuxt:/home/projects/github-owtwqh-hjptpo/packages/app/.nuxt/4krzpx/error-component.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/components/nuxt-error-page.vue", "/home/projects/github-owtwqh-hjptpo/node_modules/hookable/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/unctx/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/shared/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/radix3/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/cookie-es/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/runtime-core/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/shared/dist/shared.esm-bundler.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@nuxt/ui-templates/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/hookable/dist/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/unctx/dist/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/component.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/asyncData.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/hydrate.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/state.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/error.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/fetch.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/cookie.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/ssr.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/router.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/components/nuxt-link.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/radix3/dist/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/cookie-es/dist/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/@nuxt/ui-templates/dist/templates/error-404.vue", "/home/projects/github-owtwqh-hjptpo/node_modules/@nuxt/ui-templates/dist/templates/error-dev.vue", "/home/projects/github-owtwqh-hjptpo/node_modules/@nuxt/ui-templates/dist/templates/error-500.vue", "/home/projects/github-owtwqh-hjptpo/node_modules/vue-router/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/ohash/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/reactivity/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js", "plugin-vue:export-helper", "/home/projects/github-owtwqh-hjptpo/node_modules/vue-router/dist/vue-router.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/nuxt/dist/app/composables/utils.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/ohash/dist/index.mjs", "/home/projects/github-owtwqh-hjptpo/node_modules/@nuxt/ui-templates/dist/templates/error-404.vue?vue&type=style&index=0&scoped=e0e1cf8f&lang.css", "/home/projects/github-owtwqh-hjptpo/node_modules/@nuxt/ui-templates/dist/templates/error-dev.vue?vue&type=style&index=0&scoped=0d86080f&lang.css", "/home/projects/github-owtwqh-hjptpo/node_modules/@nuxt/ui-templates/dist/templates/error-500.vue?vue&type=style&index=0&scoped=9880db5c&lang.css", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/package.json", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/index.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/env.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/const.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/proxy.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/api/index.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/plugin.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/time.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/api/api.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/api/app.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/api/component.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/api/context.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/api/hooks.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@vue/devtools-api/lib/esm/api/util.js", "/home/projects/github-owtwqh-hjptpo/node_modules/@nuxt/ui-templates/dist/templates/welcome.vue", "/home/projects/github-owtwqh-hjptpo/packages/app/src/app.vue?vue&type=script&lang.ts", "/home/projects/github-owtwqh-hjptpo/node_modules/@nuxt/ui-templates/dist/templates/welcome.vue?vue&type=style&index=0&scoped=e70f2a14&lang.css", "/home/projects/github-owtwqh-hjptpo/packages/app/src/assets/styles/index.scss", ], } ERROR ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯ Test Files 1 failed (1) 02:36:45 Tests (1) 02:36:45 Start at 02:36:34 02:36:45 Duration 11.20s (transform 387ms, setup 0ms, collect 536ms, tests 7.43s) 02:36:45 02:36:45 ```
pyncz commented 2 years ago

As I can see, the problem is not related to monorepos themselves. A regular app also may face such issue (here's reproduction).

But! It's probably related to the happy-dom. Everything will be fine if you install jsdom instead (and use it as vitest's environment ofc). Check fix/jsdom-as-env branch of the reproduction repo above.

Not very happy dom tho.

danielroe commented 1 year ago

Note, when you are using a <script> block without setup then you must provide a default export.

I've updated your reproduction here: https://stackblitz.com/edit/github-owtwqh-bgq2fp.

Note that there does seem to be an issue with nuxi test when running in the root directory - I've raised https://github.com/nuxt/cli/pull/284 to address that.