我正在尝试在单元测试中触发Vuetify v-autocomplete
组件的“ input”事件。据我所知,单元测试与Vuetify guys are using十分相似,但是由于某种原因,从未调用过模拟方法。
factory方法仅返回通过mount
创建的组件实例,并添加本地存储,vue和vueLoading实例。
在这里我会很想见识,已经为此失去了几个小时,我开始有点生气...
Vuetify版本:1.4.3
组件
<template>
<v-autocomplete
:items="options"
:value="selectedId"
:label="label || $t('user.filter')"
:dark="dark"
:class="fieldClass"
:menu-props="{ contentClass }"
:loading="$loading.isLoading('fetch users')"
item-text="email"
item-value="id"
name="search_by_user"
hide-details
single-line
clearable
@input="updateValue($event)"
@click.native="fetchUsers"
/>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
props: {
value: {
type: String,
required: false,
default: null
},
label: {
type: String,
required: false,
default: null
},
dark: {
type: Boolean,
required: false,
default: true
},
fieldClass: {
type: String,
required: false,
default: 'select-user-search'
},
contentClass: {
type: String,
required: false,
default: 'user-search'
},
blankItem: {
type: Object,
required: false,
default: null
}
},
data () {
return {
selectedId: this.value
}
},
computed: {
...mapGetters(['users']),
options () { return this.blankItem ? [this.blankItem].concat(this.users) : this.users }
},
created () {
if (this.value) this.fetchUsers()
},
methods: {
fetchUsers () {
if (this.users.length) return
this.$store.dispatch('FETCH_USERS', {
fields: ['id', 'email'],
filter: { active: 'true' }
})
},
updateValue (value) {
this.selectedId = value
this.$emit('input', value)
}
}
}
</script>
<style>
.select-user-search {
overflow: hidden;
padding-bottom: 1px;
}
.select-user-search .v-select__selections {
overflow: hidden;
}
.select-user-search .v-select__selection {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
单元测试
import { mount, shallowMount, createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import VueLoading from 'vuex-loading'
import Vuetify from 'vuetify'
import UserSearch from 'manager/components/user/search.vue'
const factory = (values, shallow = true) => {
if (!shallow) {
return mount(UserSearch, { ...values })
}
return shallowMount(UserSearch, { ...values })
}
const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(VueLoading)
localVue.use(Vuetify)
describe('UserSearch', () => {
let actions, getters, store, vueLoading
beforeEach(() => {
actions = {
FETCH_USERS: jest.fn()
}
getters = {
users: () => []
}
vueLoading = new VueLoading({ useVuex: true })
store = new Vuex.Store({
actions,
getters
})
})
it('calls "updateValue" method when input triggered', async () => {
const methods = {
updateValue: jest.fn()
}
const wrapper = factory({ methods, store, localVue, vueLoading }, false)
const input = wrapper.find('input')
input.element.value = 'value'
input.trigger('input')
await wrapper.vm.$nextTick()
expect(methods['updateValue']).toBeCalledWith('value')
})
})
答案 0 :(得分:0)
我使用以下变体
组件
<template>
<span> <!-- span (or the other HTML element) around <v-autocomplete> is important -->
<v-autocomplete
:items="options"
:value="selectedId"
:label="$t('user.filter')"
:menu-props="{ contentClass }"
:loading="false"
item-text="email"
item-value="id"
name="search_by_user"
hide-details
single-line
clearable
@input="updateValue($event)"
@click.native="fetchUsers"
/>
</span>
</template>
<script lang="ts">
import { Component } from 'vue-property-decorator';
import Vue from 'vue';
@Component
export default class AppAutocomplete extends Vue {
private options: any[] = [{email: 'box1@gmail.com', id: 1}];
private selectedId: string|undefined = undefined;
private contentClass = 'user-search';
private fetchUsers() {
}
public updateValue(event: any) {
}
}
</script>
单元测试
import { Wrapper, createLocalVue, mount } from '@vue/test-utils';
import Vue from 'vue';
import Vuetify from 'vuetify';
// @ts-ignore
import AppAutocomplete from '@/components/AppAutocomplete.vue';
describe('AppAutocomplete', () => {
Vue.use(Vuetify);
let wrapper: Wrapper<Vue>;
let vm: any;
beforeEach(() => {
wrapper = mount(AppAutocomplete, {
localVue: createLocalVue(),
vuetify: new Vuetify({
mocks: { $vuetify: { lang: { t: (val: string) => val } } },
}),
mocks: { $t: () => { /** */ } },
});
vm = wrapper.vm;
});
afterEach(() => wrapper.destroy());
it(`calls "updateValue" method when input triggered`, () => {
jest.spyOn(vm, 'updateValue');
const autocompleteElem = wrapper.find('.v-autocomplete');
autocompleteElem.vm.$emit('input', 'box1');
expect(vm.updateValue).toBeCalledTimes(1);
expect(vm.updateValue).toHaveBeenCalledWith('box1');
});
});
用其他HTML元素包围v-autocomplete很重要。没有它,测试将失败。
Vuetify版本:2.1.12