Reputation: 13
This question is very similar to Selenium webdriver can't find elements at chrome://downloads
I'm trying to use Selenium with Python (3) to get at the cancel button on the chrome://downloads page. My use case is that I have an obfuscated link for which a random token is generated every time a user clicks on it. If you don't click on it, you can't start the download (it seems to fire a piece of js that generates the token, but I haven't been successful in digging through the code to figure out how that happens).
For my test to pass, all I need is to verify that:
The way that I'm trying to accomplish this is by triggering the download by clicking on the button element, then having Selenium open chrome://downloads, cancel the download, and capture the file size of the file that it attempted to download.
In theory this seems like it should work, the stumbling block is trying to access any elements in the #shadow-root tags on the chrome://downloads page. The solution to the other question which I linked above unfortunately no longer works:
driver = webdriver.Chrome("chromedriver.exe")
driver.get("chrome://downloads/")
manager = driver.find_element_by_css_selector('body/deep/downloads-manager')
item = manager.find_element_by_css_selector('body/deep/downloads-item')
shadow = driver.execute_script('return arguments[0].shadowRoot;', item)
link = shadow.find_element_by_css_selector('div#title-area>a')
file_url = link.get_attribute("href")
... as it fails on the item declaration line:
>>> item = manager.find_element_by_css_selector('body/deep/downloads-item')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 430, in find_element_by_css_selector
return self.find_element(by=By.CSS_SELECTOR, value=css_selector)
File "/usr/local/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 659, in find_element
{"using": by, "value": value})['value']
File "/usr/local/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
return self._parent.execute(command, params)
File "/usr/local/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/usr/local/lib/python3.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"body/deep/downloads-item"}
(Session info: chrome=80.0.3987.149)
This is out of my area of expertise, and any help in figuring out how to get at the cancel button would be greatly appreciated.
Upvotes: 1
Views: 2733
Reputation: 1
The previous answer by @supputuri works, however I needed to make a little modification which took hours to figure out. Here is the script that worked for me in case anyone else can't figure it out:
# navigate to chrome downloads page first
driver.get("chrome://downloads/")
driver.execute_script("document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector(\"button[id='cancel']\").click()")
The main changed part is button[id='cancel']
Upvotes: 0
Reputation: 14135
Please try the below.
driver.execute_script("document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector("cr-button[focus-type='cancel']").click()")
If you need more information how to work on the shadow-root elements, please refer here. And if you want to work on the downloads then you can refer to this and update the js as per your requirement.
Upvotes: 1