test-utils
test-utils copied to clipboard
Behavior of global.components is confusing
I'm struggling to understand the reasoning, why global.components perform two things simultaneously:
- registers global components (this is perfectly fine)
- acts as
global.stubs, but just for component we are mounting
Second one is provided by this piece of code inside mount:
if (isObjectComponent(component)) {
component.components = { ...component.components, ...global.components }
}
where global.components effectively overwrite local components.
I find this behavior super-confusing:
- now we have two approaches for stubbing components, and one of them (via
global.components) will work only for components, who use Options API - relationship between
global.stubsandglobal.componentsbecomes hard-to-explain
For example this test looks super-confusing unless you know what is happening [source]:
it('allows global stubs to be deactivated without warning', () => {
const GlobalComponent = {
template: '<div>Global</div>'
}
const spy = jest.spyOn(console, 'warn')
const wrapper = mount(
{
template: '<div><global-component/></div>'
},
{
global: {
components: {
GlobalComponent
},
stubs: { GlobalComponent: false }
}
}
)
You're like: ...em... what? I'm unstubbing GlobalComponent by passing GlobalComponent: false, but why it is stubbed, we're not using shallowMount?
I see no added benefits in current behavior and would like to suggest dropping it, and matching global.components application API app.component behavior - it simply registers component as global one and nothing more
@lmiller1990 considering I saw some recent activity from you would be happy to hear your thoughts
It like the change was made here: https://github.com/vuejs/vue-test-utils-next/pull/504 to support a use-case in the posva/vue-router-mock library.
I can see why this would be confusing. Have you encountered this use case in your usual development workflow? I have not really found myself using global.stubs and global.components in the same test, I'm guessing this is not a very common edge case.
It looks like reverting it might have some negative impacts, at least on the vue-router-mock library.
@lmiller1990 thank you for giving context! I will take a look and come back today with proposal
@lmiller1990 I've checked that #504 is actually not the issue where problematic code was added Original source of the problematic code is https://github.com/vuejs/vue-test-utils-next/pull/116 and after analyzing discussion there I believe it was based at least on assumptions which are not in the play anymore
Regarding "if we meet this in the wild" - I've discovered this while preparing codemod, which "automatically" unpacked non-existent anymore parentComponent to relevant global properties. I still vote for having as simple mental model as possible.
This behavior was very confusing me as well and the main challenge for me was that the globals are registered using app.component() and/or app.use() in Vue. However, this library uses an alternate array syntax for global registration.
Luckily, I was using a custom-built component library so I was able to create an "index" that I could import to this library. I then used a for-loop to register the components in my main.js file.
It seems that this library handles global registration in a completely different way from Vue itself which is very confusing.
@vpillinger can you share a minimal example showing how Test Utils differs from Vue itself?
Also what do you mean by "array syntax"? You can supply components using an object: https://next.vue-test-utils.vuejs.org/api/#global
import Something from './Something.vue'
mount(Foo, {
global: {
components: {
MyButton: Something,
InlineComponent: {
template: `<div>OK</div>`
}
}
}
})
etc.