diff --git a/examples/app-vitest-full/components/ComponentWithReservedProp.vue b/examples/app-vitest-full/components/ComponentWithReservedProp.vue
new file mode 100644
index 000000000..de02fca8f
--- /dev/null
+++ b/examples/app-vitest-full/components/ComponentWithReservedProp.vue
@@ -0,0 +1,9 @@
+
+
+
+ {{ props.error }}
+
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 d9aa769be..cd047eaa2 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,7 @@ import ExportDefineComponent from '~/components/ExportDefineComponent.vue'
import ExportDefaultWithRenderComponent from '~/components/ExportDefaultWithRenderComponent.vue'
import ExportDefaultReturnsRenderComponent from '~/components/ExportDefaultReturnsRenderComponent.vue'
import OptionsApiPage from '~/pages/other/options-api.vue'
+import ComponentWithReservedProp from '~/components/ComponentWithReservedProp.vue'
import { BoundAttrs } from '#components'
import DirectiveComponent from '~/components/DirectiveComponent.vue'
@@ -123,6 +124,21 @@ describe('mountSuspended', () => {
expect(component.html()).toMatchInlineSnapshot(`"
"`)
})
+ it('can handle reserved words in component props', async () => {
+ const comp = await mountSuspended(ComponentWithReservedProp, {
+ props: {
+ error: '404',
+ },
+ })
+ const span = comp.find('span')
+ expect(span.text()).toBe('404')
+
+ await comp.setProps({
+ error: '500',
+ })
+ expect(span.text()).toBe('500')
+ })
+
describe('Options API', () => {
beforeEach(() => {
vi.spyOn(console, 'error').mockImplementation((message) => {
diff --git a/src/runtime-utils/mount.ts b/src/runtime-utils/mount.ts
index 919c860f4..0ce997e8b 100644
--- a/src/runtime-utils/mount.ts
+++ b/src/runtime-utils/mount.ts
@@ -66,10 +66,7 @@ export async function mountSuspended(
const setProps = reactive>({})
let passedProps: Record
- const wrappedSetup = async (
- props: Record,
- setupContext: SetupContext,
- ) => {
+ const wrappedSetup = async (props: Record, setupContext: SetupContext) => {
passedProps = props
if (setup) {
const result = await setup(props, setupContext)
@@ -131,12 +128,16 @@ export async function mountSuspended(
}
for (const key in setupState || {}) {
renderContext[key] = isReadonly(setupState[key]) ? unref(setupState[key]) : setupState[key]
+ if (key === 'props') {
+ renderContext[key] = cloneProps(renderContext[key] as Record)
+ }
}
+ const propsContext = 'props' in renderContext ? renderContext.props as Record : renderContext
for (const key in props || {}) {
- renderContext[key] = _ctx[key]
+ propsContext[key] = _ctx[key]
}
for (const key in passedProps || {}) {
- renderContext[key] = passedProps[key]
+ propsContext[key] = passedProps[key]
}
if (methods && typeof methods === 'object') {
for (const key in methods) {
@@ -196,3 +197,11 @@ const defuReplaceArray = createDefu((obj, key, value) => {
return true
}
})
+
+function cloneProps(props: Record) {
+ const newProps = reactive>({})
+ for (const key in props) {
+ newProps[key] = props[key]
+ }
+ return newProps
+}
diff --git a/src/runtime-utils/render.ts b/src/runtime-utils/render.ts
index b9ec3a5af..2126cb8e1 100644
--- a/src/runtime-utils/render.ts
+++ b/src/runtime-utils/render.ts
@@ -47,10 +47,7 @@ type SetupState = Record
* @param component the component to be tested
* @param options optional options to set up your component
*/
-export async function renderSuspended(
- component: T,
- options?: RenderOptions,
-) {
+export async function renderSuspended(component: T, options?: RenderOptions) {
const {
props = {},
attrs = {},
@@ -148,12 +145,16 @@ export async function renderSuspended(
}
for (const key in setupState || {}) {
renderContext[key] = isReadonly(setupState[key]) ? unref(setupState[key]) : setupState[key]
+ if (key === 'props') {
+ renderContext[key] = cloneProps(renderContext[key] as Record)
+ }
}
+ const propsContext = 'props' in renderContext ? renderContext.props as Record : renderContext
for (const key in props || {}) {
- renderContext[key] = _ctx[key]
+ propsContext[key] = _ctx[key]
}
for (const key in passedProps || {}) {
- renderContext[key] = passedProps[key]
+ propsContext[key] = passedProps[key]
}
if (methods && typeof methods === 'object') {
for (const key in methods) {
@@ -203,3 +204,11 @@ declare global {
interface AugmentedVueInstance {
setupState?: SetupState
}
+
+function cloneProps(props: Record) {
+ const newProps = reactive>({})
+ for (const key in props) {
+ newProps[key] = props[key]
+ }
+ return newProps
+}