【问题标题】:Use more than one directive to add data attributes to components使用多个指令向组件添加数据属性
【发布时间】:2019-09-05 15:00:20
【问题描述】:

我有两个指令应该向组件添加数据属性以进行测试,但是实际上只有一个指令被添加。这两个组件是 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
}
}

jobs-search-input-directive 是

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])
    })
  }
}

jobs-search-button-directive 是

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。任何帮助将不胜感激。

【问题讨论】:

  • 什么是v-jobs-search-button-directive?那是你写的吗?我们可以看到它的代码吗?您确定正确地注册了该指令吗?控制台中的任何错误?该指令是在应用程序本身中失败还是仅在运行测试时失败?
  • @skirtle 我已经添加了上面指令的代码。它们在指令内的组件上注册:{...}。它们不会在应用程序本身失败,而只会在运行测试时失败。更具体地说,只有 ``` v-jobs-search-input-directive``` 被添加用于测试,而 v-jobs-search-button-directive 没有

标签: vue.js vue-test-utils


【解决方案1】:

我相信问题发生在...

  • ...尝试使用指令...
  • ...在功能性子组件上...
  • ...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 的代码,但是在调试器中单步执行让我怀疑这一行:

https://github.com/vuejs/vue-test-utils/blob/9dc90a3fd4818ff70e270568a2294b1d8aa2c3af/packages/create-instance/create-component-stubs.js#L99

这是存根子组件的render 函数。 context.data.directives 似乎确实包含正确的指令,但它们没有在对 h 的调用中传递。

与我的示例组件MyFunctional 中的render 函数进行对比,它传递了所有data。这是指令与功能组件一起使用所必需的,但是当MyFunctional 被存根替换时,新的render 函数似乎删除了directives 属性。

我能想到的唯一解决方法是提供您自己的存根:

VueTestUtils.shallowMount(MyComponent, {
  stubs: {
    BButton: { render: h => h('div')}
  }
})

通过使用非功能存根,该指令可以正常工作。但不确定这会从测试中带走多少价值。

【讨论】:

  • 感谢您的回答,我认为我们最终将使用类而不是指令,因为它看起来像 Bootstrap-vue 的大多数组件都是功能性的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-08
  • 2018-10-01
  • 1970-01-01
相关资源
最近更新 更多