Test Svelte Component Slot Using svelte-htm
Mar 1, 2023 · 3 min readThis is a short guide on how to test a Svelte component with slot using the svelte-htm library.
Introduction
At the time of writing this article, there’s no way to pass in slot content to Svelte component using svelte-testing-library.
The workaround for this is usually by creating a separate dummy component that put some elements inside the slot and test the dummy component instead.
For example, say that we have a Button.svelte
component.
<button> <slot /></button>
To test if the component inside the slot is rendered properly, we have to create a dummy component that use Button.svelte
. We’ll call this component TestButton.svelte
.
<script> import Button from ./Button.svelte;</script>
<Button> <div data-testid="slot-component">PLACEHOLDER</div></Button>
Finally, we can test the component.
// Other importsimport TestButton from "./TestButton.svelte";
describe("Button", () => { it("should render component inside slot properly", () => { render(TestButton); expect(screen.getByTestId("slot-component")).toBeInTheDocument(); });});
That works, but it’s certainly not a fun experience, and your project is probably going to be littered by bunches of dummy component.
Solution
The solution to this problem is to use svelte-htm
.
svelte-htm
allows us to write our Svelte components with JSX-like syntax. It completely eliminates our need of dummy component. We can test our Svelte component just like how we test components from JSX-based framework like React.
Now, let’s refactor our test using svelte-htm
.
// Other importsimport html from `svelte-htm`;import Button from './Button.svelte'
describe("Button", () => { it("should render component inside slot properly", () => { render(html` <${Button}> <div data-testid="slot-component">PLACEHOLDER</div> </${Button}> `); expect(screen.getByTestId("slot-component")).toBeInTheDocument(); });});
That’s all we need to do. Felt much more natural, right?
You might think that the syntax is still not as nice as testing JSX component, but it’s pretty close, and I would consider this solution a major leap compared to the dummy component solution.
In case you’re wondering how the test would look like for JSX component:
// Other importsimport Button from "./Button.tsx";
describe("Button", () => { it("should render component inside slot properly", () => { render( <Button> <div data-testid="slot-component">PLACEHOLDER</div> </Button>, ); expect(screen.getByTestId("slot-component")).toBeInTheDocument(); });});
Testing Named Slot
We can test named slot just like how we test normal slot in the examples above.
Here is an example:
Let’s change our Button.svelte
component to use named slot.
<button> <div> <slot name="icon" /> </div> <div> <slot name="label" /> </div></button>
Now, to test it:
// Other importsimport html from `svelte-htm`;import Button from './Button.svelte'
describe("Button", () => { it("should render component inside slot properly", () => { render(html` <${Button}> <div slot="icon">ICON</div> <div slot="label">Click me!</div> </${Button}> `); // assertions here ... });});
You get the idea :)
Wrap Up
That’s it for this post. You should be able to test your Svelte components that have slot now. Happy testing!