Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: locator does not find element under slot in shadow dom #33547

Open
jeff-an opened this issue Nov 11, 2024 · 5 comments
Open

[Bug]: locator does not find element under slot in shadow dom #33547

jeff-an opened this issue Nov 11, 2024 · 5 comments

Comments

@jeff-an
Copy link

jeff-an commented Nov 11, 2024

Version

1.48.2

Steps to reproduce

  1. Clone https://github.com/jeff-an/playwright-shadow-dom-repro/tree/main
  2. npm i
  3. npx playwright test
  4. Notice test failure in example.spec.ts

Expected behavior

Locator should resolve to the element in the open shadow DOM

Actual behavior

Locator throws timeout error (locator never resolves to the element on the page).

Additional context

I am using this library to check the CSS selector I have provided. The CSS selector is effectively a direct path from the root body to the element in the shadow DOM. querySelectorDeep indeed returns the correct element, but playwright can't seem to find it.

Note that the test DOES work if I remove one of the ">" direct descendent operators in the CSS selector, specifically the one that "goes through" the slot. So like:

componentreference-bundles:nth-child(1) > componentreference-tile-viewer:nth-child(1) -> componentreference-bundles:nth-child(1) componentreference-tile-viewer:nth-child(1)

It does not work if I explicitly include the slot in the selector. What is the best practice here? I'd like to keep the > to be as specific as possible in my selector and guarantee a unique path.

Seems related to #29357 but I'm not knowledgeable enough about slots to articulate why. Would love to do this without injecting a ustom selector library if possible.

Environment

npx envinfo --preset playwright

  System:
    OS: macOS 14.4
    CPU: (14) arm64 Apple M3 Max
    Memory: 145.00 MB / 36.00 GB
  Binaries:
    Node: 20.9.0 - ~/.nvm/versions/node/v20.9.0/bin/node
    Yarn: 1.22.21 - ~/Library/pnpm/yarn
    npm: 10.9.0 - ~/.nvm/versions/node/v20.9.0/bin/npm
    pnpm: 8.7.6 - ~/Library/pnpm/pnpm
  IDEs:
    VSCode: 1.95.1 - /Applications/Visual Studio Code.app/Contents/Resources/app/bin/code
  Languages:
    Bash: 3.2.57 - /bin/bash
  npmPackages:
    @playwright/test: ^1.48.2 => 1.48.2
@pavelfeldman
Copy link
Member

What is the best practice here? I'd like to keep the > to be as specific as possible in my selector and guarantee a unique path.

The best practices would be here: https://playwright.dev/docs/best-practices#best-practices. You should never rely on css locators if at all possible and should make them as lax as possible, as opposed to making them strict.

@jeff-an
Copy link
Author

jeff-an commented Nov 11, 2024

I was asking about the best practices regarding slots specifically, not in general.

We intentionally want a strict locator since it is being used ephemerally over the course of a single test run. Effectively, we already have a JS reference to the element and would like to turn it into a CSS selector that Playwright can action on.

@pavelfeldman
Copy link
Member

Effectively, we already have a JS reference to the element and would like to turn it into a CSS selector that Playwright can action on.

I don't think we have a good solution for your use case. It is a little hard to reason about what is wrong and what is not - your page is using Polymer that rewrites important functions such as querySelector and querySelectorAll with non-standard, incompatible implementations. So most of the bets are off when it comes to the css selectors.

If your page is non-reactive, you could use page.evaluateHandle to return ElementHandle for your JS reference. You can click that handle, etc. But that defeats the purpose of Playwright where you should only use selectors based on the accessible content, with the powers of auto-waiting, etc. Otherwise Playwright is no better than other tools and your tests will be reliably flaky.

@jeff-an
Copy link
Author

jeff-an commented Nov 12, 2024 via email

@pavelfeldman
Copy link
Member

I'm confused as to what is the intended way is to write a locator that finds an element under a slot

CSS selectors follow the standard DOM semantics + they pierce shadow roots as fragments. So they will work the same way as document.querySelector with the exception of they will pierce shadow roots See https://playwright.dev/docs/locators#locate-in-shadow-dom for docs. Playwright does not perform node distribution and does not operate the notion of the composed tree by design, so slots have no meaning for it.

Or are you saying there are no standard definitions at all and we should use a custom css selector implementation?

There is no spec for CSS selectors because it matches the definition of document.querySelector. As a convenience feature it will pierce shadow as well.

There just seems to be this narrow issue affecting CSS selectors using the descendant operator, so this doesn't feel like a "playwright is fundamentally incompatible with this page" idea.

It is hard to tell what will break. All I can say is that Playwright does use querySelector under the hood, in different js worlds. Main world will have it redefined by Polymer, so some scenarios will definitely fail. Use it at your own risk. For example, the selector that you have works with page.locator.evaluate and does not work with page.locator.isVisible for that reason. Those run in different worlds.

Seems like there was some similar confusion on this issue #29357

Yep, the explanation there still stands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants