-
Notifications
You must be signed in to change notification settings - Fork 71
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
Implement visual tests for KButton component #710
Implement visual tests for KButton component #710
Conversation
Percy Visual Test ResultsPercy Dashboard: View Detailed Report Environment:
Instructions for Reviewers:
|
docs/pages/testing-playground.vue
Outdated
<!-- Render default slot if provided --> | ||
<template v-if="slots.default"> | ||
<!-- eslint-disable-next-line vue/no-v-html --> | ||
<span v-html="slots.default"></span> |
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 should this be in as span? I think a div would be more appropiate in case we need to add more elements inside
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.
If I take the KButton test with default slot as an example, if you use div, the button will become twice the size, with the upper part showing slot content and the lower part showing the content passed to button itself. That's the reason for using span here.
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.
Hmm I see, but there could be some components where a span could also be a problem. What if we add something like a "wrapperEl" prop that defines the element container, and a "content" that defines the v-html prop? Any other idea is welcome 👐.
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 think we can combine both and have something like:
{
slots: {
default: {
element: "div", // or any vue component like KIcon
elementProps: {
class: "some-class"
},
innerHTML: "<div> Some nested <a>content</a> </div>"
}
}
}
docs/pages/testing-playground.vue
Outdated
</template> | ||
<!-- Render named slots passed to the component --> | ||
<template v-for="(slot, name) in namedSlots" #[name]> | ||
<component :is="slot.content" v-bind="slot.props" :key="name" /> |
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 think it would be better if we follow the same pattern in both default slot and named slot, I would vote to render it inside a v-html. Or in any case, if rendering inside a div gives any error, we can be flexible and provide both options. If slots.name is String, then render it inside a v-html, if not, we can render it as you are doing it here. What do you think?
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.
Won't the named slots be other components that are being nested in a particular component? In that case they'll always have a name and specific props attached to them just like the parent component, which is being handled correctly in the current scenario.
I thought that default slots are used to handle the case in which slots.name is expected to be a string. I may be wrong though; I am not fully aware of how slots are used throughout KDS.
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.
Not necessarily, we can have html elements that are not vue components as part of named slots (e.g. this #divider in KListWithOverflow, It is a correct Vue syntax, there are actually no differences in the restrictions of what we can do in the default slot vs named slots.
@@ -1,23 +1,24 @@ | |||
import percySnapshot from '@percy/puppeteer'; | |||
|
|||
export async function renderComponent(component, props) { | |||
export async function renderComponent(component, props, 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.
Here we need to add a jsdoc explaining these props, and explaining the structure slots should follow
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.
Sure, will get it done 👍
@@ -40,8 +41,30 @@ export async function renderComponent(component, props) { | |||
global.expect(isComponentRendered).toBe(true); | |||
} | |||
|
|||
export async function takeSnapshot(name) { | |||
export async function takeSnapshot(name, options = {}) { |
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.
Here would be good also to have some jsdoc, and let users know what options could we use (I think it should be a lot of options that percySnapshot receives, in any case we could link to their documentation).
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.
Sure 👍
it('renders correctly with default props', async () => { | ||
await renderComponent('KButton', { text: 'Test Button' }); | ||
await takeSnapshot('KButton - Default'); | ||
it('renders correctly with different appearances', async () => { |
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.
IMO each snapshot should be a test case. Unit test cases should be simple and test just one thing. If we want to group multiple test cases like for example with the disable state, we could use a describe block inside de discribe.visual block and group them.
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, if I am getting it correctly, for the case where we are testing different appearances of KButton for example, we need to write them all in separate it
blocks and group those it blocks in one describe
block?
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.
Yes, although Im not sure if we should group them as "different appearances", in general all snapshots are different appearances.
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.
Oh different appearances means different values for the appearance
prop. I hadnt get it, in that case its up to you if it makes sense to group them, you can group them, if not its fine too.
Hi @AlexVelezLl. I've updated the PR based on the suggestions 👍 |
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.
Thanks @KshitijThareja!! Code looks good to me, and snapshots are working as expected! I think we have reach to a very neat and flexible api for slots elements, which is super great. I left just a minor observation, once it is fixed, please feel free to hit that merge button.
We are almost thereee!!! Congratulations 🎉 🎉 🎉 🎉.
primary: true, | ||
appearance: 'raised-button', | ||
}); | ||
await takeSnapshot('KButton - Primary Raised Button', { widths: [400], minHeight: 512 }); |
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.
As we will probably have the same sizes for (almost) all the screenshots of a single component, I think we can make this a constant object defined in the context of the describe.visual block and use the same options object thoughout the tests.
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've made the changes as requested ✅
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.
Thank you!!
3bddaab
into
learningequality:gsoc/visual-testing
Description
This PR aims to introduce concrete visual tests for the
KButton
component, supplemented by modifications to the existingtesting playground
file and therenderComponent
function to allow for usage of slots in the visual tests.Issue addressed
#689
Addresses #PR# HERE
Before/after screenshots
Changelog
[#PR no]: PR link
Steps to test
yarn test:visual
to execute visual testsAt a high level, how did you implement this?
This was accomplished by referring to the Puppeteer documentation for implementing abstract methods for interacting with the components. The changes to the render function and playground file were made in order to render the components if slots were passed from within the tests.
Testing checklist
Reviewer guidance
After review
CHANGELOG.md
Comments