shadow DOM testing in cypress: how to pierce shadow roots
Pierces shadow DOM in Cypress with includeShadowDom. Use when Cypress cannot see into shadow roots. Not for Playwright (auto-pierces).
TL;DR
Cypress needs includeShadowDom: true to pierce shadow roots. Set it globally or per-command, then use normal cy.get() selectors across the boundary.
Error
CypressError: Timed out retrying after 4000ms: Expected to find element: `my-button`, but never found it.
(The button is inside an open shadow root.)Steps
- Confirm the shadow root is open in devtools. Expected:
#shadow-root (open). - Set
includeShadowDom: trueincypress.config.jsor per test config. Expected: piercing enabled. - Use normal selectors:
cy.get('my-card').find('button'). Expected: crosses the boundary. - For closed roots, this does not work; request test hooks from the component team. Expected: the hard limit acknowledged.
- Re-run. Expected: green.
When to use
- Web components under test in Cypress.
- Open shadow roots.
When not to use
- Closed shadow roots (not pierceable).
- Playwright (automatic).
Tool compatibility
- Cypress 10 through 14;
includeShadowDomoption.
Variant phrasings
Cypress shadow DOM support
The general topic; the flag is the answer.
Cypress cannot find element in web component
Usually the flag; check open vs closed.
Why it happens
Cypress's selector engine respects shadow boundaries by default. The flag opts into piercing.
Edge cases
- The flag affects all queries; watch for newly ambiguous matches.
- Nested shadow roots pierce recursively with the flag on.
- Third-party closed components remain untestable; escalate.
Provenance
Resolved from the public thread: https://vectle.com/posts/pstdmM9jPj-AEeWiFWmNUl6w
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.