Skip to content

Commit 4eb66e0

Browse files
committed
Merge branch 'main' into fix/reactive-teleport
# Conflicts: # src/vnodeTransformers/util.ts
2 parents cc9639d + b94a0ae commit 4eb66e0

File tree

10 files changed

+126
-18
lines changed

10 files changed

+126
-18
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ assignees: ''
1515

1616
**To Reproduce**
1717
<!-- A link to a minimal reproduction (with the minimum code to reproduce the issue).
18-
It takes just a few minutes to build a repro online with https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/vue?initialPath=__vitest__
18+
It takes just a few minutes to build a repro online with https://stackblitz.com/github/vuejs/create-vue-templates/tree/main/typescript-vitest?file=src%2Fcomponents%2F__tests__%2FHelloWorld.spec.ts
1919
-->
2020

2121
**Expected behavior**

docs/.vitepress/config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ export default defineConfig({
106106
}
107107
]
108108
},
109+
{
110+
text: 'FAQ',
111+
link: '/guide/faq/'
112+
},
109113
{
110114
text: 'Migrating from Vue 2',
111115
link: '/migration/'
@@ -214,6 +218,10 @@ export default defineConfig({
214218
}
215219
]
216220
},
221+
{
222+
text: 'FAQ',
223+
link: '/guide/faq/'
224+
},
217225
{
218226
text: 'Migrating from Vue 2',
219227
link: '/migration/'

docs/fr/.vitepress/locale-config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ const frLocaleConfig: DefaultTheme.LocaleConfig & Omit<DefaultTheme.Config, "loc
66
nav: [
77
{ text: 'Guide', link: '/fr/guide/' },
88
{ text: 'API', link: '/fr/api/' },
9+
{
10+
text: 'FAQ',
11+
link: '/fr/guide/faq/'
12+
},
913
{ text: 'Migrer depuis Vue 2', link: '/fr/migration/' },
1014
{
1115
text: 'Journal de modifications',
@@ -86,6 +90,10 @@ const frLocaleConfig: DefaultTheme.LocaleConfig & Omit<DefaultTheme.Config, "loc
8690
}
8791
]
8892
},
93+
{
94+
text: 'FAQ',
95+
link: '/fr/guide/faq/'
96+
},
8997
{
9098
text: 'Migrer depuis Vue 2',
9199
link: '/fr/migration/'

docs/fr/guide/faq/index.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# FAQ
2+
3+
[[toc]]
4+
5+
## Vue warn: Failed setting prop
6+
7+
```
8+
[Vue warn]: Failed setting prop "prefix" on <component-stub>: value foo is invalid.
9+
TypeError: Cannot set property prefix of #<Element> which has only a getter
10+
```
11+
12+
Cet avertissement est affiché si vous utilisez `shallowMount` ou `stubs` avec une propriété dont le nom est celui de l'une des propriétés de [`Element`](https://developer.mozilla.org/fr-FR/docs/Web/API/Element).
13+
14+
Parmi les noms de propriétés courants partagés avec `Element` figurent&nbsp;:
15+
* `attributes`
16+
* `children`
17+
* `prefix`
18+
19+
Voir https://developer.mozilla.org/en-US/docs/Web/API/Element
20+
21+
**Solutions possibles**
22+
23+
1. Utilisez `mount` au lieu de `shallowMount` pour rendre le composant sans utiliser de `stubs`
24+
2. Ignorez l'avertissement en utilisant un mock pour `console.warn`
25+
3. Renommez la propriété du composant pour éviter les conflits avec les propriétés de `Element`

docs/guide/faq/index.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# FAQ
2+
3+
[[toc]]
4+
5+
## Vue warn: Failed setting prop
6+
7+
```
8+
[Vue warn]: Failed setting prop "prefix" on <component-stub>: value foo is invalid.
9+
TypeError: Cannot set property prefix of #<Element> which has only a getter
10+
```
11+
12+
This warning is shown in case you are using `shallowMount` or `stubs` with a property name that is shared with [`Element`](https://developer.mozilla.org/en-US/docs/Web/API/Element).
13+
14+
Common property names that are shared with `Element`:
15+
* `attributes`
16+
* `children`
17+
* `prefix`
18+
19+
See: https://developer.mozilla.org/en-US/docs/Web/API/Element
20+
21+
**Possible solutions**
22+
23+
1. Use `mount` instead of `shallowMount` to render without stubs
24+
2. Ignore the warning by mocking `console.warn`
25+
3. Rename the prop to not clash with `Element` properties

src/createInstance.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ export function createInstance(
307307
// stub out Transition and Transition Group by default.
308308
transformVNodeArgs(
309309
createVNodeTransformer({
310+
rootComponents,
310311
transformers: [
311312
createStubComponentsTransformer({
312313
rootComponents,

src/vnodeTransformers/stubComponentsTransformer.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { isKeepAlive, isTeleport, VTUVNodeTypeTransformer } from './util'
1+
import {
2+
isKeepAlive,
3+
isRootComponent,
4+
isTeleport,
5+
VTUVNodeTypeTransformer
6+
} from './util'
27
import {
38
Transition,
49
TransitionGroup,
@@ -177,14 +182,8 @@ export function createStubComponentsTransformer({
177182
})
178183
}
179184

180-
if (
181-
// Don't stub VTU_ROOT component
182-
!instance ||
183-
// Don't stub mounted component on root level
184-
(rootComponents.component === type && !instance?.parent) ||
185-
// Don't stub component with compat wrapper
186-
(rootComponents.functional && rootComponents.functional === type)
187-
) {
185+
// Don't stub root components
186+
if (isRootComponent(rootComponents, type, instance)) {
188187
return type
189188
}
190189

src/vnodeTransformers/util.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { isComponent } from '../utils'
22
import { registerStub } from '../stubs'
3-
import { ConcreteComponent, transformVNodeArgs } from 'vue'
3+
import { Component, ConcreteComponent, transformVNodeArgs } from 'vue'
44

55
type VNodeArgsTransformerFn = NonNullable<
66
Parameters<typeof transformVNodeArgs>[0]
@@ -23,9 +23,30 @@ export type VTUVNodeTypeTransformer = (
2323
export const isTeleport = (type: any): boolean => type.__isTeleport
2424
export const isKeepAlive = (type: any): boolean => type.__isKeepAlive
2525

26+
export interface RootComponents {
27+
// Component which has been passed to mount. For functional components it contains a wrapper
28+
component?: Component
29+
// If component is functional then contains the original component otherwise empty
30+
functional?: Component
31+
}
32+
export const isRootComponent = (
33+
rootComponents: RootComponents,
34+
type: VNodeTransformerInputComponentType,
35+
instance: InstanceArgsType
36+
): boolean =>
37+
!!(
38+
!instance ||
39+
// Don't stub mounted component on root level
40+
(rootComponents.component === type && !instance?.parent) ||
41+
// Don't stub component with compat wrapper
42+
(rootComponents.functional && rootComponents.functional === type)
43+
)
44+
2645
export const createVNodeTransformer = ({
46+
rootComponents,
2747
transformers
2848
}: {
49+
rootComponents: RootComponents
2950
transformers: VTUVNodeTypeTransformer[]
3051
}): VNodeArgsTransformerFn => {
3152
const transformationCache: WeakMap<
@@ -40,17 +61,19 @@ export const createVNodeTransformer = ({
4061
return [originalType, props, children, ...restVNodeArgs]
4162
}
4263

64+
const componentType: VNodeTransformerInputComponentType = originalType
65+
4366
const cachedTransformation = transformationCache.get(originalType)
4467
if (
4568
cachedTransformation &&
69+
// Don't use cache for root component, as it could use stubbed recursive component
70+
!isRootComponent(rootComponents, componentType, instance) &&
4671
!isTeleport(originalType) &&
4772
!isKeepAlive(originalType)
4873
) {
4974
return [cachedTransformation, props, children, ...restVNodeArgs]
5075
}
5176

52-
const componentType: VNodeTransformerInputComponentType = originalType
53-
5477
const transformedType = transformers.reduce(
5578
(type, transformer) => transformer(type, instance),
5679
componentType
Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
<template>
22
<div>
3+
<h2>{{ name }}</h2>
34
<Hello />
4-
<RecursiveComponent v-if="first" />
5+
<template
6+
v-for="item in items"
7+
:key="item"
8+
>
9+
<RecursiveComponent
10+
:name="item"
11+
/>
12+
</template>
513
</div>
614
</template>
715

816
<script setup lang="ts">
917
import Hello from './Hello.vue'
1018
1119
defineProps<{
12-
first?: boolean
20+
name: string
21+
items?: string[]
1322
}>()
1423
</script>

tests/shallowMount.spec.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,29 @@ describe('shallowMount', () => {
7474
)
7575
})
7676

77-
it('stub instance of same component', () => {
77+
it('stub instance of same component', async () => {
7878
const wrapper = mount(RecursiveComponent, {
7979
shallow: true,
8080
props: {
81-
first: true
81+
name: '1',
82+
items: ['2']
8283
}
8384
})
8485
expect(wrapper.html()).toEqual(
8586
'<div>\n' +
87+
' <h2>1</h2>\n' +
8688
' <hello-stub></hello-stub>\n' +
87-
' <recursive-component-stub first="false"></recursive-component-stub>\n' +
89+
' <recursive-component-stub name="2"></recursive-component-stub>\n' +
8890
'</div>'
8991
)
92+
93+
expect(wrapper.find('h2').text()).toBe('1')
94+
95+
await wrapper.setProps({
96+
name: '3'
97+
})
98+
99+
expect(wrapper.find('h2').text()).toBe('3')
90100
})
91101

92102
it('correctly renders slot content', () => {

0 commit comments

Comments
 (0)