How to initialise Vuelidate 2.0.0 when testing a Vue component with Vitest?
Asked Answered
P

2

10

In my Vue 2.7.14 app I'm using Vuelidate 2.0.0. I'm trying to migrate a test from Jest to Vitest, but the v$ object is not initialised correctly in the latter case. The component has a checkbox bound to formData.accepted

  validations () {
    return {
      formData: {
        accepted: {
          required,
          sameAs: sameAs(true)
        }
      }
    }
  }

Vuelidate is initialised within the component as per the docs

  setup () {
    return {
      v$: useVuelidate({ $autoDirty: true })
    }
  },

When I run the following test under Jest, it passes

  it('click save button', async () => {
    const wrapper = mount(MyComponent)

    expect(wrapper.vm.v$.formData.accepted.$invalid).toBeTruthy()
    await wrapper.find('[data-cy="accept-checkbox"]').trigger('click')
    expect(wrapper.vm.v$.formData.accepted.$invalid).toBeFalsy()
  })

However, if I run the same test using Vitest it fails because wrapper.vm.v$.formData is undefined because v$ is initialised to:

v$ {
  "$dirty": false,
  "$path": "__root",
  "$model": null,
  "$error": false,
  "$errors": [],
  "$invalid": false,
  "$anyDirty": false,
  "$pending": false,
  "$silentErrors": [],
  "$validationGroups": {}
}

By contrast, when the Jest test is run, $silentErrors is not empty, and the following property path is (obviously) valid

v$.formData.accepted.$invalid 

What should I do to ensure that v$ is initialised correctly when the test is run with Vitest?

Photosynthesis answered 8/12, 2022 at 17:20 Comment(2)
Were you able to find a solution here? I'm seeing the same issue with no clear work-around.Drivein
@Drivein yes, I'm not sure which version of Vitest I was using when I ran into this issue, but I tried again with a later version and the problem just magically disappeared.Hardenberg
C
-1

First try:

You need to assign a const to the wrapper:

  it('click save button', async () => {
    const wrapper = mount(MyComponent)
    const { $v } = wrapper.vm;

    expect(wrapper.vm.v$.formData.accepted.$invalid).toBeTruthy()
    await wrapper.find('[data-cy="accept-checkbox"]').trigger('click')
    expect(wrapper.vm.v$.formData.accepted.$invalid).toBeFalsy()
  })

Further try:

I think you are also missing the import of validationMixin in your test file to use the $v object:

import { validationMixin } from 'vuelidate';

After that change your component to this:

export default {
  mixins: [validationMixin],
  setup () {
    return {
      v$: useVuelidate()
    }
}

Glad about feedback if it worked and if not we'll get there. :)

Contrapuntist answered 12/12, 2022 at 22:3 Comment(4)
Alright, I just read your new answer. I'll take a look after work again if it's fine for youContrapuntist
The code in your "First try" suggestion is functionally identical to the code I'm already using (which doesn't work). The only difference is the addition of an unused $v variableHardenberg
I appreciate your effort, but your answer assumes I'm using Vuelidate 0.X, but I'm actually using 2.0, which has a very different API e.g. the validationMixin you mention no longer exists vuelidate-next.netlify.app/…Hardenberg
I already know that v$ is not initialised correctly, the very point of my question is to find out how to fix this problem. By the way, in Vuelidate 2.0, it's recommended you use v$ rather than $v vuelidate-next.netlify.app/migration_guide.html#v-instead-of-vHardenberg
I
-1

To initialise Vuelidate when testing a Vue component with Vitest you can use the following approach:

1. Add the following line to your test file:

import Vuelidate from 'vuelidate';

2. Use Vuelidate in your test like so:

it('click save button', async () => {

const wrapper = mount(MyComponent)

const v = Vuelidate.instance()

expect(v.formData.accepted.$invalid).toBeTruthy()

await wrapper.find('[data-cy="accept-checkbox"]').trigger('click')

expect(v.formData.accepted.$invalid).toBeFalsy()

})

3. Make sure that Vuelidate is initialised correctly within your Vue component like so:

v$: useVuelidate({

$autoDirty: true

})
Irisirisa answered 18/12, 2022 at 15:34 Comment(1)
Your proposed import import Vuelidate from 'vuelidate'; is invalid in Vuelidate 2.0Hardenberg

© 2022 - 2024 — McMap. All rights reserved.