vue.js - 如何测试自定义输入 Vue 组件

标签 vue.js vuejs2 vue-test-utils

在 Vue.js 文档中,有一个自定义输入组件的示例。我想弄清楚如何为这样的组件编写单元测试。该组件的用法如下所示

<currency-input v-model="price"></currency-input>

完整的实现可以在 https://v2.vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events 找到

文档说

So for a component to work with v-model, it should (these can be configured in 2.2.0+):

  • accept a value prop
  • emit an input event with the new value

如何编写单元测试来确保我编写的这个组件可以与 v-model 一起工作?理想情况下,我不想专门测试这两个条件,我想测试当组件内的值发生变化时,它也会在模型中发生变化的行为。

最佳答案

你可以做到:

  • 使用Vue Test Utils , 和
  • 安装使用元素<currency-input>
  • 伪造一个输入事件<currency-input> 的内部文本字段具有它转换的值( 13.467<currency-input> 转换为 13.46 )
  • 验证如果在父级中,price属性(绑定(bind)到 v-model)已更改。

示例代码(使用 Mocha):

import { mount } from '@vue/test-utils'
import CurrencyInput from '@/components/CurrencyInput.vue'

describe('CurrencyInput.vue', () => {
  it("changing the element's value, updates the v-model", () => {
    var parent = mount({
      data: { price: null },
      template: '<div> <currency-input v-model="price"></currency-input> </div>',
      components: { 'currency-input': CurrencyInput }
    })

    var currencyInputInnerTextField = parent.find('input');
    currencyInputInnerTextField.element.value = 13.467;
    currencyInputInnerTextField.trigger('input');

    expect(parent.vm.price).toBe(13.46);
  });
});

使用 Jasmine 的浏览器内可运行演示:

var CurrencyInput = Vue.component('currency-input', {
  template: '\
    <span>\
      $\
      <input\
        ref="input"\
        v-bind:value="value"\
        v-on:input="updateValue($event.target.value)">\
    </span>\
  ',
  props: ['value'],
  methods: {
    // Instead of updating the value directly, this
    // method is used to format and place constraints
    // on the input's value
    updateValue: function(value) {
      var formattedValue = value
        // Remove whitespace on either side
        .trim()
        // Shorten to 2 decimal places
        .slice(0, value.indexOf('.') === -1 ? value.length : value.indexOf('.') + 3)
      // If the value was not already normalized,
      // manually override it to conform
      if (formattedValue !== value) {
        this.$refs.input.value = formattedValue
      }
      // Emit the number value through the input event
      this.$emit('input', Number(formattedValue))
    }
  }
});



// specs code ///////////////////////////////////////////////////////////
var mount = vueTestUtils.mount;
describe('CurrencyInput', () => {
  it("changing the element's value, updates the v-model", () => {
    var parent = mount({
      data() { return { price: null } },
      template: '<div> <currency-input v-model="price"></currency-input> </div>',
      components: { 'currency-input': CurrencyInput }
    });
    
    var currencyInputInnerTextField = parent.find('input');
    currencyInputInnerTextField.element.value = 13.467;
    currencyInputInnerTextField.trigger('input');

    expect(parent.vm.price).toBe(13.46);
  });
});

// load jasmine htmlReporter
(function() {
  var env = jasmine.getEnv()
  env.addReporter(new jasmine.HtmlReporter())
  env.execute()
}())
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css">
<script src="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
<script src="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
<script src="https://npmcdn.com/vue@2.5.15/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-template-compiler@2.5.15/browser.js"></script>
<script src="https://rawgit.com/vuejs/vue-test-utils/2b078c68293a41d68a0a98393f497d0b0031f41a/dist/vue-test-utils.iife.js"></script>

注意:上面的代码工作正常(如您所见),但可以改进涉及 v-model 的测试很快。关注this issue获取最新信息。

关于vue.js - 如何测试自定义输入 Vue 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49225316/

相关文章:

javascript - 设置循环内选定的选项 Vue.js

javascript - 将数据传递给另一个组件

unit-testing - 如何使用 jest 对 Vue.js 组件中的方法进行单元测试

unit-testing - 为什么 VueX 存储在多个单元测试中保持状态?

javascript - Vue3 在子组件中使用 v-model

typescript - TS2749 : 'XXX' refers to a value, 但在这里被用作类型。您的意思是 'typeof XXX' 吗?

javascript - 无法访问 Vue3JS Vite 项目中的流程变量

templates - Vue JS v-bind 图像 src 属性组合路径字符串与对象值不起作用

javascript - 条件渲染: component or data

javascript - vue.runtime.common.js : "Cannot read property ' _transitionClasses' of undefined"when this. 错误未使用