使用element-ui和vue-test-utils模拟选择操作

11

我正在使用Jest和Element-ui在Vue中进行单元测试,测试的是一个包含2个选项的下拉选择框的组件。我会从下拉菜单中选择一个选项,然后检查是否已调用某个操作。

1) 使用普通的selectoption HTML标签可以正常工作。

// Fruit.vue

<template lang="pug">
  select(
    v-model="fruit"
  )
    option(
      v-for="item in fruits"
      :label="item.label"
      :value="item.value"
    )
</template>
<script>
export default {
  data () {
    return {
      fruits: [
        {
          label: 'Banana',
          value: false
        },
        {
          label: 'Apple',
          value: false
        }
      ]
    }
  },
  computed: {
    fruit: {
      get () {
        return this.$store.state.fruit
      },
      set (fruit) {
        this.$store.dispatch('setSelectedFruit', { fruit })
      }
    }
  }
</script>

// 文档对象模型(DOM)

<select>
  <option label="Banana" value="false"></option>
  <option label="Apple" value="false"></option>
</select>

// 水果.spec.js

it('calls the "setSelectedFruit" action when a value is selected', () => {
  const wrapper = mount(Fruit, { store, localVue })
  const options = wrapper.find('select').findAll('option')


  options.at(1).setSelected()
  expect(actions.setSelectedFruit).toHaveBeenCalled()
})

然而,我使用了 element-ui 的 el-selectel-option 来操作 DOM。

2) 使用 el-selectel-option

// Fruit.vue

除了将 select 替换为 el-select,将 option 替换为 el-option,其余保持不变。

// DOM

<div class="el-select-dropdown">
  <div class="el-select-dropdown__wrap">
    <ul class="el-select-dropdown__list">
      <li class="el-select-dropdown__item">
        <span>Banana</span>
      </li>
      <li class="el-select-dropdown__item">
        <span>Apple</span>
      </li>
    </ul>
  </div>
</div>

// 鰐梨.spec.js

a)

it('calls the "setSelectedFruit" action', () => {
  const wrapper = mount(Fruit, { store, localVue })
  const options = wrapper.find('.el-select-dropdown__list').findAll('el-select-dropdown__items')

  options.at(1).setSelected()
  expect(actions.setSelectedFruit).toHaveBeenCalled()
})

b) 鉴于根据 vue-test-utils 文档 的说法,setSelected 实际上是一个别名,我尝试了以下方法:

it('calls the "setSelectedFruit" action', () => {
  const wrapper = mount(Fruit, { store, localVue })
  const options = wrapper.findAll('.el-select-dropdown__item')
  const select = wrapper.find('.el-select-dropdown__list')

  options.at(1).element.selected = false
  select.trigger('change')
  expect(actions.setSelectedFruit).toHaveBeenCalled()
})

使用第二种方法,所选的option会被设置为selected,但是select上的触发器不起作用,所以v-model没有被更新。

因此,我想知道是否有人有解决方案,或者是否有另一个库(除了vue-test-utils)可以模拟element-ui的el-select


你尝试使用select.vm.$emit('change', 1)代替trigger了吗? (其中1是所选元素的值)或者$emit('input', 1) - ierdna
2个回答

1
我成功地实现了这个功能,方法是触发你想要模拟的下拉菜单项的点击事件:
wrapper.findAll('.el-select-dropdown__item').at(1).trigger('click');
await Vue.nextTick();
expect(YourExpectStatement);

Vue.nextTick()对我很有帮助,因为它允许DOM更新其周期,更多信息在此处。还要注意,您需要将测试函数设置为异步,例如:

it('Async test name', async () => {

1

<el-dropdown> 或者 <el-select> 中触发点击并让下拉菜单项出现是非常困难的。

然后我尝试模拟所有这些元素。这对我来说效果很好。

/mock/div.vue

<template>
  <div>
    <slot></slot>
    <slot name="dropdown"></slot>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({   
  inheritAttrs: true
})
</script>

jest.setup.js

import { config } from '@vue/test-utils'
import Div from './mock/div.vue'
config.global.components = {  
   ElDropdown: Div,
   ElDropdownItem: Div,
   ElDropdownMenu: Div
}

尝试使用这个解决方案,但是我得到了“TypeError: Cannot set properties of undefined (setting 'components')”的错误……我做错了什么? - Cesar Bhering

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接