使用多个指令为组件添加数据属性
Use more than one directive to add data attributes to components
我有两个指令,它们应该将数据属性添加到组件以进行测试,但是,实际上只有一个指令被添加。这两个组件是Bootstrap-Vue的BFormInput和BButton。
我尝试删除除其中一个按钮以外的所有内容,但仍未添加该指令,即
<b-input-group class="sm-2 mb-2 mt-2">
<b-button
variant="primary"
@click="searchJobs"
class="rounded-0"
v-jobs-search-button-directive="{ id: 'search-button' }"
>
Search
</b-button>
</b-input-group>
wrapper.html() 输出为:
<b-input-group-stub tag="div" class="sm-2 mb-2 mt-2"><b-button-stub target="_self" event="click" routertag="a" variant="secondary" type="button" tag="button" class="rounded-0">
Search
</b-button-stub></b-input-group-stub>
但是,它是在我保留输入表单而不是按钮时添加的,即
<b-input-group class="sm-2 mb-2 mt-2">
<b-form-input
v-jobs-search-input-directive="{ id: 'input-keyword' }"
class="mr-2 rounded-0"
placeholder="Enter Search term..."
:value="this.searchConfig.Keyword"
@input="this.updateJobsSearchConfig"
/>
</b-input-group>
wrapper.html() 输出为:
<b-input-group-stub tag="div" class="sm-2 mb-2 mt-2"><b-form-input-stub value="" placeholder="Enter Search term..." type="text" class="mr-2 rounded-0" data-jobs-search-input-id="input-keyword"></b-form-input>
这就是我添加指令的方式
<template>
<b-input-group class="sm-2 mb-2 mt-2">
<b-form-input
v-jobs-search-input-directive="{ id: 'input-keyword' }"
class="mr-2 rounded-0"
placeholder="Enter Search term..."
:value="this.searchConfig.Keyword"
@input="this.updateJobsSearchConfig"
/>
<b-button
variant="primary"
@click="searchJobs"
class="rounded-0"
v-jobs-search-button-directive="{ id: 'search-button' }"
>
Search
</b-button>
</b-input-group>
</template>
<script>
import { mapActions, mapState } from 'vuex'
import JobService from '@/api-services/job.service'
import JobsSearchInputDirective from '@/directives/components/jobs/JobsSearchInputDirective'
import JobsSearchButtonDirective from '@/directives/components/jobs/JobsSearchButtonDirective'
export default {
name: 'jobs-search',
directives: { JobsSearchInputDirective, JobsSearchButtonDirective },
data () {
return {
jobs: [],
pages: 0
}
},
computed: {
...mapState({
pagedConfig: state => state.jobs.paged,
searchConfig: state => state.jobs.search
})
},
methods: {
// Methods go here
}
}
工作搜索输入指令是
export default (el, binding) => {
if (process.env.NODE_ENV === 'test') {
Object.keys(binding.value).forEach(value => {
el.setAttribute(`data-jobs-search-input-${value}`, binding.value[value])
})
}
}
工作搜索按钮指令是
export default (el, binding) => {
if (process.env.NODE_ENV === 'test') {
Object.keys(binding.value).forEach(value => {
el.setAttribute(`data-jobs-search-button-${value}`, binding.value[value])
})
}
}
这是测试我运行,用shallowMount
安装
it('should call jobsSearch method on search button click event', () => {
wrapper.find('[data-jobs-search-button-id="search-button"]').trigger('click')
expect(searchJobs).toHaveBeenCalled()
})
返回
Error: [vue-test-utils]: find did not return [data-jobs-search-button-id="search-button"], cannot call trigger() on empty Wrapper
但是wrapper.find('[data-jobs-search-input-id="input-keyword"]')
确实找到了输入形式
这两个指令在 JobsSearch.vue
组件中注册,如果我删除 process.env
部分,它们肯定会被渲染
我希望将属性添加到两个组件,但它只在测试时添加到 BFormInput。任何帮助将不胜感激。
我认为问题发生在...
- ...尝试使用指令...
- ...在功能性子组件上...
- ... 与
shallowMount
.
b-button
是功能组件。
我整理了下面的演示来说明问题。它以 3 种不同的方式安装相同的组件,并且仅在上述特定情况下才会失败。
MyComponent = {
template: `
<div>
<my-normal v-my-directive></my-normal>
<my-functional v-my-directive></my-functional>
</div>
`,
components: {
MyNormal: {
render: h => h('span', 'Normal')
},
MyFunctional: {
functional: true,
render: (h, context) => h('span', context.data, 'Functional')
}
},
directives: {
myDirective (el) {
el.setAttribute('name', 'Lisa')
}
}
}
const v = new Vue({
el: '#app',
components: {
MyComponent
}
})
document.getElementById('markup1').innerText = v.$el.innerHTML
const cmp1 = VueTestUtils.mount(MyComponent)
document.getElementById('markup2').innerText = cmp1.html()
const cmp2 = VueTestUtils.shallowMount(MyComponent)
document.getElementById('markup3').innerText = cmp2.html()
#markup1, #markup2, #markup3 {
border: 1px solid #777;
margin: 10px;
padding: 10px;
}
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vue-template-compiler@2.6.10/browser.js"></script>
<script src="https://unpkg.com/@vue/test-utils@1.0.0-beta.29/dist/vue-test-utils.iife.js"></script>
<div id="app">
<my-component></my-component>
</div>
<div id="markup1"></div>
<div id="markup2"></div>
<div id="markup3"></div>
我之前没有真正看过 vue-test-utils
的代码,但是在调试器中单步调试让我怀疑这一行:
这是存根子组件的 render
函数。看起来 context.data.directives
确实包含正确的指令,但它们没有在对 h
.
的调用中传递
将其与我的示例组件 MyFunctional
中的 render
函数进行对比,后者传递所有 data
。这是指令与功能组件一起工作所必需的,但是当 MyFunctional
被替换为存根时,新的 render
函数似乎会删除 directives
属性.
我能想到的唯一解决方法是提供您自己的存根:
VueTestUtils.shallowMount(MyComponent, {
stubs: {
BButton: { render: h => h('div')}
}
})
通过使用非功能性存根,该指令可以正常工作。不过不确定这会从测试中带走多少价值。
我有两个指令,它们应该将数据属性添加到组件以进行测试,但是,实际上只有一个指令被添加。这两个组件是Bootstrap-Vue的BFormInput和BButton。
我尝试删除除其中一个按钮以外的所有内容,但仍未添加该指令,即
<b-input-group class="sm-2 mb-2 mt-2">
<b-button
variant="primary"
@click="searchJobs"
class="rounded-0"
v-jobs-search-button-directive="{ id: 'search-button' }"
>
Search
</b-button>
</b-input-group>
wrapper.html() 输出为:
<b-input-group-stub tag="div" class="sm-2 mb-2 mt-2"><b-button-stub target="_self" event="click" routertag="a" variant="secondary" type="button" tag="button" class="rounded-0">
Search
</b-button-stub></b-input-group-stub>
但是,它是在我保留输入表单而不是按钮时添加的,即
<b-input-group class="sm-2 mb-2 mt-2">
<b-form-input
v-jobs-search-input-directive="{ id: 'input-keyword' }"
class="mr-2 rounded-0"
placeholder="Enter Search term..."
:value="this.searchConfig.Keyword"
@input="this.updateJobsSearchConfig"
/>
</b-input-group>
wrapper.html() 输出为:
<b-input-group-stub tag="div" class="sm-2 mb-2 mt-2"><b-form-input-stub value="" placeholder="Enter Search term..." type="text" class="mr-2 rounded-0" data-jobs-search-input-id="input-keyword"></b-form-input>
这就是我添加指令的方式
<template>
<b-input-group class="sm-2 mb-2 mt-2">
<b-form-input
v-jobs-search-input-directive="{ id: 'input-keyword' }"
class="mr-2 rounded-0"
placeholder="Enter Search term..."
:value="this.searchConfig.Keyword"
@input="this.updateJobsSearchConfig"
/>
<b-button
variant="primary"
@click="searchJobs"
class="rounded-0"
v-jobs-search-button-directive="{ id: 'search-button' }"
>
Search
</b-button>
</b-input-group>
</template>
<script>
import { mapActions, mapState } from 'vuex'
import JobService from '@/api-services/job.service'
import JobsSearchInputDirective from '@/directives/components/jobs/JobsSearchInputDirective'
import JobsSearchButtonDirective from '@/directives/components/jobs/JobsSearchButtonDirective'
export default {
name: 'jobs-search',
directives: { JobsSearchInputDirective, JobsSearchButtonDirective },
data () {
return {
jobs: [],
pages: 0
}
},
computed: {
...mapState({
pagedConfig: state => state.jobs.paged,
searchConfig: state => state.jobs.search
})
},
methods: {
// Methods go here
}
}
工作搜索输入指令是
export default (el, binding) => {
if (process.env.NODE_ENV === 'test') {
Object.keys(binding.value).forEach(value => {
el.setAttribute(`data-jobs-search-input-${value}`, binding.value[value])
})
}
}
工作搜索按钮指令是
export default (el, binding) => {
if (process.env.NODE_ENV === 'test') {
Object.keys(binding.value).forEach(value => {
el.setAttribute(`data-jobs-search-button-${value}`, binding.value[value])
})
}
}
这是测试我运行,用shallowMount
安装
it('should call jobsSearch method on search button click event', () => {
wrapper.find('[data-jobs-search-button-id="search-button"]').trigger('click')
expect(searchJobs).toHaveBeenCalled()
})
返回
Error: [vue-test-utils]: find did not return [data-jobs-search-button-id="search-button"], cannot call trigger() on empty Wrapper
但是wrapper.find('[data-jobs-search-input-id="input-keyword"]')
确实找到了输入形式
这两个指令在 JobsSearch.vue
组件中注册,如果我删除 process.env
部分,它们肯定会被渲染
我希望将属性添加到两个组件,但它只在测试时添加到 BFormInput。任何帮助将不胜感激。
我认为问题发生在...
- ...尝试使用指令...
- ...在功能性子组件上...
- ... 与
shallowMount
.
b-button
是功能组件。
我整理了下面的演示来说明问题。它以 3 种不同的方式安装相同的组件,并且仅在上述特定情况下才会失败。
MyComponent = {
template: `
<div>
<my-normal v-my-directive></my-normal>
<my-functional v-my-directive></my-functional>
</div>
`,
components: {
MyNormal: {
render: h => h('span', 'Normal')
},
MyFunctional: {
functional: true,
render: (h, context) => h('span', context.data, 'Functional')
}
},
directives: {
myDirective (el) {
el.setAttribute('name', 'Lisa')
}
}
}
const v = new Vue({
el: '#app',
components: {
MyComponent
}
})
document.getElementById('markup1').innerText = v.$el.innerHTML
const cmp1 = VueTestUtils.mount(MyComponent)
document.getElementById('markup2').innerText = cmp1.html()
const cmp2 = VueTestUtils.shallowMount(MyComponent)
document.getElementById('markup3').innerText = cmp2.html()
#markup1, #markup2, #markup3 {
border: 1px solid #777;
margin: 10px;
padding: 10px;
}
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vue-template-compiler@2.6.10/browser.js"></script>
<script src="https://unpkg.com/@vue/test-utils@1.0.0-beta.29/dist/vue-test-utils.iife.js"></script>
<div id="app">
<my-component></my-component>
</div>
<div id="markup1"></div>
<div id="markup2"></div>
<div id="markup3"></div>
我之前没有真正看过 vue-test-utils
的代码,但是在调试器中单步调试让我怀疑这一行:
这是存根子组件的 render
函数。看起来 context.data.directives
确实包含正确的指令,但它们没有在对 h
.
将其与我的示例组件 MyFunctional
中的 render
函数进行对比,后者传递所有 data
。这是指令与功能组件一起工作所必需的,但是当 MyFunctional
被替换为存根时,新的 render
函数似乎会删除 directives
属性.
我能想到的唯一解决方法是提供您自己的存根:
VueTestUtils.shallowMount(MyComponent, {
stubs: {
BButton: { render: h => h('div')}
}
})
通过使用非功能性存根,该指令可以正常工作。不过不确定这会从测试中带走多少价值。