【问题标题】:Vue.js filters and testingVue.js 过滤器和测试
【发布时间】:2017-03-30 22:53:23
【问题描述】:

我使用 vue-cli 创建示例项目 vue init webpack my-test3,并选择同时包含 e2e 和单元测试。

问题 1: 根据 template filters 的文档,我尝试在 main.js 中添加新过滤器:

import Vue from 'vue'
import App from './App'

/* eslint-disable no-new */
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App },
  filters: {
    capitalize: function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }
})

还有我的App.vue

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <hello></hello>
    <world></world>

    <div class="test-test">{{ 'tesT' | capitalize }}</div>
  </div>
</template>

<script>
import Hello from './components/Hello'
import World from './components/World'

export default {
  name: 'app',
  components: {
    Hello,
    World
  }
}
</script>

我收到警告(错误):

[Vue 警告]:无法解析过滤器:大写(在组件 中找到)

如果我在初始化新的 Vue 应用程序之前修改 main.js 以注册过滤器,那么它可以正常工作。

import Vue from 'vue'
import App from './App'

Vue.filter('capitalize', function (value) {
  if (!value) return ''
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)
})

/* eslint-disable no-new */
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})

为什么一个有效而另一个无效?

问题 2: 使用上面的示例 Vue.filter(...,我为 World.vue 组件添加了一个测试:

<template>
  <div class="world">
    <h1>{{ msg | capitalize }}</h1>
    <h2>{{ desc }}</h2>

    Items (<span>{{ items.length }}</span>)
    <ul v-for="item in items">
        <li>{{ item }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'world',
  data () {
    return {
      msg: 'worldly App',
      desc: 'This is world description.',
      items: [ 'Mon', 'Wed', 'Fri', 'Sun' ]
    }
  }
}
</script>

还有World.spec.js:

import Vue from 'vue'
import World from 'src/components/World'

Vue.filter('capitalize', function (value) {
  if (!value) return ''
  value = value.toString()
  return value.charAt(0).toUpperCase() + value.slice(1)
})

describe('World.vue', () => {
  it('should render correct title', () => {
    const vm = new Vue({
      el: document.createElement('div'),
      render: (h) => h(World)
    })
    expect(vm.$el.querySelector('.world h1').textContent)
      .to.equal('Worldly App')
  })
  it('should render correct description', () => {
    const vm = new Vue({
      el: document.createElement('div'),
      render: (w) => w(World)
    })
    expect(vm.$el.querySelector('.world h2').textContent)
      .to.equal('This is world description.')
  })
})

为了通过上述测试,我需要包含Vue.filter(... 过滤器大写的定义,否则测试将失败。所以我的问题是,如何构造过滤器/组件并对其进行初始化,以便测试更容易?

我觉得我不应该在单元测试中注册过滤器,这应该是组件初始化的一部分。但是如果组件继承/使用主应用定义的过滤器,测试组件将无法工作。

有什么建议、cmets、阅读材料吗?

【问题讨论】:

    标签: unit-testing vue.js vue-component


    【解决方案1】:

    一个好的做法是创建一个过滤器文件夹并在此文件夹中的单个文件中定义您的过滤器,如果您想在所有组件中访问它们,则全局定义所有过滤器,例如:

    
        // capitalize.js
    
        export default function capitalize(value) {
          if (!value) return '';
          value = value.toString().toLowerCase();
          value = /\.\s/.test(value) ? value.split('. ') : [value];
    
          value.forEach((part, index) => {
            let firstLetter = 0;
            part = part.trim();
    
            firstLetter = part.split('').findIndex(letter => /[a-zA-Z]/.test(letter));
            value[index] = part.split('');
            value[index][firstLetter] = value[index][firstLetter].toUpperCase();
            value[index] = value[index].join('');
          });
    
          return value.join('. ').trim();
        }
    

    要成功测试它并且如果您使用@vue/test-utils 来测试您的单个文件组件,您可以使用createLocalVue 进行测试,如下所示:

    // your-component.spec.js
    
    import { createLocalVue, shallowMount } from '@vue/test-utils';
    import capitalize from '../path/to/your/filter/capitalize.js';
    import YOUR_COMPONENT from '../path/to/your/component.vue';
    
    describe('Describe YOUR_COMPONENT component', () => {
      const localVue = createLocalVue();
    
      // this is the key line
      localVue.filter('capitalize', capitalize);
    
      const wrapper = shallowMount(YOUR_COMPONENT, {
        // here you can define the required data and mocks
        localVue,
        propsData: {
          yourProp: 'value of your prop',
        },
        mocks: {
          // here you can define all your mocks
          // like translate function and others.
        },
      });
    
      it('passes the sanity check and creates a wrapper', () => {
        expect(wrapper.isVueInstance()).toBe(true);
      });
    });
    
    

    希望能帮到你。

    问候。

    【讨论】:

      【解决方案2】:

      我最好的猜测是,如果您在组件内定义filters,它们将只能在该组件内使用。在您的情况下,您只能在主 Vue 实例中使用 capitalize,而不能在其子组件中使用。将其移至全局级别即可解决问题。

      对于第二个问题,您在测试文件中添加过滤器定义是正确的。

      【讨论】:

        猜你喜欢
        • 2020-01-05
        • 2018-01-27
        • 2020-02-01
        • 2016-06-17
        • 2021-08-28
        • 2018-09-09
        • 2018-09-28
        • 1970-01-01
        • 2018-07-02
        相关资源
        最近更新 更多