Vue.js 过滤器和测试 [英] Vue.js filters and testing
问题描述
我使用 vue-cli 创建示例项目 vue init webpack my-test3
,并选择包含 e2e 和单元测试.
问题 1:基于模板过滤器 我试图在 main.js
中添加新的过滤器:
从'vue'导入Vue从'./App'导入应用程序/* eslint-disable no-new */新的 Vue({el: '#app',模板:'<App/>',组件:{应用},过滤器:{大写:函数(值){if (!value) 返回 ''值 = value.toString()返回值.charAt(0).toUpperCase() + value.slice(1)}}})
还有我的App.vue
:
<div id="应用程序"><img src="./assets/logo.png"><你好></你好><世界></世界><div class="test-test">{{ 'test' |大写 }}
模板><脚本>从 './components/Hello' 导入 Hello从./components/World"导入世界导出默认{名称:'应用',成分: {你好,世界}}
我收到警告(错误):
<块引用>[Vue 警告]:无法解析过滤器:大写(在组件
如果我在初始化新的 Vue 应用程序之前修改 main.js
以注册过滤器,那么它就可以正常工作.
从'vue'导入Vue从'./App'导入应用程序Vue.filter('capitalize', function (value) {if (!value) 返回 ''值 = value.toString()返回值.charAt(0).toUpperCase() + value.slice(1)})/* eslint-disable no-new */新的 Vue({el: '#app',模板:'<App/>',组件:{应用}})
为什么一个有效而另一个无效?
问题 2: 在上面的例子中,Vue.filter(...
,我为 World.vue
组件添加了一个测试:
<div class="world"><h1>{{ 味精 |大写 }}<h2>{{ desc }}</h2>项目 ({{ items.length }}</span>)<ul v-for="项目中的项目"><li>{{ item }}</li>
模板><脚本>导出默认{name: '世界',数据 () {返回 {msg: '世俗应用',desc: '这是世界描述.',项目:[周一"、周三"、周五"、周日"]}}}
和World.spec.js
:
从'vue'导入Vue从 'src/components/World' 导入世界Vue.filter('capitalize', function (value) {if (!value) 返回 ''值 = value.toString()返回值.charAt(0).toUpperCase() + value.slice(1)})describe('World.vue', () => {it('应该呈现正确的标题', () => {const vm = 新的 Vue({el: document.createElement('div'),渲染:(h) =>h(世界)})期望(vm.$el.querySelector('.world h1').textContent).to.equal('Worldly App')})it('应该呈现正确的描述', () => {const vm = 新的 Vue({el: document.createElement('div'),渲染:(w) =>w(世界)})期望(vm.$el.querySelector('.world h2').textContent).to.equal('这是世界描述.')})})
要通过上述测试,我需要包含 Vue.filter(...
过滤器大写的定义,否则测试将失败.所以我的问题是,如何构建过滤器/组件和初始化它们,所以测试更容易?
我觉得我不应该在单元测试中注册过滤器,这应该是组件初始化的一部分.但是如果组件继承/使用从主应用程序定义的过滤器,测试组件将不起作用.
有什么建议、意见、阅读材料吗?
一个好的做法是创建一个过滤器文件夹并在该文件夹中的单个文件中定义您的过滤器,如果您想在其中访问它们,则全局定义所有过滤器您的所有组件,例如:
//大写.js导出默认函数大写(值){if (!value) 返回 '';value = value.toString().toLowerCase();值 =/\.\s/.test(value) ?value.split('.') : [value];value.forEach((part, index) => {让第一个字母 = 0;部分 = part.trim();firstLetter = part.split('').findIndex(letter =>/[a-zA-Z]/.test(letter));值[索引] = part.split('');value[index][firstLetter] = value[index][firstLetter].toUpperCase();值[索引] = 值[索引].join('');});return value.join('.').trim();}
为了成功测试它,如果你使用 @vue/test-utils,测试你的单文件组件,你可以用 createLocalVue
来做,就像这样:
//your-component.spec.js从'@vue/test-utils'导入{createLocalVue,shallowMount};从../path/to/your/filter/capitalize.js"导入大写;从../path/to/your/component.vue"导入 YOUR_COMPONENT;describe('描述你的_COMPONENT 组件', () => {const localVue = createLocalVue();//这是关键行localVue.filter('capitalize', capitalize);const 包装器 = 浅贴(YOUR_COMPONENT,{//在这里你可以定义所需的数据和模拟本地Vue,道具数据:{yourProp: '你的道具价值',},嘲笑:{//在这里你可以定义所有的模拟//像翻译函数等.},});it('通过健全性检查并创建一个包装器', () => {期望(wrapper.isVueInstance()).toBe(true);});});
希望能帮到你.
问候.
I used vue-cli to create sample project vue init webpack my-test3
, and opted for including both e2e and unit tests.
Question 1: Based on documentation for template filters I tried to add new filter as such in 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)
}
}
})
And my 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>
I get warning(error):
[Vue warn]: Failed to resolve filter: capitalize (found in component <app>)
If I modify main.js
to register filter before initializing new Vue app, then it works without problem.
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 }
})
Why one works and other not?
Question 2: With example above that works Vue.filter(...
, I added a test for World.vue
component:
<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>
And 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.')
})
})
For the above test to pass, I need to include Vue.filter(...
definition for filter capitalize, otherwise tests would fail. So my question is, how to structure filters/components and initialize them, so testing is easier?
I feel like I should not have to register filters in unit tests, that should be part of the component initialization. But if component is inheriting/using filter defined from main app, testing component will not work.
Any suggestions, comments, reading materials?
A good practice is create a filters folder and define your filters inside this folder in individual files and define all your filters globally if you want to have access to them in all of your components, eg:
// 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();
}
To test it successfully and if you use @vue/test-utils, to test your single file components, you can do that with createLocalVue
, like this:
// 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);
});
});
I hope to help you.
Regards.
这篇关于Vue.js 过滤器和测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!