Open alejandroiglesias opened 3 years ago
Hi, I just stumbled upon the same problem. A little investigation revealed that this was made possible with this PR: https://github.com/bahmutov/cypress-svelte-unit-test/pull/33
but was removed later ... at least it's gone by the update to svelte3: https://github.com/bahmutov/cypress-svelte-unit-test/pull/41
You (and I) probably could work around the problem by creating a test specific intermediary component, that wraps your component under test and provides the slots ... not nice but it should work.
I found a solution to test slots on this Svelte issue comment. The idea behind it is to add a createSlots
helper function as specified in such comment and use it to populate the $$slots
prop of the component. I put such helper in cypress/helpers.js
as an exported function:
export function createSlots(slots) {
// ...
}
And then import it and use in the spec:
// Import helper function in spec:
// import { createSlots } from '../../../cypress/helpers'
mount(
Content,
{
props: {
$$slots: createSlots({ default: document.createTextNode('Content slot') }),
$$scope: {}
}
}
)
In this case, I pass a text node with the content Content slot
, but obviously you can pass any element. I don't know why the $$scope
prop is required but it doesn't work without it. A bit hacky solution but it works just fine. Hopefully, we will have a cleaner solution in the future.
Now the challenge I'm facing is how to pass another component into the slot? For example, to test components that are meant to be used as:
<Dropdown>
<DropdownTrigger />
<DropdownList />
</Dropdown>
Where the Dropdown component just renders what's passed into the default slot, but then it also creates context, and child components interact with such context, so no possibility to fully test the whole behavior when testing them in isolation. Any suggestions?
Would svelte:component
be what you're looking for? https://svelte.dev/docs#svelte_component
Can pass a comonent type in and render and instance of it.
@JohnnyFun how do you pass a svelte:component
to the mount
function?
Oh sorry, I misunderstood what you were asking. The way I've been doing it is by wrapping the component(s) I want to test in a wrapper components with some example usages. Then I simply mount that wrapper component instead of the underlying component. I put my "wrapper" components in "./cypress/fixtures/components".
Something like this:
<h3>Simple example</h3>
<MyListComponent {items} let:item dataTest="simple-example">
<strong>{item.name}</strong>
<em>{item.desc}</em>
</MyListComponent>
<h3>Some other example</h3>
<MyListComponent {items} let:item dataTest="other-example">
...
</MyListComponent>
<script>
export let items
</script>
Makes it really nice when building up a component too. Kind of like an interactive style guide that shows how to use your components and what the expected behavior of them is.
I see what you mean. I ended up doing that in some cases since the team already has wrapper components for rendering in Storybook.
Hi, I cannot seem to find a way to test component slots. The examples in the readme seem outdated since I cannot seem to make them work. Can you please give an updated example? I appreciate your help in advance. Best regards.