nuxt / test-utils

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

Using `mountSuspended()` with a component using `<script setup>` and `#import` makes an error #871

Open cadenzah opened 4 days ago

cadenzah commented 4 days ago

Environment

Working directory: /home/projects/jvmibwmjx.github Nuxt project info:


Reproduction

https://stackblitz.com/edit/github-mmtufx?file=app.vue

Describe the bug

Let's say there is a root component which I want to mount using @nuxt/test-utils's mountSuspended() API. If this component

it makes an error below and breaks entire test.

stdout | createSuspenseBoundary (/home/projects/jvmibwmjx.github/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:1451:43)
<Suspense> is an experimental feature and its API will likely change.

stderr | warn$1 (/home/projects/jvmibwmjx.github/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:50:13)
[Vue warn]: Cannot mutate <script setup> binding "useRouter" from Options API. 
  at <MountSuspendedComponent > 
  at <MountSuspendedHelper> 
  at <Anonymous ref="VTU_COMPONENT" > 
  at <VTUROOT>
[Vue warn]: Unhandled error during execution of render function 
  at <MountSuspendedComponent > 
  at <MountSuspendedHelper> 
  at <Anonymous ref="VTU_COMPONENT" > 
  at <VTUROOT>

Only if the root component meets the condition above, the issue occurs. As you see in the reproduction, if you use #imports and <script setup> in child elements it work fine.

The app itself is built and works fine if I run it.

You can reproduce the issue with the repository link above.

Additional context

No response

Logs

No response

cadenzah commented 4 days ago

FYI @danielroe

dosubot[bot] commented 4 days ago

To resolve the issue with mountSuspended() when using a root component with <script setup> and #import for composable APIs from Nuxt, you need to ensure that the setup function is properly wrapped and executed within the Nuxt environment. Here are the steps to address this:

  1. Wrap the setup function: Ensure that the setup function is properly wrapped to handle the Nuxt environment.

  2. Initialize the Nuxt environment: Make sure the Nuxt environment is correctly initialized before running your tests.

Here is an example of how you can achieve this:

import { mountSuspended } from '@nuxt/test-utils'
import { defineNuxtComponent, tryUseNuxtApp } from '#app'
import { h } from 'vue'

const wrappedSetup = async (props, setupContext) => {
  let setupState = {}
  if (setup) {
    const result = await setup(props, setupContext)
    setupState = result && typeof result === 'object' ? result : {}
    return result
  }
}

const vueApp = tryUseNuxtApp()?.vueApp || globalThis.__unctx__.get('nuxt-app').tryUse().vueApp

const wrapper = await mountSuspended(defineNuxtComponent({
  setup: wrappedSetup,
  render: () => h('div', 'hi there'),
}))

expect(wrapper.html()).toMatchInlineSnapshot('"<div>hi there</div>"')

This code ensures that the setup function is properly handled and the Nuxt environment is correctly initialized. Additionally, you can refer to the test/nuxt/composables.test.ts file for more examples on how to test various composables within the Nuxt environment [1][2].

If you are still encountering issues, ensure that your component and its dependencies are correctly set up and that the Nuxt environment is properly initialized before running your tests.

@danielroe, this one's a bit out of my wheelhouse, could you step in and provide your guidance?

To continue talking to Dosu, mention @dosu.