2

I'm having a difficult time mocking a composable inside of a component.

Looking to see if a function from the composable was called after a button was clicked.

The composable is quite simple:

export default function useForm() {
  const form = ref({})
  const submit = () => {
    console.log('submit this amazing form')
  }

  return {
    form,
    submit,
  }
}

The component is also quite simple:

<template>
  <form>
      <input v-model="form.name" type="text" />
      <button class="submit-button" @click="submit">Submit</button>
  </form>
</template>

<script setup>
import useForm from '@/composable/useForm'

const { form, submit } = useForm()
</script>

Now lets test!

Component.spec.js:

import { mount } from '@vue/test-utils'
import Component from '@/component/Component.vue'

vi.mock('@/composables/useForm.js', async (importOriginal) => {
  const composable = await importOriginal()
  return {
    ...composable,
    submit: vi.fn(),
  }
})

describe('Component', () => {
  let wrapper

  beforeEach(() => {
    wrapper = mount(Component)
  })

  it('should call submit function when button is clicked', async () => {
    await wrapper.find('button.submit-button').trigger('click')

    const spy = vi.spyOn(wrapper.vm, 'submit')
    expect(spy).toHaveBeenCalled() // This does not work
  })
})

I don't need to call the function, just determine that it was called. The wrapper object doesn't seem to have the submit available and the mock doesn't seem to help.

Any help would be appreciated.


EDIT:

I did get something to work with doMock:

import { mount } from '@vue/test-utils'
import BaseForm from '../BaseForm.vue'

describe('BaseForm', () => {
  it('submits form', async () => {
    vi.doMock('../../composables/useForm.ts', () => ({
      submit: vi.fn()
    }))

    const wrapper = mount(BaseForm, {})
    const spy = vi.spyOn(wrapper.vm, 'submit')

    await wrapper.find('button').trigger('click')

    expect(spy).toHaveBeenCalled()
  })
})

It seems that submit is now part of the Components (I'm going to say the wrong thing here) 'structure' and now can be referenced with wrapper.vm.

0

1 Answer 1

1

You're importing from

'@/composable/useForm'

but mocking

'@/composables/useForm.js'
//          👆

A good rule of thumb for named (non relative) imports is to copy/paste the import path into the mock:

vi.mock('@/composable/useForm', async (original) => ({
  ...(await original()),
  submit: vi.fn()
})
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.