Skip to content

Commit 042f935

Browse files
committed
wip: class component support
1 parent 1380114 commit 042f935

File tree

3 files changed

+123
-13
lines changed

3 files changed

+123
-13
lines changed

src/utils.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,13 @@ export const mergeDeep = (
6666
}
6767

6868
export function isClassComponent(component: any) {
69-
return '__vccBase' in component
69+
// TypeScript
70+
return (
71+
component.toString().includes('_super.apply(this, arguments) || this') ||
72+
// native ES6
73+
(typeof component === 'function' &&
74+
/^\s*class\s+/.test(component.toString()))
75+
)
7076
}
7177

7278
export function isFunctionalComponent(component: any) {

tests/components/ClassComponent.vue

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<template>
2+
<div class="hello">
3+
<h1>{{ computedMsg }}</h1>
4+
<button @click="changeMessage('Hello')" />
5+
</div>
6+
</template>
7+
8+
<script lang="ts">
9+
import { Options, Vue } from 'vue-class-component'
10+
@Options({
11+
props: {
12+
msg: String
13+
}
14+
})
15+
export default class ClassComponent extends Vue {
16+
dataText: string
17+
get computedMsg(): string {
18+
return `Message: ${(this.$props as any).msg}`
19+
}
20+
21+
changeMessage(text: string): void {
22+
this.dataText = text
23+
}
24+
}
25+
</script>

tests/features/classComponent.spec.ts

Lines changed: 91 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,102 @@ import 'reflect-metadata'
22
import { h } from 'vue'
33
import { Options, Vue } from 'vue-class-component'
44
import { mount } from '../../src'
5+
import ClassComponent from '../components/ClassComponent.vue'
56

6-
test('data: $props should be available', () => {
7-
@Options({
8-
props: ['foo']
7+
describe('class component', () => {
8+
it('minimal class component', () => {
9+
class Foo extends Vue {
10+
render() {
11+
return h('span')
12+
}
13+
}
14+
const wrapper = mount(Foo)
15+
expect(wrapper.find('span').exists()).toBe(true)
916
})
10-
class MyComp extends Vue {
11-
message = 'answer is ' + (this.$props as any).foo
12-
render() {
13-
return h('div', this.message)
17+
18+
it('data: $props should be available', () => {
19+
@Options({
20+
props: ['foo']
21+
})
22+
class MyComp extends Vue {
23+
message = 'answer is ' + (this.$props as any).foo
24+
render() {
25+
return h('div', this.message)
26+
}
1427
}
15-
}
1628

17-
const wrapper = mount(MyComp, {
18-
props: {
19-
foo: 42
29+
const wrapper = mount(MyComp, {
30+
props: {
31+
foo: 42
32+
}
33+
})
34+
35+
expect(wrapper.html()).toBe('<div>answer is 42</div>')
36+
})
37+
38+
it('hooks', () => {
39+
let created = false
40+
class MyComp extends Vue {
41+
created() {
42+
created = true
43+
}
44+
render() {
45+
return h('div')
46+
}
2047
}
48+
mount(MyComp)
49+
expect(created).toBe(true)
2150
})
2251

23-
expect(wrapper.html()).toBe('<div>answer is 42</div>')
52+
it('methods', () => {
53+
let msg: string = ''
54+
55+
class MyComp extends Vue {
56+
hello() {
57+
msg = 'hi'
58+
}
59+
content() {
60+
return 'content'
61+
}
62+
render() {
63+
return h('div', this.content())
64+
}
65+
}
66+
67+
const wrapper = mount(MyComp)
68+
wrapper.vm.hello()
69+
expect(wrapper.html()).toBe('<div>content</div>')
70+
expect(msg).toBe('hi')
71+
})
72+
73+
it('computed', () => {
74+
class MyComp extends Vue {
75+
a!: number
76+
data() {
77+
return {
78+
a: 1
79+
}
80+
}
81+
get b() {
82+
return this.a + 1
83+
}
84+
render() {
85+
return h('div')
86+
}
87+
}
88+
89+
const wrapper = mount(MyComp)
90+
expect(wrapper.vm.a).toBe(1)
91+
expect(wrapper.vm.b).toBe(2)
92+
wrapper.vm.a = 2
93+
expect(wrapper.vm.b).toBe(3)
94+
})
95+
96+
it('works with shallow mount and SFC', async () => {
97+
const wrapper = mount(ClassComponent, {
98+
shallow: true
99+
})
100+
await wrapper.get('button').trigger('click')
101+
expect(wrapper.get('h1').text()).toMatch('Hello')
102+
})
24103
})

0 commit comments

Comments
 (0)