简体   繁体   English

如何使用返回任何元素数组的渲染函数对 Vue.js 功能组件进行单元测试?

[英]How do you unit test a Vue.js functional component with a render function that returns any array of elements?

In Vue.js, a functional component can return multiple root nodes by using a render function that returns an array of createdElements .在 Vue.js 中,功能组件可以通过使用返回 createdElements 数组的render函数返回多个根节点。

export default {
  functional: true,
  props: ['cellData'],
  render: function (h, context) {
    return [
      h('td', context.props.cellData.category),
      h('td', context.props.cellData.description)
    ]
  }
}

This works great but I'm having trouble trying to create a unit test for such a component.这很好用,但我在尝试为这样的组件创建单元测试时遇到了麻烦。 Using shallowMount on the component results in [Vue warn]: Multiple root nodes returned from render function. Render function should return a single root node.在组件上使用shallowMount会导致[Vue warn]: Multiple root nodes returned from render function. Render function should return a single root node. [Vue warn]: Multiple root nodes returned from render function. Render function should return a single root node.

import { shallowMount } from '@vue/test-utils'
import Cell from '@/components/Cell'

wrapper = shallowMount(Cell, {
  context: {
    props: {
      cellData {
        category: 'foo',
        description: 'bar'
      }
    }
  }
});

This github issue suggests that the component needs to be wrapped in a single root node to actually render it, but trying that results in [vue-test-utils]: mount.context can only be used when mounting a functional component这个 github 问题表明该组件需要包装在单个根节点中才能实际呈现它,但尝试这样做会导致[vue-test-utils]: mount.context can only be used when mounting a functional component

import { shallowMount } from '@vue/test-utils'
import Cell from '@/components/Cell'

wrapper = shallowMount('<div><Cell></div>', {
  context: {
    props: {
      cellData {
        category: 'foo',
        description: 'bar'
      }
    }
  }
});

So how do I test a functional component that returns multiple root nodes?那么如何测试一个返回多个根节点的功能组件呢?

You could create a higher order, transparent wrapper component that passes all props and event listeners to the inner Cell component using v-bind="$attrs" [1] and v-on="$listeners" [2] .您可以使用v-bind="$attrs" [1]v-on="$listeners" [2]创建一个更高阶的透明包装组件,将所有道具和事件侦听器传递给内部Cell组件。 Then you can use propsData to pass props to the wrapper component ..然后你可以使用propsData将 props 传递给包装器组件..

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

const WrappedCell = {
  components: { Cell },
  template: `
    <div>
      <Cell v-bind="$attrs" v-on="$listeners" />
    </div>
  `
}

const wrapper = mount(WrappedCell, {
  propsData: {
    cellData: {
      category: 'foo',
      description: 'bar'
    }
  }
});

You can create a fragment_wrapper for wrapping your Components with Fragments (multiple root elements).您可以创建一个fragment_wrapper来用片段(多个根元素)包装您的组件。

//File: fragment_wrapper.js

exports.fragment_wrapper = function(FragmentComponent){
  const wrapper = {
    components: { FragmentComponent },
    props: FragmentComponent.props,
    template: `<div><FragmentComponent v-bind="$props" v-on="$listeners"/></div>`
  }
  return wrapper;  
}

Then you can use this to test all your Fragmented Components as follows:然后,您可以使用它来测试所有碎片组件,如下所示:

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


describe('Test Cell', () => {
  let WrappedCell = fragment_wrapper(Cell);
  const wrapper = mount(WrappedCell, {
    propsData: {
      cellData: {
        category: 'foo',
        description: 'bar'
      }
    }
  });

  it('renders the correct markup', () => {
    expect(wrapper.html()).toContain('<td>foo</td>')
  });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM