vuejs3vitestformkit

How can I perform basic testing with FormKit and Vue/Vite?


I'm trying to figure out how to test a basic FormKit form using Vue and Vite. The form has a text field and a button. If you enter text and then click the button, it should display in another field on the screen the text you entered.

In the test, I can enter in text and can see that the button is clicked, but the text field is empty and therefore I don't see what was entered on the screen. What am I missing? I'm going in circles trying things and haven't found many examples in my searches. thanks!

Here is my basic form:

<template>
<div class="ml-6 mt-6">
  <h2>Basic Form</h2>
  <FormKit type="form" id="myform" v-model="myform" :actions="false">
    <FormKit
      type="text"
      name="name"
      id="name"
      label="Name:"
      help="Your full name"
      placeholder="“Jon Doe”"
    />
    <div class="mt-6 mb-6">
      <FormKit
        type="button"
        name="clickme"
        data-testid="clickme"
        label="Click Me"
        help="This will show what you entered."
        @click="displayName"
      />
    </div>
  </FormKit>
  <div class="mt-4">
    <p>Entered Name: {{ enteredName }}</p>
  </div>
</div>
</template>

<script setup>
import { ref } from 'vue';

const myform = ref();
let enteredName = ref('');

function displayName()
{
  console.log('button clicked');
  enteredName.value = myform.value.name;
  console.log('form value: ' + JSON.stringify(myform.value));
  console.log('Entered Name: ' + enteredName.value);
}
</script>

here is my test:

import { mount} from '@vue/test-utils';
import { beforeEach, describe, it, expect } from 'vitest';
import BasicForm from '../components/BasicForm.vue';
import { plugin, defaultConfig } from "@formkit/vue";

describe('BasicForm.vue', () => {
  let wrapper = null;
  beforeEach(() => {
        // render the component
        wrapper = mount(BasicForm, {
      attachTo: document.getElementById('app'),
            props: {
            },
            global: {
                plugins: [
                    [plugin, defaultConfig],
                ],
            },
        });
  });

  it('displays the entered name when the button is clicked', async () => {
    // Find the input and set its value
    const input = wrapper.find('input[name="name"]');
    console.log('input= ' + JSON.stringify(input));
    await input.setValue('Joe Doe');
    console.log('input= ' + JSON.stringify(input));

    // Find the button and trigger a click event
    const button = await wrapper.find('[data-testid="clickme"]');
    console.log('button= ' + JSON.stringify(button));
    await button.trigger('click');
    await wrapper.vm.$nextTick();

    // Assert that the entered name is displayed
    // expect(wrapper.vm.enteredName).toBe('Joe Doe');
    expect(wrapper.text()).toContain('Entered Name: Joe Doe');
  });
});

Here is the test result: test result


Solution

  • In order to get the "click" to work, you'll have to natively call the "click" event on the FormKit element.

    Before:

    await button.trigger('click');
    

    After:

    button.element.dispatchEvent(new Event('click'));
    

    For some reason, we have to manually trigger the click event for FormKit to respond in the testing environment.