diff --git a/src/mount.ts b/src/mount.ts index 97b84104fc..127f5b0734 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -8,7 +8,8 @@ import { Plugin, Directive, Component, - reactive + reactive, + ComponentPublicInstance } from 'vue' import { createWrapper } from './vue-wrapper' @@ -37,7 +38,10 @@ interface MountingOptions { stubs?: Record } -export function mount(originalComponent: any, options?: MountingOptions) { +export function mount( + originalComponent: new () => T, + options?: MountingOptions +) { const component = { ...originalComponent } // Reset the document.body @@ -63,7 +67,10 @@ export function mount(originalComponent: any, options?: MountingOptions) { // override component data with mounting options data if (options?.data) { const dataMixin = createDataMixin(options.data()) - component.mixins = [...(component.mixins || []), dataMixin] + ;(component as any).mixins = [ + ...((component as any).mixins || []), + dataMixin + ] } // we define props as reactive so that way when we update them with `setProps` @@ -136,5 +143,5 @@ export function mount(originalComponent: any, options?: MountingOptions) { // mount the app! const app = vm.mount(el) - return createWrapper(app, events, setProps) + return createWrapper(app, events, setProps) } diff --git a/src/vue-wrapper.ts b/src/vue-wrapper.ts index e0f28b8639..4b22a33ac6 100644 --- a/src/vue-wrapper.ts +++ b/src/vue-wrapper.ts @@ -6,8 +6,9 @@ import { WrapperAPI } from './types' import { ErrorWrapper } from './error-wrapper' import { MOUNT_ELEMENT_ID } from './constants' -export class VueWrapper implements WrapperAPI { - private componentVM: ComponentPublicInstance +export class VueWrapper + implements WrapperAPI { + private componentVM: T private __emitted: Record = {} private __vm: ComponentPublicInstance private __setProps: (props: Record) => void @@ -19,7 +20,7 @@ export class VueWrapper implements WrapperAPI { ) { this.__vm = vm this.__setProps = setProps - this.componentVM = this.vm.$refs['VTU_COMPONENT'] as ComponentPublicInstance + this.componentVM = this.__vm.$refs['VTU_COMPONENT'] as T this.__emitted = events } @@ -41,8 +42,8 @@ export class VueWrapper implements WrapperAPI { return this.hasMultipleRoots ? this.parentElement : this.componentVM.$el } - get vm(): ComponentPublicInstance { - return this.__vm + get vm(): T { + return this.componentVM } classes(className?: string) { @@ -104,10 +105,10 @@ export class VueWrapper implements WrapperAPI { } } -export function createWrapper( +export function createWrapper( vm: ComponentPublicInstance, events: Record, setProps: (props: Record) => void -): VueWrapper { - return new VueWrapper(vm, events, setProps) +): VueWrapper { + return new VueWrapper(vm, events, setProps) } diff --git a/tests/vm.spec.ts b/tests/vm.spec.ts new file mode 100644 index 0000000000..2613b3f0bd --- /dev/null +++ b/tests/vm.spec.ts @@ -0,0 +1,26 @@ +import { defineComponent, ref } from 'vue' + +import { mount } from '../src' + +describe('vm', () => { + it('returns the component vm', () => { + const Component = defineComponent({ + template: '
{{ msg }}
', + setup() { + const msg = 'hello' + const isEnabled = ref(true) + const toggle = () => (isEnabled.value = !isEnabled.value) + return { msg, isEnabled, toggle } + } + }) + + const wrapper = mount(Component) + + expect(wrapper.vm.msg).toBe('hello') + expect(wrapper.vm.isEnabled).toBe(true) + + wrapper.vm.toggle() + + expect(wrapper.vm.isEnabled).toBe(false) + }) +})