-
Notifications
You must be signed in to change notification settings - Fork 669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Named slots' content is not generated for stubbed components via shallowMount #1307
Comments
Related to #1261? |
@runarberg I think this is a different issue. The "old syntax" slots render, but they do not render with any kind of wrapper, so they appear to be in the default slot and it's not possible for a test to confirm whether content was rendered to the correct slot. |
To be clear, to properly test a component, its shallowMount rendering should be something like this:
Not simply this:
|
I was hoping #1261 would fix the issue we were having with moving our codebase to the new slot syntax, but that didn't resolve the issue. Moving to the new slot syntax breaks a lot of our existing unit tests. It looks like this would allow us to use the new syntax while keeping our existing unit tests as-is. Is there a timeline of when this would be available? |
I believe the new slot syntax is now supported @jcmillett - this is a differerent issue unique to shallowMount, no? |
I have closed the PR that supposedly solved this problem. We will revisit shallowMount and how it should render things for the Vue 3 integration. At this point, I don't think we will change how shallowMount is working. I will make a new issue when we revisit shallowMount for v3 integration and invite everyone's input that point. |
For those looking for a solution now, manually stubbing out the component seems to render the child slots: const wrapper = shallowMount(MyComponent, {
stubs: { HigherOrderComponent }
}
expect(wrapper.text()).toContain('header slot content');
expect(wrapper.text()).toContain('footer slot content'); |
This may work but you end up stubbing so much you aren't really testing anything. The best way to test slots is by using |
That's the intention. To use OP's example, I'm writing a unit test for Right now, the default template is being rendered in the stub with Using https://vue-test-utils.vuejs.org/guides/common-tips.html
|
Important part:
At least, this was the intention. To stub the children. Unit testing a single component might make sense sometimes, but if you are testing with slots, it doesn't make a ton of sense to test it as a single unit - it will never be used a single unit, but with other components and children. Just use mount to test it. Using stubs and shallow is really just making more work for yourself - but each to their own. We will improve the docs before Vue 3 integration (over the next few weeks). If you are interested, I will add you as a reviewer to a PR that discusses testing slots, since you have an interest in this topic. There is definitely different ways to accomplish the same thing. We should mention both approaches, and their pros and cons. Is this something you'd like to be involve with? |
<root-component>
<child-component-1>
<child-component-2>
...
<child-component-10> <!-- if this does an AJAX call, I have to mock it -->
<child-component-11> <!-- if this does an AJAX call, I have to mock it --> child components 10 and 11 are very far removed from the root component, but by using
Ultimately, what we need is a way to unit test a component that passes down named slot templates to a stubbed child. It's already possible to check for |
Because I see two options:
In the second case if I have
What do I get?
Or no Before even trying to implement this, we should be very clear one what the goal is. |
I already addressed that, but to quote @souldzin, who put it much better than I can: #1498 (comment)
Yes.
For the sake of example, you have 1 million unique child components, each of which does an AJAX call in their |
We are investigating the rendering of stubbed slots for our Vue 3 integration. I still don't see why slots should get special treatment - shallow should stub everything, instead of this weird selector slot behavior. If you have 1 million unique components then your component is not testable. Write your code in a testable manner. Use Clearly I am not the target user for this feature, so I can't fully understand. Either way, I am way pasting trying to push this issue. Let's move on. We will find something for this use case in the Vue 3 integration, since this is something (some) users feel strongly about. If you feel strongly about this issue, you are more than welcome to attempt to implement the above behavior in this code base, too. |
I said "for the sake of example", the focus here is not the number of components. You said "just stub out the troublesome component", and I'm saying that it could be 2, 5, a dozen, or any arbitrary number of components that need to be stubbed out when using
The user story is, "as a developer writing a unit test, I want to verify that my component is passing the proper data to a child component." Data is defined as anything and everything that can be passed to the child component, which AFAIK is props, attributes, and templates. So given this example: <my-component>
<!-- other stuff that my-component does with its data -->
<child-component :p1="data.p1" :p2="data.p2" data-prefix="prefix">
<template>{{ data.defaultSlot }}</template>
<template #named>{{ data.namedSlot }}</template>
</child-component>
</my-component> it('test my component', () => {
const data = {
p1: 'p1',
p2: 'p2'
defaultSlot: 'default slot text',
namedSlot: 'named slot text'
}
const wrapper = shallowMount(MyComponent, {
propsData: { data });
})
const child = wrapper.find(ChildComponent);
// We can test for props on child stubs.
expect(child.props('p1')).toBe(data.p1);
expect(child.props('p2')).toBe(data.p2);
// We can test for attributes on child stubs.
expect(child.attributes('data-prefix')).toBe('prefix');
// We can test for the default slot on child stubs.
expect(child.text()).toContain(data.defaultSlot);
// We CANNOT test for named slots on child stubs.
expect(child.text()).toContain(data.namedSlot);
}
It's already been done, but you closed it: #1309 From your comment in the PR:
To reiterate the above example: We can test that props are properly passed to children using Without the
Sure, my original comment was simply to provide a solution that works today. This issue has been reported multiple times and even has a PR for it, so it's definitely important to at least some of us, and we can't wait around for the Vue 3 integration. |
It wasn't just a case of "I didn't merge it". Looks like there was some conflict and failing tests here which were not resolved: #1309 I think we need to support both behaviors to make this work for everyone. Some people will expect a true shallow mount, others want stubbed components to render slots. I am pretty focused on getting v1 of this lib released, vue-jest 4 and 5, and VTU next, so I cannot work on this right now. If you (or anyone else reading this) would like to take a stab at this (or anyone else) feel free to do so. What I'd like to see:
Or
I don't think it makes sense as a mounting option, since those are shared with Another alternative would be a Either way, the API won't impact the implementation. Does this sound appropriate? I think this will let everyone write their tests however they like. |
What is the final solution for this? I can't find those configurations on |
Try using |
Here's my solution for named slots content: I took my inspiration from the I used vitest.setup.ts
stub.ts (I had to copy some functions from
We can then use
|
What problem does this feature solve?
Higher-order components make use of named slots. It's possible to test higher-order components via shallowMount because named slot content can be mocked, but it's not possible to test components which consume higher-order components because their generated named slot output is not available in the stubbed content.
#782 added support for outputting default slot content, but not named slots.
To be clear, an example of a component which needs this support is:
Currently, this is stubbed out to only:
<higherordercomponent-stub foo="bar">default slot content</higherordercomponent-stub>
The end user experience should be that components which generate named slot content "just work" when testing with shallowMount.
What does the proposed API look like?
The API would not change.
The text was updated successfully, but these errors were encountered: