`How can you effectively navigate and engage with Shadow DOM elements using Watir?`

I am trying to access the page chrome://downloads/ to verify that a file has been downloaded, but it is using Shadow DOM.

I came across an article on how to access DOM Elements With Selenium Webdriver. You can read it here.

However, the code in the article is written in JavaScript.

driver.executeScript("return $('body /deep/ <#yourSelector>')")

driver.executeScript("return $('body /deep/ ._mm_column')[0].textContent").then(function(title){
  title.should.contain(segmentName);
});

After converting the syntax to Watir, my code runs without errors but does not provide the expected results:

execute_script("return $('<#file-link>')")

execute_script("return $( '<:contains(test-file.mp3)>')")

When I check the console, I only see nil values.

See image here

What I really want is to ensure that the element is present on the page.

Answer №1

In a previous response that titusfortner had provided before it was deleted, Selenium Easy shared an article titled "Working with Shadow DOM Elements using Webdriver". This article revealed how to access shadow elements through JavaScript and interact with their children as usual.

However, in order to make it work with Watir, I had to make modifications to the Watir::Browser class. While this is a temporary solution, I am exploring options for a more permanent fix. Here is an example of how it currently works:

require 'watir'

# Custom implementation to handle checking the tag name of the shadow root
class Watir::Browser
  def wrap_element(scope, element)
    Watir.element_class_for(element.tag_name.downcase).new(scope, element: element)
  rescue Selenium::WebDriver::Error::UnknownError # need a better rescue
    Watir::Element.new(scope, element: element)
  end
end

def expand_root_element(element, browser)
    browser.execute_script("return arguments[0].shadowRoot", element)
end

browser = Watir::Browser.new

# Simulating a download process
browser.goto('https://chromedriver.storage.googleapis.com/2.33/chromedriver_win32.zip')
browser.goto('chrome://downloads')

# Navigating through the shadow DOM to find download items
download_manager = browser.element(css: 'downloads-manager')
shadow_download_manager = expand_root_element(download_manager, browser)

download_items = shadow_download_manager.elements(css: '#downloads-list downloads-item')
shadow_download_items = download_items.map { |s| expand_root_element(s, browser) }

# Locating a specific download item based on file name
expected_file = /chromedriver_win32/
download = shadow_download_items.find { |s| s.span(id: 'name').text_content =~ expected_file }

# Taking action on the download - for instance, waiting for the download to complete
download.link(id: 'show').wait_until_present

Answer №2

It has come to my attention that the monkey patch previously used is no longer effective, and I am currently unaware of a suitable workaround.

The initial issue addressed by Justin was related to a shadow dom attached to an element lacking a tag name, prompting the need for the monkey patch. However, due to recent updates, this patch is no longer functional. The primary error now manifests as a

Selenium::WebDriver::Error::JavascriptError
, necessitating an update in your rescue line to handle the correct error.

  • In addition, resolving the first error will lead to subsequent errors such as
    javascript error: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'
    . This particular issue stems from an internal API call within the wire protocol, as evidenced by the error traced back to
    selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/http/default.rb:81
    . The API call triggers an internal 500 error with an associated payload containing information about the JavaScript error encountered. Unfortunately, at present, I do not have a solution to bypass this issue.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A guide to entering information into an input field with JavaScript for logging in successfully

https://i.stack.imgur.com/TF51Z.gif https://i.stack.imgur.com/HHsax.png https://i.stack.imgur.com/HUztt.png When attempting to input text using document.getelement('').value="" , it doesn't behave as expected. The text disappear ...

Load options from server directory using PHP jQuery AJAX

I am faced with a file structure on my server that resembles the following: My query is quite complex: How can I dynamically populate <select> HTML tags from the contents of sub-files on a server? For instance, I have 3 <select> tags here tha ...

WebSocket connection established on port 8888, while the web server is running on port 80 - incompatible to merge the two services

Here is some node.js server-side code that involves watching a file and sending modifications to the browser: var app = require('http').createServer(handler) , io = require('socket.io').listen(app) , fs = require('fs') a ...

When attempting to access AJAX JSON properties using an index within a promise, the result returned is undefined

I have a quiz app that communicates with my server's API using MongoDB. I am trying to access the response indexes in this way: setTimeout(() => { axios.get('/api/ninjas') .then(function (questions) { var data = questions.d ...

