Reputation: 165
I'm testing a component using <el-buton>
from element-plus
I am not using directly, <el-button>
is inside of my Connect component
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],
},
})
})
I am getting this warning in all test of my components:
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
Asked on github as well: https://github.com/element-plus/element-plus/issues/5830
Upvotes: 2
Views: 3209
Reputation: 90217
I don't know what you mean by "I'm not using directly", but the warning tells you Jest found this tag when traversing the component's DOM, during shallow mounting, and it doesn't know how to resolve it, as it's neither a native DOM tag, nor a known component.
Important note: the fact that Jest stubs sub-components when shallow mounting doesn't mean it doesn't resolve them.
<el-button>
is not relevant for the current test, simply ignore this warning.<el-button>
is!"<el-button>
is not relevant for the test, but the warning annoys you, either declare <el-button>
a web component (which is false, but it tells Jest to ignore it), by following the link and the instructions shown in the warning; or stub it manually (replace it with an empty <div />
) in this test suite:import { config } from '@vue/test-utils'
config.stubs['el-button'] = '<div />'
<el-button>
is relevant for the current test, you have to add ElementUI to the wrapper instance's globals.import ElementUI from 'element-ui';
beforeEach(() => {
wrapper = shallowMount(App, {
propsData: {},
global: {
plugins: [store, ElementUI],
},
});
});
This is, in fact, the correct way to provide them, because it's how they're provided to the instance in the real app, when you're installing them on the root instance, using app.use(SomePlugin)
.
You should do this for all other plugins used in app. If it gets too repetitive, create a helper function, pass the currently tested component and its setup as arguments, returning a wrapper
which has all the bells and whistles of your app.
Some purists might say: "but I don't want to test my component with all the global plugins, I want to only test it with the ones it uses."
IMHO, that's wrong. even if the component only uses a few of the global provided plugins, it runs (on live) in a context where they are all provided. So, should there be any conflict between some global plugin and the current component, you probably want to learn about it from this test, not from a github issue.
Generic wrapper factory example:
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,
})
}
Note this even allows you to override globals
, through setup
, should you want to but, IMHO, that's not a good idea, for the reason outlined above.
And now you can import useWrapper
in all your tests, which are a bit more 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...
})
});
When you need to mount
instead of shallowMount
, pass false
as third argument to useWrapper
.
Upvotes: 3