test-utils icon indicating copy to clipboard operation
test-utils copied to clipboard

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

Open cadenzah opened this issue 1 year ago • 6 comments

Environment

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


  • Operating System: Linux
  • Node Version: v18.20.3
  • Nuxt Version: 3.12.2
  • CLI Version: 3.12.0
  • Nitro Version: 2.9.6
  • Package Manager: [email protected]
  • Builder: -
  • User Config: devtools
  • Runtime Modules: -
  • Build Modules: -

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

  • uses <script setup>
  • imports composable API from Nuxt #import (i.e. useRouter, useRoute, ...)

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 avatar Jun 25 '24 08:06 cadenzah

FYI @danielroe

cadenzah avatar Jun 25 '24 08:06 cadenzah

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.

dosubot[bot] avatar Jun 25 '24 08:06 dosubot[bot]

Is there any update on this? I'm getting a very similar error in my tests, and the workaround above does not seem feasible to be included in a simple test.

Aietes avatar Aug 15 '24 13:08 Aietes

I am running into the same issue. It's the only component/test running into this, despite all of them using <script setup lang="ts">.

<script lang="ts" setup>
const {
  label,
  error,
  helpText,
  id = 'input',
} = defineProps<{
  label?: string;
  error?: string;
  helpText?: string;
  id?: string;
}>();
const modelValue = defineModel<string | number>();
const attrs = useAttrs();
</script>

[Vue warn]: Cannot mutate <script setup> binding "error" from Options API.

ngajhede avatar Oct 17 '24 06:10 ngajhede

Possibly the same issue as #744? Any updates for this or that? @danielroe

cadenzah avatar Oct 18 '24 11:10 cadenzah

Related bug report: https://github.com/nuxt/test-utils/issues/986 I have triaged this and renderSuspended starts getting this issue from v13.14.0.

@ngajhede In your case it's breaking since you're using the prop name error.

oskarols avatar Oct 22 '24 14:10 oskarols

resolved in https://github.com/nuxt/test-utils/commit/4e9f34b96ac5432cc9429aadfa07c3503dffbf15

danielroe avatar Dec 05 '24 06:12 danielroe

@danielroe sorry to revive this, but even with 3.15.4 when I have a prop named results with mountSuspended I still get the warning

[Vue warn]: Cannot mutate

A prop named error seems to be working though.

sebbayer avatar Jan 30 '25 17:01 sebbayer

3.16.1 I'm getting this with a prop name error if I rename that, it works just fine

nandi95 avatar Apr 12 '25 06:04 nandi95