在 Vue 3 上测试点击事件时无法访问 emit 属性



我是测试新手,我正在尝试使用 Vue test-utils 测试组件,但是当我尝试测试对导入组件的单击时遇到问题。

这是我的测试文件:

import { Table, Input } from 'ant-design-vue';
import { CheckOutlined, EditOutlined } from '@ant-design/icons-vue';

import { shallowMount } from '@vue/test-utils';
let wrapper;
beforeEach(() => {
wrapper = shallowMount(TableEditable, {
global: {
components: {
'a-table': Table,
'a-input': Input,
'check-outlined': CheckOutlined,
'edit-outlined': EditOutlined,
}
},
emits: ['edit', 'save'],
props: {
tableData: {
"data":[
{"id":"0","monday":"0"}],
"columns":[
{"title":"Mon","dataIndex":"monday","slots":{"customRender":"monday"}}]
},
dataSrc: [{"id":"0","monday":"0","tuesday":"0","wednesday":"0","thursday":"0","friday":"0","saturday":"9","sunday":"10","key":"0"}]
}
})
})

describe('first test', () => {
it('first test: check if theres a class name', () => {
expect(wrapper.classes()).toContain('tableEditable')
})
it('click and emit buttons', async () => {
await wrapper.findComponent({ref: 'edit-outlined'})
await wrapper.trigger('click')
expect(wrapper.emitted()).toHaveProperty('edit')

})
})

这是我的组件:

<template>
<a-table bordered :data-source="dataSrc" :columns="tableData.columns" :pagination="false" class="tableEditable">
<template #title>
<div class="formLayoutCrud">
<p>{{this.title}}</p>
<input-multiple-button :name="'buttonOptions'" :value="'percentage'" :options="this.buttonOptions"> </input-multiple-button>
</div>
</template>
<template v-for="col in this.editableCells" #[col]="{ column, text, record }" :key="col">
<div class="editable-cell">
<div v-if="editableTableData[record.key + '|' + column.key] !== undefined" class="editable-cell-input-wrapper">
<a-input v-model:value="editableTableData[record.key + '|' + column.key]" @pressEnter="save(record.key, column.key)" type="number" />
<check-outlined class="editable-cell-icon-check" @click="save(record.key, column.key)" />
</div>
<div v-else class="editable-cell-text-wrapper">
{{ text || ' ' }}
<edit-outlined class="editable-cell-icon" @click="edit(record.key, column.key)" />
</div>
</div>
</template>
</a-table>
</template>
<script>

import { CheckOutlined, EditOutlined } from '@ant-design/icons-vue';

import InputMultipleButton from '@/components/crudForm/InputMultipleButton.vue';

export default {
name: 'TableEditable',
props: {
title: String,
buttonOptions: Array,
editableCells: Array,
tableData: Object,
dataSrc: Array,
editableDataProp: Object
},
emits: ['edit', 'save'],
components: {
CheckOutlined,
EditOutlined,
InputMultipleButton
},
data(){
return {
editableTableData: this.editableDataProp
}
},
methods: {
edit(row, column) {
this.$emit('edit', row, column)
},
save(row, column) {
this.$emit('save', row, column)
}
}
}
</script>
<style>

这是我运行 npm 测试时遇到的错误

> vue-cli-service test:unit "TableEditable.spec.js"

FAIL  tests/unit/components/crudForm/TableEditable.spec.js
checkbox first tests
✓ first test: check if theres a class name (18ms)
✕ click and emit buttons (7ms)

● checkbox first tests › click and emit buttons

expect(received).toHaveProperty(path)

Expected path: "edit"
Received path: []

Received value: {"click": [[{"isTrusted": false}]]}

38 |       // await wrapper.vm.$nextTick()
39 |       await wrapper.trigger('click')
> 40 |       expect(wrapper.emitted()).toHaveProperty('edit')
|                     ^
41 |
42 |     })
43 | })

at Object.<anonymous> (tests/unit/components/crudForm/TableEditable.spec.js:40:39)

Test Suites: 1 failed, 1 total
Tests:     1 failed, 1 passed, 2 total
Snapshots: 0 total
Time:      4.653s
Ran all test suites matching /TableEditable.spec.js/i.

正如我所说,对不起,如果这是一个简单的错误,但我开始学习测试,所以我没有很多经验。如果有人需要更多信息,请告诉我。提前感谢!

据我所知expect(wrapper.emitted()).toHaveProperty('edit')应该有效。

所以我认为问题是点击没有按预期工作

你有

await wrapper.findComponent({ref: 'edit-outlined'})
await wrapper.trigger('click')

这将

  • 在包装器中找到edit-outlined按钮
  • 单击组件/包装器(不是按钮)

要解决此问题,您可以尝试像这样链接它:

await wrapper
.findComponent({ref: 'edit-outlined'})
.trigger('click');

此处的触发器分配给结果findComponent

更新

我相信wrapper.findComponent({ref: 'edit-outlined'})没有找到组件。使用ref时,它将查找在 ref 属性中具有该值的组件。

你有

<div v-else class="editable-cell-text-wrapper">
{{ text || ' ' }}
<edit-outlined class="editable-cell-icon" @click="edit(record.key, column.key)" />
</div>

edit-outlined是组件的名称/类型,而不是引用。

您可以将其更改为

<div v-else class="editable-cell-text-wrapper">
{{ text || ' ' }}
<edit-outlined ref="edit-outlined" class="editable-cell-icon" @click="edit(record.key, column.key)" />
</div>

这会将其放入内部对象(this.$refs['edit-outlined']特别是)this.$refs,这将使它可以使用wrapper.findComponent({ref: 'edit-outlined'})进行访问。

您还应该能够更改定位该元素的方式,这应该使其在不更改正在测试的代码的情况下工作。

FindComponent 有三种类型,您可以作为选择器参数传递。

{Component|ref|string} selector

如果您只有一个实例或EditOutlined,则可以使用如下所示的Component类型来定位该实例或实例:

const btn = wrapper.findComponent(EditOutlined);
expect(btn.exists()).toBe(true);
await btn.trigger('click');

此外,最好添加以下内容:expect(btn.exists()).toBe(true);它们还可以充当"健全性测试",并确保当您收到错误时,您正在寻找正确的位置。

最新更新