vuejs3cypressvuexvue-test-utils

how to spy/stub a function and stub an action Vuex in the component vue3 composition api


my stack:

  1. cypress

  2. @vue/test-utils

  3. component in vue3 in composition api (<script setup />)

My test, i would like to spy a method inside a component, and spy action vuex inside a method in component.

myComponent

testView.vue

<template>
    <div class="test" @click="a()">test </test>
<template>
    <script setup>
    function a() {
        // logic 
        b()
    }
    function b() {
        // logic
        // launch dispatch in simple action in vuex
        dispatch('actionA')
    }
</script>


test.cy.js
describe('ClientView.vue', () => {
    it('test', async () => {
        const store = createStore({
            state() {
                return {
                    varA: null,
                }
            },
            actions: {
                actionA(context, newMessage) {
                    return Promise.resolve()
                },
            },
        })
        const mockRoute = createRouter({ history: createWebHistory(), routes: [] })
        mockRoute.currentRoute.value.name = 'testUrl'
        mockRoute.currentRoute.value.params = undefined
        const wrapper = mount(testView, {
            global: {
                mocks: {
                    $route: mockRoute,
                },
                plugins: [store, mockRoute]
            },
        })
        const spyA = cy.spy(wrapper.vm, 'a').as('a')
        const spyB = cy.spy(wrapper.vm, 'b').as('bSpy')
       

          // simulate click and launch function a()
          // I see in my log, the function A, b  and the action is called
         wrapper.find('test').trigger('click')
        expect(spyA ).to.be.called
        expect(spyB ).to.be.called
        expect(stubB ).to.be.called
       
    })
})






My errors

spyA is called ok

expected  spyB to have been called at least once, but it was never called
expected stubB to have been called at least once, but it was never called

My declaration of my spy and stub for b is not correct ? i don't understand why.

// If a modify my template

testView.vue

<template>
    <div class="test" @click="a()">test </test>
<template>
    <script setup>
    function a() {
        // logic 
        this.b()
    }
    function b() {
        // logic
        // launch dispatch in simple action in vuex
        dispatch('actionA')
    }
</script>

My test work ... but ... if i run my frontend 'this' is not autorize.

Error frontend

Uncaught TypeError: Cannot read properties of undefined (reading 'b')

Cypress has a problem with the version of vue3 in composition api ?


Solution

  • The spy code is correct and should work after // simulate click and launch function a(), so as mentioned it's likely the vm does not hold a reference to the functions.

    You can easily check if that's so with console.log(wrapper.vm.a), it should not be undefined for your spy to work.

    If it is undefined, you could spy on the internal functions by exposing them on the window object.

    Something like this:

    // component
    if (window.Cypress) {
      window.a = a
    }
    
    ...
    
    // test
    const spyA = cy.spy(window, 'a').as('a')