-
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
generate named slots content for stubbed components via shallowMount #1309
Conversation
Hi! This is my first ever OSS contribution. Please let me know any feedback you may have! :) |
I did create an Issue for this PR, but I guess I failed to link it: |
This is a super helpful fix... What's the chances of this being merged? |
Any updates on this? It's really helpful and would make snapshot testing with Vuetify components a lot better. |
Hey @chriswa , awesome first OSS contribution. I will review this now and give you feedback so w can get this merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an awesome first OSS contribution. Left a few comments, only one really requires any action (first one about ignored elements).
Might also be good to rebase on the last develop. Great job! I can't wait to get this one merged in.
const slots = context ? context.slots() : this._renderProxy.$slots | ||
|
||
// ensure consistent ordering of slots (default first, then alphabetical) | ||
const sortedSlotEntries = Object.entries(slots) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice usage of Object.entries
? -1 | ||
: slotNameB === 'default' | ||
? 1 | ||
: slotNameA.localeCompare(slotNameB) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have used a simple >
and <
for the string compare. Not sure it makes a big difference - it is common to use characters like á
in code? (my language does not have those characters, so I have never seen this before).
If we are doing to support using localeCompare
, maybe we should have a test containing a á
character vs an a
character. Although probably not strictly necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought, this kind of ternary is super confusing. I would deff advise for some sort of reordering or other.
test/specs/shallow-mount.spec.js
Outdated
|
||
it('renders named slots for functional components', () => { | ||
const localVue = createLocalVue() | ||
localVue.component('child', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice job! it's easy to forget the case of functional components.
@@ -86,31 +86,48 @@ export function createStubFromComponent( | |||
// ignoreElements does not exist in Vue 2.0.x | |||
if (Vue.config.ignoredElements) { | |||
Vue.config.ignoredElements.push(tagName) | |||
if (Vue.config.ignoredElements.indexOf('template-stub') === -1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the template-stub
stays as <template-stub />
in the finished render, correct?
@chriswa left some comments, let me know what you think. Excited to get this one in. |
? -1 | ||
: slotNameB === 'default' | ||
? 1 | ||
: slotNameA.localeCompare(slotNameB) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought, this kind of ternary is super confusing. I would deff advise for some sort of reordering or other.
@@ -86,31 +86,48 @@ export function createStubFromComponent( | |||
// ignoreElements does not exist in Vue 2.0.x | |||
if (Vue.config.ignoredElements) { | |||
Vue.config.ignoredElements.push(tagName) | |||
if (Vue.config.ignoredElements.indexOf('template-stub') === -1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the template-stub
stays as <template-stub />
in the finished render, correct?
: slotNameA.localeCompare(slotNameB) | ||
) | ||
|
||
const children = sortedSlotEntries.map(([slotName, slotChildren]) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this should render the default slot, and all others as children of the template-stub
? Wont this be a super breaking change for snapshots?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, this will break all snapshots using the original behavior. We probably should have some snapshot tests in VTU as well to capture these regressions. But then we will need to move to Jest, I think? Or we can do a manual comparison between strings.
Probably not the biggest deal, we just need to make sure that's clear in release notes. Something like:
NOTE: You will need to update all snapshots when updating.
f437d08
to
97228ce
Compare
// | ||
// return [] | ||
// } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So @lmiller1990 I'm mostly concerned about why no tests break when I comment this out
hyphenate, | ||
keys | ||
hyphenate | ||
// keys |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commented out for formatting until we can figure out how to merge everything in.
// this.$options.parent._vnode.data.scopedSlots[x]() | ||
// ) | ||
// } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was initially how I expanded out and merged dev and this PR, but was failing so I commented it out and reverted to mainly this PR's version of rendering slots
@@ -130,7 +136,11 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'shallowMount', () => { | |||
expect(wrapper.find({ name: 'Foo' }).exists()).to.equal(true) | |||
expect(wrapper.find('.new-example').exists()).to.equal(true) | |||
expect(wrapper.html()).to.equal( | |||
'<foo-stub>\n' + ' <p class="new-example">text</p>\n' + '</foo-stub>' | |||
'<foo-stub>\n' + | |||
' <template-stub slot="newSyntax">\n' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The need to update all the assertions with template-stub
worry me. This will be a breaking change :/
Hi! As mentioned here, we're not merging this before v1 is released. Just in case someone stumbles upon this PR – there are 2 workarounds:
thanks for the effort put on this one, though! 🤗 |
I thought about this a bit more, I'm not convinced this behavior is actually correct. I think children of stubbed components, including slots, should not be rendered. I am in favor of closing this as a wontfix. We need to figure out what shallowMount should/shouldn't do. |
This looks to be a significant a breaking change at this point. I also am not sure this actually makes sense - I think stubbed children should not render their slots. I'm going to close this one. Thanks for the work - sorry the team was unresponsive and this didn't get the attention it should have when the PR was opened. We are looking to a v1 release soon, and we will revisit shallowMount and what it should be rendering for the Vue 3 integration. |
Hi @lmiller1990 , just sharing my opinion here regarding your thought:
I'm afraid if there's multiple interpretation of defining this use-case. I agree that generally, However, slot is different. Slot is a way for the parent to "inject" the content they expect in the child component. The child is responsible for the placement of the slot, but it's the parent responsibility to ensure the content injected are working as expected. Thus, testing the slot content is the parent responsibility. For example, when we have a component that needs to load a modal component like b-modal with specific content for the named slot: // parent component
<template>
<b-modal v-model="visible">
<template #modal-header>
{{ title }}
<button @click="onClickModalHeader">
</template>
</b-modal> On testing the parent component, I don't care with how the note: example with jest const parentComponentWrapper = shallowMount(parentComponent);
parentComponent.setData({ title: 'The Parent Title' });
const modal = parentComponent.findComponent({ name: 'BModal' });
expect(modal.html()).toContain('The Parent Title'); // better if can assert which slot it's expecting
modal.find('button').trigger('click')
// assert the side effect from `onClickModalHeader` The idea is, slots are used by parent for the parent's logic, and we need to test them too. Using I beg you to reconsider 🙇 and let me know if my example above doesn't makes sense or not applicable. Thank you 🙇 |
This is taken care of in Vue 2. Default slots are rendered behind a flag, named slots only via a special helper. :) |
Thanks to respond @dobromir-hristov
Can you clarify what's the special helper you mentioned about? Is it the manual stub that @danieltian suggested: const wrapper = shallowMount(RootComponent, {
stubs: { ChildComponent }
}
expect(wrapper.find(ChildComponent).text()).toContain('some text'); |
Sort of. In shallowMount default slots can be auto rendered, but not named and scoped slots. We cant know that data, as it is deeply buried in the render function tree of the components you are stubbing. Does it make sense? I tried to make this for a while, bit there is just no sensible way to do render all slots, while still stubbing. |
@lmiller1990 @dobromir-hristov I've seen the discussion has been going on heavily in #1307 which has better explanation than mine. My appreciation to you and the core team for the stable release, and taking in the concern of this issue ❤️
Yes, seems like the issue here is more towards the implementation, not the goal behind. I agree with @lmiller1990 suggestion that this behavior can be made as optional. Again, thank you! 🥇 |
resolves #1307