BigDaddyO Posted October 16 Posted October 16 I'm using Au3WebDriver 1.5.0 and AutoIt 3.3.14.5 I'm trying to interact with our ServiceNow page but I can only access a few top most controls. Only the first _WD_FindElement below works as it's just before the #shadow-root, everything after that can't be found _WD_Navigate($sSession, $sDirectLink) _WD_LoadWait($sSession, 5000, 30000) $eID = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "/html/body/macroponent-f51912f4c700201072b211d4d8c26010") ;This is the last item that can be found ;How to use this JS Path? document.querySelector("body > macroponent-f51912f4c700201072b211d4d8c26010").shadowRoot.querySelector("div > sn-canvas-appshell-root") $eID = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, "body > macroponent-f51912f4c700201072b211d4d8c26010 > div > sn-canvas-appshell-root") ;_WD_FindElement ==> No match [8] $eID = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, '/html/body/macroponent-f51912f4c700201072b211d4d8c26010//div/sn-canvas-appshell-root]') ;_WD_FindElement ==> Invalid Expression [11] $eID = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "/html/body/macroponent-f51912f4c700201072b211d4d8c26010/./div/sn-canvas-appshell-root") ;trying . in the blank selector spot. _WD_FindElement ==> No match [8] The actual controls I want are stored under MANY nested #shadow-root (Open) items that can't be found. Each find just returns "_WD_FindElement ==> No match [8]" When I copied the JS Path from the Edge Inspect, that at least shows the .shadowRoot but I don't know how to use this JS Path as part of the _WD_FindElement? document.querySelector("body > macroponent-f51912f4c700201072b211d4d8c26010").shadowRoot.querySelector("div > sn-canvas-appshell-root")
LRX Posted 2 hours ago Posted 2 hours ago The selectors fail because XPath and CSS can’t cross a #shadow-root boundary. Each shadow root is a separate DOM tree, so macroponent... > div > sn-canvas-appshell-root is never a valid path from the document. You have to enter each shadow root one at a time and search inside it. Inside a shadow root, only CSS selectors work. XPath is rejected there, so stick to $_WD_LOCATOR_ByCSSSelector. (Your second XPath also has a stray ] at the end, which is why you got “Invalid Expression”.) Au3WebDriver 1.5.0 supports this directly: 1. Step through each shadow root ; Get the shadow root of the macroponent host Local $sRoot1 = _WD_GetShadowRoot($sSession, $_WD_LOCATOR_ByCSSSelector, "body > macroponent-f51912f4c700201072b211d4d8c26010") ; Search INSIDE that shadow root (last param $bShadowRoot = True) Local $eApp = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, "sn-canvas-appshell-root", $sRoot1, False, True) ; Next level: get that element's shadow root, then search inside it Local $sRoot2 = _WD_ElementAction($sSession, $eApp, 'shadow') Local $eLayout = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, "sn-canvas-appshell-layout", $sRoot2, False, True) ; ...and so on 2. A helper so you don’t repeat this a dozen times ; Each array item is a CSS selector run inside the current shadow root. ; Every item except the last is a shadow host: the function enters its shadow root. Func _WD_FindInShadowPath($sSession, $aPath) Local $sContext = Default, $bShadow = False, $sElem For $i = 0 To UBound($aPath) - 1 $sElem = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, $aPath[$i], $sContext, False, $bShadow) If @error Then Return SetError(@error, $i, "") ; @extended = which step failed If $i = UBound($aPath) - 1 Then Return $sElem $sContext = _WD_ElementAction($sSession, $sElem, 'shadow') If @error Or $sContext = "" Then Return SetError(9, $i, "") $bShadow = True Next EndFunc ; Usage Local $aPath[] = [ _ "body > macroponent-f51912f4c700201072b211d4d8c26010", _ "sn-canvas-appshell-root", _ "sn-canvas-appshell-layout sn-polaris-layout", _ "your-next-host", _ "#theControlYouWant" ] Local $eTarget = _WD_FindInShadowPath($sSession, $aPath) If @error Then ConsoleWrite("Failed at step " & @extended & @CRLF) Look at sn-canvas-appshell-layout sn-polaris-layout in that list. In your screenshot, sn-polaris-layout has a slot badge. That means it’s a regular child of sn-canvas-appshell-layout, not inside that element’s shadow root. A plain descendant selector in the same step finds it, so you don’t enter a shadow root there. Only add a new array item where the inspector shows a new #shadow-root. 3. Or use the JS Path you copied from Edge You can run the JS Path as-is and ask for the element back: Local $sJS = 'return document.querySelector("body > macroponent-f51912f4c700201072b211d4d8c26010")' & _ '.shadowRoot.querySelector("div > sn-canvas-appshell-root")' Local $eID = _WD_ExecuteScript($sSession, $sJS, Default, Default, $_WD_JSON_Element) $eID is a normal element ID, so you can use it with _WD_ElementAction, _WD_ElementActionEx, and so on. This is often the quickest route: copy the JS Path for the actual control from Edge, prefix it with return , and you’re done. The downside is that it’s tied to that exact structure, so it breaks when ServiceNow updates its UI. ServiceNow tips that may save you all of this Classic forms run inside an iframe. In the Next Experience (Polaris) UI, list and form pages (incident.do, etc.) load in iframe#gsft_main, which sits deep in the shadow tree. Find the iframe with one of the methods above, then call _WD_FrameEnter($sSession, $eIframe). Inside the frame it’s a normal DOM, and your usual XPath works again. Skip the shell entirely. If your target is a classic form, navigate straight to it, e.g. https://yourinstance.service-now.com/incident.do?sys_id=..., instead of a /now/nav/ui/classic/params/target/... link. That page has no Polaris wrapper and no shadow roots, so _WD_FindElement with XPath works directly. The macroponent-f51912... tag is tied to the page definition. If it ever changes, body > * or body > [component-id] is a more stable first selector.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now