Is there a way to retrieve the left offset of a floating element even when it is positioned outside the viewport?

My current situation involves creating several panels that are stacked side by side within a main container. Each panel takes up 100% of the viewport width and height. I want to be able to horizontally scroll to each panel when clicking on their respective ...

Revise Script to Duplicate Alt Attribute onto Miniatures

I'm customizing a gallery plugin for a website that I am currently developing, aiming to add support for titles. The script I am using can be found here: DEMO: http://jquery.malsup.com/cycle/pager2.html CODE: All the functionalities are in place e ...

Organize your items vertically using jQuery Mobile's list feature

I am currently working on a mini chat application. The messages in the list are appearing side by side and I would like them to be displayed one below the other. Is there a way to adjust the CSS or add classes to achieve this? <div style="height:100% ...

Control the HTML button's state according to the information received from the server

I am currently working with datatable Jquery and using an ajax call to retrieve data from the server. Let's assume that the database consists of three attributes: "Attribute1, Attribute2, Status". Depending on the Status attribute, I need to enable or ...

Pressing the button only seems to be effective if a time.sleep function is included in the

click() method in python(selenium) seems to require the use of time.sleep() in order to work properly. The main script already includes an implicit wait at the beginning, so it's puzzling why this additional wait is needed. Can anyone offer insight in ...

Utilizing unique symbols to dynamically add form elements to an HTML page with jQuery's append method

I am facing an issue with creating forms on my HTML page. Here is an example of how I am trying to do it: <form action="/tasks/<%= allTasks.e[0].id %>/delete" method="POST"> <button class="deleteTask">Delete</button> </f ...

Having trouble with submitting an Ajax form to a MySQL database

My expertise lies in PHP and HTML, but I'm currently learning JavaScript. I'm facing a challenge with creating a form that can submit data to be inserted into MySQL without reloading the page (using AJAX). Here is the form I have: <form id=" ...

JQuery Anchor Link Scrolling Problem on Specific Devices

I'm having an issue where my webpage does not scroll correctly to an anchor when a link is clicked. The problem arises from the header size changing based on the viewport width. While it works fine in desktop Chrome, in the mobile version the header h ...

Guide on extracting data from all the pages on transfermarkt with the help of selenium

from selenium import webdriver import time driver = webdriver.Firefox() f = open("superliga.csv", "w") driver.get("https://www.transfermarkt.com/") f.write("Emri,Pozicioni,Mosha,Cmimi\\n") f = open("su ...

Determining whether the selection in jQueryUI autocomplete was made using the ENTER key or not

Seeking assistance with implementing an autocomplete field using jQuery 1.7.2 and jQueryUI 1.8.12 to achieve the following: If a suggestion is chosen from the autocomplete list (via mouse or keyboard), execute function A If no matches are found (meaning ...

Mastering the Art of Utilizing $(this) in jQuery

$(".item_listing").hover(function(){ $(".overlay_items").display(); },function(){ $(".overlay_items").hide(); } ); This is my jQuery code. I am trying to display the "overlay_items" div when the "item_listing" div is hovered ov ...

Processing PHP response while waiting for jQuery AJAX call

I utilized an ajax function to transmit data. Within the PHP process, I executed phpmailer to send emails by using smtp gmail. The procedure proceeded smoothly, however, there are instances where I require informing the user to wait for the ongoing process ...

Disable Button's Shadow when it is in an active state (clicked)

Check out the DEMO to see the button animation CSS in action. The CSS code for the button animations is as follows: .btnliner { /* CSS properties */ } /* More CSS properties */ .btnliner:hover { /* Hover effects */ } Here is the corresponding J ...

The test() function in JavaScript alters the output value

I created a simple form validation, and I encountered an issue where the test() method returns true when called initially and false upon subsequent calls without changing the input value. This pattern repeats with alternating true and false results. The H ...

Is your Jquery validation malfunctioning?

I am currently facing a challenge with required validation on an asp.net page. In order to validate the inputs, I have implemented multiple controls which can be hidden or displayed based on certain conditions. These controls include checkboxlists, dropdow ...

Having trouble receiving a response from $.get method in localhost using jQuery

Attempting to send a GET request using jQuery in order to receive a dynamically determined namespace page. The index page (in Jade) contains a text input form that is being used by this script: script(src="http://code.jquery.com/jquery-1.11.1.js") script( ...