Description
Overview
The render
function provides two options for changing how a component gets rendered into the DOM: componentOptions.target
and renderOptions.container
. It returns a result.container
element.
const { container } = render(Component, componentOptions, renderOptions)
componentOptions.target
is the target element the component is rendered into- Defaults to an empty
<div>
that we create
- Defaults to an empty
renderOptions.container
is the element thattarget
is inserted into- Defaults to
document.body
- Defaults to
result.container
returnsrenderOptions.container
These option names and their behaviors are different in confusing ways from other testing-library
frameworks that make svelte-testing-library
a little more difficult to use than its siblings. The primary issue is that by default we return document.body
rather than the created div
for result.container
.
Expectations
Value | Svelte | React / Preact / Vue |
---|---|---|
Document root option | container |
baseElement |
Mount point option | target |
container |
Returned container | Document root | Mount point |
const { container, component } = render(Comp, { foo: 'bar' })
<body> <!-- container (baseElement) -->
<div> <!-- target (container) -->
<Comp foo="bar" /> <!-- component -->
</div>
</body>
The main issue I have is result.container
is one level higher than I expect. The most common way I notice this is that I expect container.firstChild
to be my component's first node. Instead, it is container.firstElement.firstElement
.
This expectation comes from the react-testing-library docs:
container
The containing DOM node of your rendered React Element (rendered using ReactDOM.render). It's a
div
. This is a regular DOM node, so you can callcontainer.querySelector
etc. to inspect the children.Tip: To get the root element of your rendered element, use
container.firstChild
.
Proposed changes
Since there are definitely breaking changes on the horizon due to Svelte moving on from v3, I think there's an opportunity here to align the render
API with all the other libraries.
I think a small but effective change set would be:
- Rename the existing
container
option tobaseElement
- Return
baseElement
(root) asresult.baseElement
- Return
target
(the wrapping<div>
) asresult.container
- If
target
is provided, use it as thebaseElement
and do not create/insert any other elements- This is the same behavior as (react|preact|vue)-testing-library
I think there are a few other changes we could consider:
- Rename the existing
target
option tocontainer
- Pro: this would align better with the name of the return value
- Con: would misalign us with the name of the Svelte option
- Collapse
componentOptions
andrenderOptions
into a singleoptions
object- Pro: aligns a little better with
vue-testing-library
- Con: runs the risk of conflicts between Svelte options and testing-library options
- Pro: aligns a little better with
Relates to #312