ElementUI单元测试未知元素警告如何解决?

How to solve ElementUI unknown element warning in unit tests?

我正在使用来自 element-plus

<el-buton> 测试组件

我没有直接使用,<el-button>在我的Connect组件里面

import { shallowMount } from '@vue/test-utils'
import { createApp } from 'vue'
import { createStore } from 'vuex'
import App from '@/components/connect'

const store = createStore({
  state() {
    return {
      user: {},
    }
  },
  mutations: {},
})

let wrapper
const app = createApp(App)
app.use(store)

beforeEach(() => {
  wrapper = shallowMount(App, {
    propsData: {},
    global: {
      plugins: [store],
    },
   
  })
})

我在所有组件测试中都收到此警告:

If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.

也在 github 上提问:https://github.com/element-plus/element-plus/issues/5830

我不知道你所说的 “我没有直接使用” 是什么意思,但是警告告诉你 Jest 在遍历组件时发现了这个标签 DOM,在浅安装期间,它不知道如何解决它,因为它既不是本机 DOM 标记,也不是已知组件。

重要说明:当浅层安装时 Jest 存根 sub-components 并不意味着它没有解决它们。

  1. 如果 <el-button> 与当前测试无关,请忽略此警告。
    开玩笑:“但我不知道 <el-button> 是什么!”
    你:“没关系,你不需要。
  2. 如果 <el-button> 与测试无关,但警告 惹恼了 你,要么声明 <el-button> 一个网络组件(这是错误的,但是它告诉 Jest 忽略它),遵循 link 和警告中显示的说明;或在此测试套件中手动存根(将其替换为空 <div />):
import { config } from '@vue/test-utils'

config.stubs['el-button'] = '<div />'
  1. 如果 <el-button> 与当前测试相关,您必须将 ElementUI 添加到包装器实例的全局变量中。
    这将使您的包装器知道每个 ElementUI 的组件和指令是什么。这并不意味着他们不会被打脸。他们会的,但 Jest 会知道它在存根什么,最重要的是,它会解决它们的依赖关系:
import ElementUI from 'element-ui';

beforeEach(() => {
  wrapper = shallowMount(App, {
    propsData: {},
    global: {
      plugins: [store, ElementUI],
    },
  });
});

事实上,这是提供它们的正确方法,因为当您使用 app.use(SomePlugin) 在根实例上安装它们时,这是将它们提供给真实应用程序中的实例的方式.


您应该对应用中使用的所有其他插件执行此操作。如果它变得过于重复,创建一个辅助函数,将当前测试的组件及其设置作为参数传递,返回一个 wrapper,它具有您应用程序的所有功能。

一些纯粹主义者可能会说:“但我不想用所有全局插件测试我的组件,我只想用它使用的插件测试它。”
恕我直言,这是错误的。即使该组件只使用一些全局提供的插件,它也会在提供所有插件的上下文中运行(实时)。因此,如果某些全局插件和当前组件之间存在任何冲突,您可能希望通过此测试了解它,而不是通过 github 问题。

通用包装器工厂示例:

import { shallowMount, mount } from '@vue/test-utils'
import SomePlugin from 'some-library';
import SomeOtherPlugin from 'some-other-library';
import { createStore } from 'vuex'

export const useWrapper = (component, setup, shallow = true) => {
  const store = createStore({ /* ... */ });
  return (shallow ? shallowMount : mount)(component, {
    globals: {
      plugins: [SomePlugin, SomeOtherPlugin, store]
    },
    ...setup,
  })
}

注意 这甚至允许您通过 setup 覆盖 globals,但是,恕我直言,这不是一个好主意,因为原因如上。

现在你可以在你所有的测试中导入useWrapper,这有点多boilerplate-free:

import { useWrapper } from '../path-to-helpers';
import SomeComponent from '@/components/SomeComponent.vue'

//...
describe('SomeComponent', () => {
  let wrapper;

  beforeEach(() => {
    wrapper = useWrapper(SomeComponent, {
      propsData: {} // extend as needed
    });
  });

  it('should do stuff...', () => {
    // expect it does stuff...
  })
});

当您需要 mount 而不是 shallowMount 时,将 false 作为第三个参数传递给 useWrapper