Skip to content

Commit fe21a93

Browse files
fix: allow mounting functional components (#118)
* fix: allow mounting functional components * Apply suggestions from code review Co-authored-by: Carlos Rodrigues <[email protected]> Co-authored-by: Carlos Rodrigues <[email protected]>
1 parent 3fa0a19 commit fe21a93

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

src/mount.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
VNodeNormalizedChildren,
77
transformVNodeArgs,
88
reactive,
9+
FunctionalComponent,
910
ComponentPublicInstance,
1011
ComponentOptionsWithObjectProps,
1112
ComponentOptionsWithArrayProps,
@@ -53,6 +54,11 @@ type ExtractComponent<T> = T extends { new (): infer PublicInstance }
5354
? PublicInstance
5455
: any
5556

57+
// Functional component
58+
export function mount<TestedComponent extends FunctionalComponent>(
59+
originalComponent: TestedComponent,
60+
options?: MountingOptions<any>
61+
): VueWrapper<ComponentPublicInstance>
5662
// Component declared with defineComponent
5763
export function mount<TestedComponent extends ComponentPublicInstance>(
5864
originalComponent: { new (): TestedComponent } & Component,
@@ -80,7 +86,14 @@ export function mount(
8086
originalComponent: any,
8187
options?: MountingOptions<any>
8288
): VueWrapper<any> {
83-
const component = { ...originalComponent }
89+
// normalise the incoming component
90+
const component =
91+
typeof originalComponent === 'function'
92+
? {
93+
setup: (_, { attrs, slots }) => () =>
94+
h(originalComponent, attrs, slots)
95+
}
96+
: { ...originalComponent }
8497

8598
const el = document.createElement('div')
8699
el.id = MOUNT_ELEMENT_ID

tests/functionalComponents.spec.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { mount } from '../src'
2+
import { h } from 'vue'
3+
import Hello from './components/Hello.vue'
4+
5+
describe('functionalComponents', () => {
6+
it('mounts a functional component', () => {
7+
const Foo = (props: { msg: string }) =>
8+
h('div', { class: 'foo' }, props.msg)
9+
10+
const wrapper = mount(Foo, {
11+
props: {
12+
msg: 'foo'
13+
}
14+
})
15+
16+
expect(wrapper.html()).toEqual('<div class="foo">foo</div>')
17+
})
18+
19+
it('renders the slots of a functional component', () => {
20+
const Foo = (props, { slots }) => h('div', { class: 'foo' }, slots)
21+
22+
const wrapper = mount(Foo, {
23+
slots: {
24+
default: 'just text'
25+
}
26+
})
27+
28+
expect(wrapper.html()).toEqual('<div class="foo">just text</div>')
29+
})
30+
31+
it('asserts classes', () => {
32+
const Foo = (props, { slots }) => h('div', { class: 'foo' }, slots)
33+
34+
const wrapper = mount(Foo, {
35+
attrs: {
36+
class: 'extra_classes'
37+
}
38+
})
39+
40+
expect(wrapper.classes()).toContain('extra_classes')
41+
expect(wrapper.classes()).toContain('foo')
42+
})
43+
44+
it('uses `find`', () => {
45+
const Foo = () => h('div', { class: 'foo' }, h(Hello))
46+
const wrapper = mount(Foo)
47+
48+
expect(wrapper.find('#root').exists()).toBe(true)
49+
})
50+
51+
it('uses `findComponent`', () => {
52+
const Foo = () => h('div', { class: 'foo' }, h(Hello))
53+
const wrapper = mount(Foo)
54+
55+
expect(wrapper.findComponent(Hello).exists()).toBe(true)
56+
})
57+
})

0 commit comments

Comments
 (0)