vitest-dev / vitest-dev/vitest

Web Component `<slot />` support for locators

Open
#8,693 6 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

upstream
Dominant language
TypeScript
Stars
17.1k
Forks
2k
Avg merge
1d 22h
Merged PRs (30d)
94

Description

Clear and concise description of the problem

The locators currently do not follow the slots of Web Components, which is pretty unintuitive, especially when using the accessibility tree in the browser dev tools as primary source.

Consider the following custom element:

<my-list>
  <template shadowrootmode="open">
    <ul>
      <slot></slot>
    </ul>
  </template>

  <li>Item 1</li>
</my-list>

My expectation would be that I can do the following:

const item = page.getRyRole('list')
  .getByRole('listitem')

But that does not work because getByRole('list') finds the <ul> and the locators don't chain through the slot.

I created a reproduction repo to play around with this.

Suggested solution

Have locators follow slots and thereby the accessibility tree

Alternative

I added one possible workaround in the reproduction repo. This works for simple cases, does not come without issues:

  • It's not really intuitive
  • it requires the tag-name of the custom element (which could be considered an implementation detail)
  • lt falls apart for more complex Web Components:
Example
<my-dialog>
  <template shadowrootmode="open">
    <dialog aria-label="Custom element list">
      <header>
        <slot name="header"></slot>
      </header>
      <slot></slot>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </dialog>
  </template>

  <div slot="header">
    <button aria-label="Close">X</button>
  </div>

  <div slot="footer">
    <button>Close</button>
  </div>
</my-dialog>

With chaining through slots this would be possible:

const item = page.getRyRole('dialog')
  .getByRole('header')
  .getByRole('button', { name: 'Close' })

But without the only way would be via the have to start in the <my-dialog> component and then probably use something like [slot="header"] to get to the right button.

Additional context

This is a long-standing issue with the Playwright locators, but they consider this a breaking change and don't want to fix this without enough upvotes. I summarized everything in this comment. Since the browser mode is still fresh, I hope this change is possible in Vitest.

On another note: I considered opening this issue in the ivya repo, but figured other people looking for this would probably start here.

Validations

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked reproduction repo, vitest-slot-feature-request, and compare its locator behavior with the documented Web Component examples. Define done as locators chaining through open shadow-root slots so the list and dialog examples resolve their slotted descendants, including named slots.

Written by the indexing model from the issue text.

Assessment

Tech stack
playwright, typescript
Domain
testing-qa, web-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.