Access Shadow Root Elements
Overview
The shadow_root_elements
function locates elements within one or more nested Shadow DOM (shadow root) levels on a web page. It is used when target elements are encapsulated inside Web Components or browser-internal pages that utilize Shadow DOM, where standard document queries (CSS or XPath) cannot access them directly.
Internally, the function sequentially finds each shadow host and then accesses its shadow DOM, for example, using Selenium's shadow_root
method or a JavaScript call such as driver.execute_script('return arguments[0].shadowRoot', host)
.
This feature should be used when the required element is hidden within an open-mode shadow root and must be accessed through its host elements. Note that Element.shadowRoot
only returns the shadow DOM if the root is open; therefore, this function cannot access closed shadow roots.
This capability enables traversal through nested Shadow DOMs to locate target elements, which is essential for modern web applications that rely on encapsulation using Shadow DOM.
Key Concepts
- Shadow Host: Element that contains a Shadow Root.
- Shadow Root: An encapsulated subtree attached to a Shadow Host.
- Parent Scope: An optional container element for Shadow Hosts, specified using the
parent
parameter.
User Input Structure
Users define Shadow DOM traversal using step data by following these rules:
1. Shadow Root Parameters
- Format:
sr <index> <type> parameter
- index: An integer (e.g., 1, 2, 3.....) representing the nesting level. If omitted, it defaults to
sr 1
. - type: Use
element parameter
to specify a Shadow Host orparent parameter
to define the container scope.
- index: An integer (e.g., 1, 2, 3.....) representing the nesting level. If omitted, it defaults to
- Allowed Attributes:
id
,class
,tag
and any other attribute (e.g.,title
,data-qa
).- Text selectors are not supported; use attribute-based selectors instead.
Example:
["id", "sr 1 parent parameter", "container"]
["tag", "sr 1 element parameter", "user-profile"]
2. Target Element Parameters
Define the final element within the deepest Shadow Root using the standard element parameter
syntax, using only CSS selectors.
Example:
["class", "element parameter", "submit-button"]
Traversal Workflow
-
Process Parameters
- Group the
sr
parameters based on theirindex
andtype
(eitherelement
orparent
). - Validate that indices are unique and follow a sequential order.
- Group the
-
For Each Shadow Level
- Parent Scope (if provided)
- Locate the parent container using a CSS selector.
- Search for the Shadow Host within the specified parent.
- Shadow Host
- Construct a CSS selector using element attributes.
- Locate the element within the current root or parent scope.
- Enter Shadow Root
- Access it using
element.shadowRoot
. - Fail the operation if no Shadow Root exists.
- Access it using
- Parent Scope (if provided)
-
Locate Target Element
- After traversing all Shadow Roots, proceed with the operation:
- Construct the CSS selector for the final element.
- Return the element(s) from the deepest Shadow Root.
- After traversing all Shadow Roots, proceed with the operation:
Rules and Restrictions
-
Selector Types
- Shadow Hosts: Use CSS selectors only; XPath and text-based selectors are not supported.
- Target Elements: Except for the first level, use CSS selectors only; before entering the Shadow DOM, there are no restrictions on selector type.
-
Index Handling
- If the index is omitted,
sr 1
is assumed implicitly. - Consecutive indices are required (e.g.,
sr 1
must be followed bysr 2
). - A parent is not required; one level may contain a parent, while another level may not.
- If the index is omitted,
-
Parent Scoping
- The parent must exist within the current root, either the main document or an active Shadow Root.
- The Shadow Host is searched within the specified parent element.
-
Error Cases
- Shadow Host was not found.
- The element has no Shadow Root.
- The index or parameter format is invalid.
Example Use Case
HTML:
<div id="app"> <!-- Parent for 1st Shadow Host -->
<user-card> <!-- Shadow Host (Level 1) -->
#shadow-root
<!-- Inside user-card's Shadow Root -->
<div class="profile"> <!-- Shadow Host (Level 2) -->
#shadow-root
<button class="save">Save</button> <!-- Target -->
</div>
</user-card>
</div>
Step Data:
shadow_root_ds = [
["id", "sr 1 parent parameter", "app"], # Parent of 1st Shadow Host
["tag", "sr 1 element parameter", "user-card"], # Shadow Host (Level 1)
["class", "sr 2 element parameter", "profile"] # Shadow Host (Level 2)
]
element_ds = [
["class", "element parameter", "save"] # Target element
["click", "selenium action", "click"]
]
The user must provide all of this data in a single action.
Traversal:
- Find the parent element
#app
, then locate the<user-card>
element within it. - Enter the Shadow Root of the
<user-card>
element. - Locate the
.profile
element and enter its Shadow Root. - Locate the
.save
button. - Click the Save button.
Page DOM (main document)
└─ Shadow Host (sr-1) [e.g. <custom-element id="outer-host">]
└─ Shadow DOM Level 1
└─ Shadow Host (sr-2) [e.g. <inner-element class="inner">]
└─ Shadow DOM Level 2
└─ [Target Element, e.g. <button>]
Why are only CSS selectors used?
- Shadow DOM encapsulation prevents XPath from traversing its internal structure.
- CSS selectors pierce Shadow Boundaries via
::shadow
or/deep/
deprecation. - Ensures consistency and compatibility across browsers.
Troubleshooting Tips
- Shadow Host not found
- Verify that the parent scope exists within the current root.
- Check for typos in attribute names and values.
- No Shadow Root:
- Ensure the element is a Shadow Host (verify using DevTools).
- Use the
allow-hidden
option if the element is not yet rendered.
- Index Mismatches:
- Explicitly specify indices (e.g., use
sr 2
instead of justsr
).
- Explicitly specify indices (e.g., use
Test Case Scenario of "Access Nested Shadow Root Elements"
Title
Access Nested Shadow Root Elements
Sample test case: TEST-8216 Access Nested Shadow Root Elements
Scenario Overview
This test case is designed to verify the ability to interact with elements within nested shadow DOMs on a specific webpage. The test involves navigating through different levels of shadow DOMs to find and interact with specific elements, ensuring that the expected connection status messages are displayed correctly.
Steps to Follow
- Navigate to the website using the Selenium go to link action.
- Access the nested shadow DOM to locate the element with tag
team-container
and titleUI/UX Designer
. - Click the button with class
connect-btn
inside that element. - Validate the text You are now connected with Alice Benjin in the element with ID
connectionStatus
. - Locate the nested element using parent ID
parentDiv
and child IDteamRoot
with the nameBob Smith
. - Click the
connect-btn
inside that structure. - Validate the text You are now connected with Bob Smith in
connectionStatus
.
Actions
1. Enter Nested Levels and Click
Parameter | Type | Value |
---|---|---|
tag | sr 1 element parameter | team-container |
title | sr 2 element parameter | UI/UX Designer |
class | element parameter | connect-btn |
click | selenium action | click |
2. Enter Nested Levels by Parent and Click
Parameter | Type | Value |
---|---|---|
id | sr parent parameter | parentDiv |
id | sr element parameter | teamRoot |
name | sr 2 element parameter | Bob Smith |
class | element parameter | connect-btn |
click | selenium action | click |
Expected Result
- The automation correctly accesses and interacts with elements within nested shadow roots, and the intended outcome, such as confirmation message, is successfully displayed.
Common Errors and Fixes
- Error: Unable to access the shadow root.
- Fix: Confirm that the shadow root is open. Closed shadow roots are not accessible via standard DOM traversal.
- Error: The locator or selector is incorrect.
- Fix: Double-check the tag names, attributes (e.g.,
id
,title
,name
), and the hierarchy used to locate the target element.
- Fix: Double-check the tag names, attributes (e.g.,
- Error: Timing issue: the element is not yet rendered.
- Fix: Add appropriate wait or delay steps to ensure the shadow DOM and its content are fully loaded before access.
- Error: Action not performed (e.g., click fails).
- Fix: Ensure that the element is interactable (visible, enabled, in view) and that focus or scroll steps are used if needed.
Additional Tips for "Access Nested Shadow Root Elements"
- Traverse each shadow layer step-by-step using
shadowRoot.querySelector(...)
. - Ensure the shadow root is open, as closed roots cannot be accessed.
- Use stable selectors such as,
id
,title
, orname
for accuracy. - Add wait or delay steps to ensure the shadow DOM content is fully rendered.
- Validate the presence of elements at each shadow level before proceeding.
- Log each step during shadow root access for easier debugging.
Error Handling for "Access Nested Shadow Root Elements"
-
Error: Cannot read properties of null (reading
shadowRoot
).
Possible Cause: The host element does not exist and is not yet rendered when the script attempts to access it.
How to Fix: Use an explicit wait to ensure the host element is present in the DOM before accessing itsshadowRoot
. -
Error: The shadowRoot is null.
Possible Cause: The element does not have an open shadow root or the script is trying to access it from an unsupported context.
How to Fix: Ensure that the host element has an open shadow root by verifying its presence and checking that it usesmode: 'open'
in the web component definition. -
Error: Cannot find the element inside the shadow root.
Possible Cause: An incorrect or incomplete locator is used to identify the element within the shadow root.
How to Fix: Access each level of the nested shadow root sequentially before locating the target element. -
Error: The element is not interactable.
Possible Cause: The element is not visible or enabled on the page when the interaction is attempted.
How to Fix: Wait until the element is visible and enabled before performing any action on it. -
Error: Security Error: Access to the Shadow DOM is restricted.
Possible Cause: Tried to access a closed shadow DOM that is purposely hidden.
How to Fix: Request the developer to change the shadow DOM's mode to open instead of closed to allow access.