0

I'm brand new to Vue Test Utils and struggling a bit with the documentation on testing v-model updates. I'm using vite and so I've decided to use vitest

I have an AutoComplete component with two slots input and results. The input slot is monitored for @keydown events. If the user has pressed a "special" key then this is captured and triggers a different action, but if they press a "normal" key then the input (and therefore the modelValue) should update accordingly.

A simplified version of my AutoComplete component:

<script setup>

import { ref, watchEffect, computed} from 'vue';

    // Props
    const props = defineProps({
        modelValue : {
            type: [String, null],
            required: true
        },
        autoCompleteConfigs : {
            type: Array,
            required: true,
        }
    });

    const emit = defineEmits(['selected','chosen','updated','update:modelValue']);

    ///

    const methods = {
        //when the user makes a selection
        onChosen :  (result) =>{
            ///
        },

        moveSelection: (x) =>{
            ///
        },

        // Event handler for keydown
        onKeydown : (event) => {

            //check if form select is active before passing through events
            if (query.value === null){
                return;
            }

            //check for special keys
            const passThruKeys = ['ArrowUp','ArrowDown','Tab','Enter','Delete'];

            if (passThruKeys.includes(event.key)) {
                event.preventDefault();

                //if user chooses current selection
                if (event.key === 'Enter' || event.key === 'Tab'){
                    methods.onChosen(searchResults.value[currentSelection.value])
                }

                //move selection up or down
                if (event.key === 'ArrowUp'){
                    methods.moveSelection(-1);
                }
                else if (event.key === 'ArrowDown'){
                    methods.moveSelection(1);
                }
            }
        }

    };

</script>

<template>


    <!-- input field for this slot-->
    <div>
        <slot name="input" @keydown="methods.onKeydown" ></slot>
    </div>

    <!-- Define how results will be displayed-->
    <div>
        <slot v-if="searchResults.length > 0" name="results" :results="searchResults" :indexSearched="currentSearchIndex" @chosen="methods.onChosen"></slot>
        
    </div>

</template>

My attempt at a first test:

import { mount} from "@vue/test-utils";
import AutoComplete from '@/Components/AutoComplete.vue'
import { describe, it, expect, vi} from "vitest";

//const useRemoteSearch = vi.fn(() => [])

describe("AutoComplete", () => {

    let wrapper;

    beforeEach(() => {
        wrapper = mount(AutoComplete, {
            props: {
                modelValue: 'Some text ',
                'onUpdate:modelValue': (e) => wrapper.setProps({ modelValue: e }),
                autoCompleteConfigs : [
                    {
                        trigger : '#',
                        index : 'tag',
                        autoComplete : 'tag'
                    },
                    {
                        trigger : '@',
                        index : 'user',
                        autoComplete : 'username'
                    }
                ],
            },
            slots: {
                input: `<input :value="modelValue" 
                         @keydown="onKeydown" 
                         id="message" 
                         @input="$emit(
                               'update:modelValue', 
                                $event.target.value
                         )"/>`,
            },
        });
    });

    it("should update model value", async() => {

        const input = wrapper.find('#message');

        input.setValue(wrapper.props().modelValue + "#h");

        await wrapper.vm.$nextTick();

        expect (wrapper.vm.query).toBe("h");

    });

});

///

The error message:

    TypeError: _ctx.$emit is not a function

1 Answer 1

0

Not really answer, but if I stop trying to update modelValue by updating the input field and juts update the modelValue directly then it works:

    it("should update query when there is a match with autoconfig", async () => {

        wrapper.setProps({ modelValue: wrapper.props().modelValue + "#h" })

        await wrapper.vm.$nextTick();

        expect (wrapper.vm.query).toBe("h");
    });
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.