diff --git a/examples/app-vitest-full/components/BoundAttrs.vue b/examples/app-vitest-full/components/BoundAttrs.vue new file mode 100644 index 000000000..da98db79f --- /dev/null +++ b/examples/app-vitest-full/components/BoundAttrs.vue @@ -0,0 +1,23 @@ + + + diff --git a/examples/app-vitest-full/tests/nuxt/mount-suspended.spec.ts b/examples/app-vitest-full/tests/nuxt/mount-suspended.spec.ts index e599ddeb7..e8341656d 100644 --- a/examples/app-vitest-full/tests/nuxt/mount-suspended.spec.ts +++ b/examples/app-vitest-full/tests/nuxt/mount-suspended.spec.ts @@ -14,6 +14,8 @@ import ExportDefineComponent from '~/components/ExportDefineComponent.vue' import ExportDefaultWithRenderComponent from '~/components/ExportDefaultWithRenderComponent.vue' import ExportDefaultReturnsRenderComponent from '~/components/ExportDefaultReturnsRenderComponent.vue' +import { BoundAttrs } from '#components' + const formats = { ExportDefaultComponent, ExportDefineComponent, @@ -32,6 +34,13 @@ describe('mountSuspended', () => { `) }) + it('should handle passing setup state and props to template', async () => { + const wrappedComponent = await mountSuspended(BoundAttrs) + const component = mount(BoundAttrs) + + expect(component.html()).toEqual(wrappedComponent.html()) + }) + it('should work with shallow mounting within suspense', async () => { const component = await mountSuspended(App, { shallow: true }) expect(component.html()).toMatchInlineSnapshot(` diff --git a/src/runtime-utils/mount.ts b/src/runtime-utils/mount.ts index 87d5d4626..f1adb03ef 100644 --- a/src/runtime-utils/mount.ts +++ b/src/runtime-utils/mount.ts @@ -1,6 +1,6 @@ import { mount } from '@vue/test-utils' import type { ComponentMountingOptions } from '@vue/test-utils' -import { Suspense, h, nextTick } from 'vue' +import { Suspense, h, nextTick, isReadonly } from 'vue' import type { DefineComponent, SetupContext } from 'vue' import { defu } from 'defu' import type { RouteLocationRaw } from 'vue-router' @@ -60,10 +60,12 @@ export async function mountSuspended( let setupContext: SetupContext let setupState: any + let passedProps: Record const wrappedSetup = async ( props: Record, setupContext: SetupContext ) => { + passedProps = props if (setup) { setupState = await setup(props, setupContext) return setupState @@ -105,11 +107,14 @@ export async function mountSuspended( ...component, render: render ? function (this: any, _ctx: any, ...args: any[]) { + for (const key in setupState || {}) { + renderContext[key] = isReadonly(setupState[key]) ? unref(setupState[key]) : setupState[key] + } for (const key in props || {}) { renderContext[key] = _ctx[key] } - for (const key in setupState || {}) { - renderContext[key] = setupState[key] + for (const key in passedProps || {}) { + renderContext[key] = passedProps[key] } return render.call(this, renderContext, ...args) }