Robot Framework- Is there a way locate shadow dom objects ?

2,725 views
Skip to first unread message

Bhupesh Dahal

unread,
Jan 30, 2018, 9:11:03 AM1/30/18
to robotframework-users
I am using robotframework with python and facing issue detecting shadow dom object. Anyone knows how to locate shadow dom object ?

Ed Manlove

unread,
Jan 30, 2018, 6:52:52 PM1/30/18
to robotframe...@googlegroups.com

I have not tried myself but did a quick google search to see how people using selenium work with shadow dom elements. It looks like from the few results I read through that one uses execute javascript to get the shadow dom object, returning a webelement, and then acting on the webelement as one would any other element. As the SeleniumLibrary works both on locators as strings (i.e. id= , css= ) or locators as webelement I suspect you could run an `execute javascript` call (or possibly better `execute async javascript`) returning a webelement and then using the webelement in any other SeleniumLibrary keyword.

Ed


On 1/30/2018 9:10 AM, Bhupesh Dahal wrote:
I am using robotframework with python and facing issue detecting shadow dom object. Anyone knows how to locate shadow dom object ?
--
You received this message because you are subscribed to the Google Groups "robotframework-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to robotframework-u...@googlegroups.com.
To post to this group, send email to robotframe...@googlegroups.com.
Visit this group at https://groups.google.com/group/robotframework-users.
For more options, visit https://groups.google.com/d/optout.

Bhupesh Dahal

unread,
Feb 1, 2018, 10:04:58 AM2/1/18
to robotframework-users
Is there an example you could point me to please


On Tuesday, January 30, 2018 at 6:52:52 PM UTC-5, Ed Manlove wrote:

I have not tried myself but did a quick google search to see how people using selenium work with shadow dom elements. It looks like from the few results I read through that one uses execute javascript to get the shadow dom object, returning a webelement, and then acting on the webelement as one would any other element. As the SeleniumLibrary works both on locators as strings (i.e. id= , css= ) or locators as webelement I suspect you could run an `execute javascript` call (or possibly better `execute async javascript`) returning a webelement and then using the webelement in any other SeleniumLibrary keyword.

Ed


On 1/30/2018 9:10 AM, Bhupesh Dahal wrote:
I am using robotframework with python and facing issue detecting shadow dom object. Anyone knows how to locate shadow dom object ?
--
You received this message because you are subscribed to the Google Groups "robotframework-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to robotframework-users+unsub...@googlegroups.com.

Ed Manlove

unread,
Feb 2, 2018, 9:26:11 AM2/2/18
to robotframe...@googlegroups.com

Once again let me forewarn you that I have no experience or any substantial background knowledge on working with the shadow dom. That said I found this interesting source

http://www.seleniumeasy.com/selenium-tutorials/accessing-shadow-dom-elements-with-webdriver

which gives us a good example page to work with. That is the chrome browser's download page - chrome://downloads. Wanting to try out the concept of using execute javascript to access the shadow dom elements or elements within the shadow dom I tried out some steps using pure python and selenium first. Within the python interpreter I tired

>>> from selenium import webdriver
>>> driver=webdriver.Chrome()
>>> driver.get('chrome://downloads')
>>> dt = driver.find_element_by_tag_name('downloads-toolbar')   # expect an error here as this is an element under the shadow dom
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Sandbox\shadowdom\cl-py27-env\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 521, in find_element_by_tag_name
    return self.find_element(by=By.TAG_NAME, value=name)
  File "C:\Sandbox\shadowdom\cl-py27-env\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 955, in find_element
    'value': value})['value']
  File "C:\Sandbox\shadowdom\cl-py27-env\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 312, in execute
    self.error_handler.check_response(response)
  File "C:\Sandbox\shadowdom\cl-py27-env\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 237, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"tag name","selector":"downloads-toolbar"}
  (Session info: chrome=63.0.3239.132)
  (Driver info: chromedriver=2.35.528161 (5b82f2d2aae0ca24b877009200ced9065a772e73),platform=Windows NT 10.0.15063 x86_64)

>>> dm = driver.find_element_by_tag_name('downloads-manager')
>>> sr_dm = driver.execute_script('return arguments[0].shadowRoot',dm)
>>> dt = sr_dm.find_element_by_tag_name('downloads-toolbar')
>>> sr_dt=driver.execute_script('return arguments[0].shadowRoot',dt)
>>> sr_dt
<selenium.webdriver.remote.webelement.WebElement (session="96d1ebe53351eb96e58f1ca37ca3f576", element="0.8956248594611789-4")>
>>> cram = sr_dt.find_element_by_css_selector('dialog')
>>> cram
<selenium.webdriver.remote.webelement.WebElement (session="96d1ebe53351eb96e58f1ca37ca3f576", element="0.8956248594611789-5")>
>>> crst = sr_dt.find_element_by_css_selector('cr-toolbar')
>>> crst
<selenium.webdriver.remote.webelement.WebElement (session="96d1ebe53351eb96e58f1ca37ca3f576", element="0.8956248594611789-6")>
>>> ma = crst.find_element_by_css_selector('button')
>>> ma
<selenium.webdriver.remote.webelement.WebElement (session="96d1ebe53351eb96e58f1ca37ca3f576", element="0.8956248594611789-8")>
>>> ma.click()
>>> btns=cram.find_elements_by_css_selector('button')
>>> btns
[<selenium.webdriver.remote.webelement.WebElement (session="96d1ebe53351eb96e58f1ca37ca3f576", element="0.8956248594611789-13")>, <selenium.webdriver.remote.webelement.WebElement (session="96d1ebe53351eb96e58f1ca37ca3f576", element="0.8956248594611789-14")>]
>>> for btn in btns:
...     btn.text
...
u''
u'Open downloads folder'
>>> import unittest
>>> tc = unittest.TestCase('__init__')
>>> tc.assertEqual(btns[0].text,u'')
>>> tc.assertEqual(btns[1].text,u'Open downloads folder')
>>>

