测试包装的 vuetify 自动完成组件 v 菜单未在 html 中打开
Posted
技术标签:
【中文标题】测试包装的 vuetify 自动完成组件 v 菜单未在 html 中打开【英文标题】:Testing a wrapped vuetify autocomplete component v menu does not open in html 【发布时间】:2021-09-15 05:45:26 【问题描述】:我想通过vue-test-utils 测试我的自定义组件。在这种情况下,我使用 vuetify autocomplete 组件。我只是用 div 包装并提取为自定义组件。到目前为止没有什么特别的。
这个组件确实在开发中工作。我没有问题。
我使用这个组件如下图。
<my-component
id="brand-dropdown"
ref="brand-dropdown"
:items="brands"
labelKey="product.brand"
item-text="name"
item-value="name"
v-model="product.brandName"/>
我的自定义组件如下所示:
<template>
<div class="comboContainer">
<v-autocomplete
class="product-combobox"
ref="complete"
:items="localItems"
append-icon="$dropdownArrow"
outlined
dense
hide-details
color="#999999"
:item-text="itemText"
:item-value="itemValue"
:filter="autoCompleteFilter"
v-model="selected"
@change="onListItemSelected">
<template slot="label">
<span>$t(labelKey)</span>
</template>
<template slot="prepend-inner" v-if="showSearchIcon">
<div class="d-flex align-center justify-center"
style="height: 25px;">
<img src="~/assets/icons/search/search.png"/>
</div>
</template>
<template v-slot:no-data>
<v-list-item id="noMatchText">
<v-list-item-title>
<div :no-data-item="dataTestId">
$t('selection.noMatchFound')
</div>
</v-list-item-title>
</v-list-item>
</template>
<template v-slot:item=" item ">
<v-tooltip top color="transparent">
<template v-slot:activator=" on, attrs ">
<div
v-on="item[itemText].length >36?on:null"
class="combobox-item comboboxOverFlow"
:data-testid="itemDataTestIdPrefix+item.id"
:parent-list="dataTestId">
<span> item[itemText] </span>
</div>
</template>
<div class="popup-rectangle">
<span> item[itemText] </span>
</div>
</v-tooltip>
</template>
</v-autocomplete>
</div>
</template>
<script>
export default
props:
items:
type: Array,
default: [],
,
labelKey:
type: String,
default: '',
,
itemText:
type: String,
default: '',
,
itemValue:
type: String,
default: '',
,
value:
type: [Number, String, Array],
,
disabled:
type: Boolean,
default: false,
shouldTriggerWatch:
type: Boolean,
default: false,
,
data()
return
selected: this.value,
showSearchIcon: false,
;
,
watch:
value:
immediate: true,
handler(val)
if (this.shouldTriggerWatch)
this.selected = val;
this.$emit('input', this.selected);
,
,
,
computed:
localItems()
if (this.items && this.items.length)
return this.items.map(x => (
...x,
displayName: x.lang_key ? this.$t(x.lang_key) : x.name,
));
return [];
,
,
methods:
onListItemSelected()
this.$emit('input', this.selected);
,
autoCompleteFilter(item, queryText, itemText)
const re = new RegExp(`(\\s+|^)($queryText.toLocaleLowerCase())(.*|$)`);
return re.test(itemText.toLocaleLowerCase());
,
,
;
我要测试三个测试用例。
-
当我传递空列表时,应呈现为空下拉列表并呈现无数据槽。
<template v-slot:no-data>
<v-list-item id="noMatchText">
<v-list-item-title>
<div :no-data-item="dataTestId">
$t('selection.noMatchFound')
</div>
</v-list-item-title>
</v-list-item>
</template>
-
当我通过带有测试数据的填充列表时,我想测试正确呈现的所有项目
<template v-slot:item=" item ">
<v-tooltip top color="transparent">
<template v-slot:activator=" on, attrs ">
<div
v-on="item[itemText].length >36?on:null"
class="combobox-item comboboxOverFlow"
:data-testid="itemDataTestIdPrefix+item.id"
:parent-list="dataTestId">
<span> item[itemText] </span>
</div>
</template>
<div class="popup-rectangle">
<span> item[itemText] </span>
</div>
</v-tooltip>
</template>
-
当我搜索时,我想提供我的过滤功能按预期工作。并且自动完成会根据过滤后的值呈现项目。
这是我的测试文件。
function mountComponent(options)
return mount(ComboBox,
vuetify: new Vuetify(),
sync: false,
mocks:
$t: key => key,
$i18n: locale: 'en' ,
,
...options,
);
describe('Combobox unit tests', () =>
beforeEach(() =>
document.body.setAttribute('data-app', 'true');
);
test('should create component successfully', () =>
const wrapper = mountComponent( items: [] );
expect(wrapper.exists()).toBeTruthy();
);
test('should list zero items if the item list is empty', async () =>
const wrapper = mountComponent(
propsData:
items: [],
labelKey: 'labelKey',
dataTestId: 'test-dropdown',
itemText: 'name',
itemValue: 'id',
,
);
const autocomplete = wrapper.find('.product-combobox');
const autocompleteControls = autocomplete.find('.v-input__slot');
autocompleteControls.trigger('click');
await wrapper.vm.$nextTick();
await flushPromises();
**// v menu cant opened !!!!**
);
test('should list third items correctly', async () =>
const testItems = [ name: 'item1', id: 1 , name: 'item2', id: 2 , name: 'item3', id: 3 ];
const wrapper = mountComponent(
attachToDocument: true,
propsData:
eagerProp: true,
items: testItems,
dataTestId: 'test-dropdown',
itemDataTestIdPrefix: 'test-dropdown-item-',
itemText: 'name',
itemValue: 'id',
value: null,
,
);
const slot = wrapper.find('.v-input__slot');
const input = wrapper.find('input');
// Focus input should only focus
input.trigger('focus');
expect(wrapper.vm.$children[0].isFocused).toBe(true);
expect(wrapper.vm.$children[0].menuCanShow).toBe(true);
expect(wrapper.vm.$children[0].isMenuActive).toBe(false);
slot.trigger('click');
expect(wrapper.vm.$children[0].isMenuActive).toBe(true);
expect(wrapper.vm.$children[0].menuCanShow).toBe(true);
wrapper.setProps( searchInput: 'foo' );
expect(wrapper.vm.$children[0].isMenuActive).toBe(true);
expect(wrapper.vm.$children[0].menuCanShow).toBe(true);
// v menu cant opened !!!!
// you think these expects is unnecesary. you are right I just explore this component
// if I success I'll delete all of them
);
test('should filter autocomplete search results', async () =>
);
);
我无法在测试环境中打开 v-menu。
我尝试发出事件并触发('click')
当我控制台日志wrapper.html()
时,我看不到 v 菜单已打开并且所有项目都以 html 呈现。输出如下所示。
<div class="comboContainer">
<div class="v-input product-combobox v-input--hide-details v-input--dense theme--light v-text-field v-text-field--enclosed v-text-field--outlined v-select v-autocomplete">
<div class="v-input__control">
<div role="combobox" aria-haspopup="listbox" aria-expanded="false" aria-owns="list-2" class="v-input__slot" style="height: 44px;">
<fieldset aria-hidden="true">
<legend style="width: 0px;"><span></span></legend>
</fieldset>
<div class="v-select__slot">
<label for="input-2" class="v-label theme--light" style="left: 0px; position: absolute;"><span></span></label><input data-testid="test-dropdown" id="input-2" type="text" autocomplete="off">
<div class="v-input__append-inner">
<div class="v-input__icon v-input__icon--append"><i aria-hidden="true" class="v-icon notranslate material-icons theme--light">$dropdownArrow</i></div>
</div>
<input type="hidden">
</div>
<div class="v-menu"></div>
</div>
</div>
</div>
</div>
我的问题是物品在哪里? <div class="v-menu"></div>
为什么我在 wrapper.html 中看不到。我不使用 shallowMount,我使用 mount。因此,我无法编写涵盖的测试用例。
如何模拟打开的菜单并渲染所有项目并提供一些断言?
我错过了什么?
版本
"@nuxtjs/vuetify": "1.12.1",
"@vue/test-utils": "1.0.0-beta.29",
"vue-jest": "3.0.7"
【问题讨论】:
【参考方案1】:嗯,可能更好的方法是用一个测试组件模拟和替换 v-autocomplete(只是控制它的值并从中发出假事件)。您不是在开发 Vuetify,因此无需测试组件内部发生的情况。
【讨论】:
以上是关于测试包装的 vuetify 自动完成组件 v 菜单未在 html 中打开的主要内容,如果未能解决你的问题,请参考以下文章