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