This goes through the elements, both the actual (?term for non shadow dom elements - "real") elements, clicking on the More Actions menu and the verifying the text of the menu items. There might be some extra code in there. I will say I got a little lost trying to see whether an element was a child of a shadow dom element or some other element..so it took me some back and forth with looking at the dom tree in Chrome developer tools.



So this walks us through a selenium solution. Let me take some time and convert this to Robot Framework.. will send another email shortly..

Ed
To unsubscribe from this group and stop receiving emails from it, send an email to robotframework-u...@googlegroups.com.

Ed Manlove

unread,
Feb 2, 2018, 11:45:35 AM2/2/18
to robotframe...@googlegroups.com
[Please Note: I am having some issues this morning with email/mailing
list so my response to the list may be cut/paste till I get resolved. My
apologies.   - Ed]

So here is the start of the robot framework version

*** Settings ***
Library    SeleniumLibrary

*** Test Cases ***
Verify Chrome Download More Actions... Menu Items
    [Documentation]  Demonstrate how to work with Shadow Dom elements
    [Teardown]    Close All Browsers
    Open Browser    chrome://downloads    browser=Chrome

    Log    Try to find element 'tag:downloads-toolbar' which is under a
shadow dom element and expect an error.    console=yes
    Run Keyword And Expect Error    Element with locator
'tag:downloads-toolbar' not found.
    ...  Get Web Element    tag:downloads-toolbar

    Log    Try to click on element 'id:moreActions' which is under a
shadow dom element and expect an error.    console=yes
    Run Keyword And Expect Error    Element with locator
'id:moreActions' not found.
    ...  Click Element    id:moreActions
    ${downloadToolbar}=    Set Variable  pass

    ${downloadsManager}=  Get WebElement    tag:downloads-manager
    ${downloadsManagerShadowRoot}=  Execute Javascript     return
arguments[0].shadowRoot    ${downloadsManager}

    #>>> dt = sr_dm.find_element_by_css_selector('downloads-toolbar')
    #>>> sr_dt=driver.execute_script('return arguments[0].shadowRoot',dt)
    #>>> sr_dt
    #<selenium.webdriver.remote.webelement.WebElement
(session="96d1ebe53351eb96e58f1ca37ca3f576",
element="0.8956248594611789-4")>
    #>>> cram = sr_dt.find_element_by_css_selector('dialog')
    #>>> cram
    #<selenium.webdriver.remote.webelement.WebElement
(session="96d1ebe53351eb96e58f1ca37ca3f576",
element="0.8956248594611789-5")>
    #>>> crst = sr_dt.find_element_by_css_selector('cr-toolbar')
    #>>> crst
    #<selenium.webdriver.remote.webelement.WebElement
(session="96d1ebe53351eb96e58f1ca37ca3f576",
element="0.8956248594611789-6")>
    #>>> ma = crst.find_element_by_css_selector('button')
    #>>> ma
    #<selenium.webdriver.remote.webelement.WebElement
(session="96d1ebe53351eb96e58f1ca37ca3f576",
element="0.8956248594611789-8")>
    #>>> ma.click()
    #>>> btns=cram.find_elements_by_css_selector('button')

There are a couple of issues that seem to be in the way for me
completing this. First the `Execute Javascript` keyword doesn't allow
arguments. I am searching way back in my memory bank but I do recall we
had a lengthy discussion about this in the old Selenium2Library stages.
(I still need to go back and see what was discussed and where we stood
on that issue). The second is that the `Get WebElement` doesn't yet
allow for a root element to start searching from. If you note the
selenium code, we are looking for children not of the document root but
of an element. This too had some discussion in the past that I might
need to revisit.

So where does that leave us.. well it looks like we can't do it WITH
ONLY Robot Framework and SeleniumLibrary. Since we proved it out using
pure selenium we could do a library; most likely an extension of the
SeleniumLibrary. Bhupesh Dahal, have you created a library before? It is
not a problem if you haven't but this might be the path forward.

Ed


Shiva Prasad Adirala

unread,
Nov 25, 2018, 6:41:59 AM11/25/18
to robotframe...@googlegroups.com
Using javascript we can locate elements present under shadow-root.


Recently I have gone through this scenario and I have achieved using javascript (in python) which can be used in robotframework is explained here

Note: Responding for this old thread to help others who will look into this post in future

Shiva Adirala
Reply all
Reply to author
Forward
0 new messages