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