vue.jsunit-testingvuejs3ts-jestvue-script-setup

Jest unit test cannot find component functions when using Vue3 script setup syntax (wrapper.vm property does not exist on type)


I am starting to use Vue3's SFC script setup syntax: https://vuejs.org/api/sfc-script-setup.html

When I try to write unit tests for these components the Intellisense complains that the functions declared within these components do not exist.

The error is on the wrapper.vm

Property 'functionName' does not exist on type

My question is am I missing a package or tool that can resolve this issue?

I can cast the wrapper.vm as any to resolve the issue but it is not ideal...

I have added more details below:

test component test component unit test with error

I can run the unit test and it will pass successfully, however if I try to build the project I will receive an error.

test success build error

Here are some of the related packages in my package.json

"@vue/vue3-jest": "^27.0.0-alpha.4",
"jest": "^27.4.7",
"jest-serializer-vue": "^2.0.2",
"ts-jest": "^27.1.3",
"vite-jest": "^0.1.4",
"vue-jest": "^5.0.0-alpha.10",
"babel-jest": "^27.4.6",
"vue3-jest": "^27.0.0-alpha.1"
"vue": "^3.0.5",
"vue-tsc": "^0.28.7",
"vite": "^2.4.4",

Example component:

<script setup lang="ts">
const msg = 'Click me'
function click(): string {
  return 'clicked'
}
</script>

<template>
  <button @click="click">{{ msg }}</button>
</template>

Example test:

import { shallowMount } from '@vue/test-utils'

import Test from './Test.vue'

describe('Test', () => {
  const wrapper = shallowMount(Test)

  test('Component Renders', () => {
    expect(wrapper.exists()).toBeTruthy()
  })

  describe('click method', () => {
    test(`to return 'clicked'`, () => {
      expect(wrapper.vm.click()).toEqual('clicked')
    })
  })
})

Here is an example of casting the wrapper as any to resolve the issue but this is something I would like to avoid.

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const wrapper: any = shallowMount(Test)

enter image description here


Solution

  • <script setup> is closed by default, so click needs to be explicitly exposed with the defineExpose() macro:

    <script setup lang="ts">
    function click(): string {
      return 'clicked'
    }
       👇
    defineExpose({ click })
    </script>
    

    Exposing click also makes it available on the wrapper vm instance's type.