Skip to content

The returned container is one level too high compared to other frameworks #313

Closed
@mcous

Description

@mcous

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
  • renderOptions.container is the element that target is inserted into
    • Defaults to document.body
  • result.container returns renderOptions.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 call container.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 to baseElement
  • Return baseElement (root) as result.baseElement
  • Return target (the wrapping <div>) as result.container
  • If target is provided, use it as the baseElement 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 to container
    • 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 and renderOptions into a single options object
    • Pro: aligns a little better with vue-testing-library
    • Con: runs the risk of conflicts between Svelte options and testing-library options

Relates to #312

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions